linux/drivers/scsi/osst.c
<<
>>
Prefs
   1/*
   2  SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying
   3  file Documentation/scsi/st.txt for more information.
   4
   5  History:
   6
   7  OnStream SCSI Tape support (osst) cloned from st.c by
   8  Willem Riede (osst@riede.org) Feb 2000
   9  Fixes ... Kurt Garloff <garloff@suse.de> Mar 2000
  10
  11  Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
  12  Contribution and ideas from several people including (in alphabetical
  13  order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
  14  Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
  15
  16  Copyright 1992 - 2002 Kai Makisara / 2000 - 2006 Willem Riede
  17         email osst@riede.org
  18
  19  $Header: /cvsroot/osst/Driver/osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $
  20
  21  Microscopic alterations - Rik Ling, 2000/12/21
  22  Last st.c sync: Tue Oct 15 22:01:04 2002 by makisara
  23  Some small formal changes - aeb, 950809
  24*/
  25
  26static const char * cvsid = "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
  27static const char * osst_version = "0.99.4";
  28
  29/* The "failure to reconnect" firmware bug */
  30#define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
  31#define OSST_FW_NEED_POLL_MAX 10704 /*(108D)*/
  32#define OSST_FW_NEED_POLL(x,d) ((x) >= OSST_FW_NEED_POLL_MIN && (x) <= OSST_FW_NEED_POLL_MAX && d->host->this_id != 7)
  33
  34#include <linux/module.h>
  35
  36#include <linux/fs.h>
  37#include <linux/kernel.h>
  38#include <linux/sched.h>
  39#include <linux/proc_fs.h>
  40#include <linux/mm.h>
  41#include <linux/init.h>
  42#include <linux/string.h>
  43#include <linux/errno.h>
  44#include <linux/mtio.h>
  45#include <linux/ioctl.h>
  46#include <linux/fcntl.h>
  47#include <linux/spinlock.h>
  48#include <linux/vmalloc.h>
  49#include <linux/blkdev.h>
  50#include <linux/moduleparam.h>
  51#include <linux/delay.h>
  52#include <linux/jiffies.h>
  53#include <linux/smp_lock.h>
  54#include <asm/uaccess.h>
  55#include <asm/dma.h>
  56#include <asm/system.h>
  57
  58/* The driver prints some debugging information on the console if DEBUG
  59   is defined and non-zero. */
  60#define DEBUG 0
  61
  62/* The message level for the debug messages is currently set to KERN_NOTICE
  63   so that people can easily see the messages. Later when the debugging messages
  64   in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
  65#define OSST_DEB_MSG  KERN_NOTICE
  66
  67#include <scsi/scsi.h>
  68#include <scsi/scsi_dbg.h>
  69#include <scsi/scsi_device.h>
  70#include <scsi/scsi_driver.h>
  71#include <scsi/scsi_eh.h>
  72#include <scsi/scsi_host.h>
  73#include <scsi/scsi_ioctl.h>
  74
  75#define ST_KILOBYTE 1024
  76
  77#include "st.h"
  78#include "osst.h"
  79#include "osst_options.h"
  80#include "osst_detect.h"
  81
  82static int max_dev = 0;
  83static int write_threshold_kbs = 0;
  84static int max_sg_segs = 0;
  85
  86#ifdef MODULE
  87MODULE_AUTHOR("Willem Riede");
  88MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
  89MODULE_LICENSE("GPL");
  90MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR);
  91MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
  92
  93module_param(max_dev, int, 0444);
  94MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
  95
  96module_param(write_threshold_kbs, int, 0644);
  97MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
  98
  99module_param(max_sg_segs, int, 0644);
 100MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
 101#else
 102static struct osst_dev_parm {
 103       char   *name;
 104       int    *val;
 105} parms[] __initdata = {
 106       { "max_dev",             &max_dev             },
 107       { "write_threshold_kbs", &write_threshold_kbs },
 108       { "max_sg_segs",         &max_sg_segs         }
 109};
 110#endif
 111
 112/* Some default definitions have been moved to osst_options.h */
 113#define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
 114#define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
 115
 116/* The buffer size should fit into the 24 bits for length in the
 117   6-byte SCSI read and write commands. */
 118#if OSST_BUFFER_SIZE >= (2 << 24 - 1)
 119#error "Buffer size should not exceed (2 << 24 - 1) bytes!"
 120#endif
 121
 122#if DEBUG
 123static int debugging = 1;
 124/* uncomment define below to test error recovery */
 125// #define OSST_INJECT_ERRORS 1 
 126#endif
 127
 128/* Do not retry! The drive firmware already retries when appropriate,
 129   and when it tries to tell us something, we had better listen... */
 130#define MAX_RETRIES 0
 131
 132#define NO_TAPE  NOT_READY
 133
 134#define OSST_WAIT_POSITION_COMPLETE   (HZ > 200 ? HZ / 200 : 1)
 135#define OSST_WAIT_WRITE_COMPLETE      (HZ / 12)
 136#define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
 137        
 138#define OSST_TIMEOUT (200 * HZ)
 139#define OSST_LONG_TIMEOUT (1800 * HZ)
 140
 141#define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
 142#define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
 143#define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
 144#define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
 145
 146/* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
 147   24 bits) */
 148#define SET_DENS_AND_BLK 0x10001
 149
 150static int osst_buffer_size       = OSST_BUFFER_SIZE;
 151static int osst_write_threshold   = OSST_WRITE_THRESHOLD;
 152static int osst_max_sg_segs       = OSST_MAX_SG;
 153static int osst_max_dev           = OSST_MAX_TAPES;
 154static int osst_nr_dev;
 155
 156static struct osst_tape **os_scsi_tapes = NULL;
 157static DEFINE_RWLOCK(os_scsi_tapes_lock);
 158
 159static int modes_defined = 0;
 160
 161static struct osst_buffer *new_tape_buffer(int, int, int);
 162static int enlarge_buffer(struct osst_buffer *, int);
 163static void normalize_buffer(struct osst_buffer *);
 164static int append_to_buffer(const char __user *, struct osst_buffer *, int);
 165static int from_buffer(struct osst_buffer *, char __user *, int);
 166static int osst_zero_buffer_tail(struct osst_buffer *);
 167static int osst_copy_to_buffer(struct osst_buffer *, unsigned char *);
 168static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
 169
 170static int osst_probe(struct device *);
 171static int osst_remove(struct device *);
 172
 173static struct scsi_driver osst_template = {
 174        .owner                  = THIS_MODULE,
 175        .gendrv = {
 176                .name           =  "osst",
 177                .probe          = osst_probe,
 178                .remove         = osst_remove,
 179        }
 180};
 181
 182static int osst_int_ioctl(struct osst_tape *STp, struct osst_request ** aSRpnt,
 183                            unsigned int cmd_in, unsigned long arg);
 184
 185static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int frame, int skip);
 186
 187static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt);
 188
 189static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt);
 190
 191static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending);
 192
 193static inline char *tape_name(struct osst_tape *tape)
 194{
 195        return tape->drive->disk_name;
 196}
 197
 198/* Routines that handle the interaction with mid-layer SCSI routines */
 199
 200
 201/* Normalize Sense */
 202static void osst_analyze_sense(struct osst_request *SRpnt, struct st_cmdstatus *s)
 203{
 204        const u8 *ucp;
 205        const u8 *sense = SRpnt->sense;
 206
 207        s->have_sense = scsi_normalize_sense(SRpnt->sense,
 208                                SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
 209        s->flags = 0;
 210
 211        if (s->have_sense) {
 212                s->deferred = 0;
 213                s->remainder_valid =
 214                        scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64);
 215                switch (sense[0] & 0x7f) {
 216                case 0x71:
 217                        s->deferred = 1;
 218                case 0x70:
 219                        s->fixed_format = 1;
 220                        s->flags = sense[2] & 0xe0;
 221                        break;
 222                case 0x73:
 223                        s->deferred = 1;
 224                case 0x72:
 225                        s->fixed_format = 0;
 226                        ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
 227                        s->flags = ucp ? (ucp[3] & 0xe0) : 0;
 228                        break;
 229                }
 230        }
 231}
 232
 233/* Convert the result to success code */
 234static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
 235{
 236        char *name = tape_name(STp);
 237        int result = SRpnt->result;
 238        u8 * sense = SRpnt->sense, scode;
 239#if DEBUG
 240        const char *stp;
 241#endif
 242        struct st_cmdstatus *cmdstatp;
 243
 244        if (!result)
 245                return 0;
 246
 247        cmdstatp = &STp->buffer->cmdstat;
 248        osst_analyze_sense(SRpnt, cmdstatp);
 249
 250        if (cmdstatp->have_sense)
 251                scode = STp->buffer->cmdstat.sense_hdr.sense_key;
 252        else
 253                scode = 0;
 254#if DEBUG
 255        if (debugging) {
 256                printk(OSST_DEB_MSG "%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
 257                   name, result,
 258                   SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
 259                   SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
 260                if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
 261                                name, scode, sense[12], sense[13]);
 262                if (cmdstatp->have_sense)
 263                        __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
 264        }
 265        else
 266#endif
 267        if (cmdstatp->have_sense && (
 268                 scode != NO_SENSE &&
 269                 scode != RECOVERED_ERROR &&
 270/*               scode != UNIT_ATTENTION && */
 271                 scode != BLANK_CHECK &&
 272                 scode != VOLUME_OVERFLOW &&
 273                 SRpnt->cmd[0] != MODE_SENSE &&
 274                 SRpnt->cmd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
 275                if (cmdstatp->have_sense) {
 276                        printk(KERN_WARNING "%s:W: Command with sense data:\n", name);
 277                        __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
 278                }
 279                else {
 280                        static  int     notyetprinted = 1;
 281
 282                        printk(KERN_WARNING
 283                             "%s:W: Warning %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
 284                             name, result, suggestion(result), driver_byte(result) & DRIVER_MASK,
 285                             host_byte(result));
 286                        if (notyetprinted) {
 287                                notyetprinted = 0;
 288                                printk(KERN_INFO
 289                                        "%s:I: This warning may be caused by your scsi controller,\n", name);
 290                                printk(KERN_INFO
 291                                        "%s:I: it has been reported with some Buslogic cards.\n", name);
 292                        }
 293                }
 294        }
 295        STp->pos_unknown |= STp->device->was_reset;
 296
 297        if (cmdstatp->have_sense && scode == RECOVERED_ERROR) {
 298                STp->recover_count++;
 299                STp->recover_erreg++;
 300#if DEBUG
 301                if (debugging) {
 302                        if (SRpnt->cmd[0] == READ_6)
 303                                stp = "read";
 304                        else if (SRpnt->cmd[0] == WRITE_6)
 305                                stp = "write";
 306                        else
 307                                stp = "ioctl";
 308                        printk(OSST_DEB_MSG "%s:D: Recovered %s error (%d).\n", name, stp,
 309                                             STp->recover_count);
 310                }
 311#endif
 312                if ((sense[2] & 0xe0) == 0)
 313                        return 0;
 314        }
 315        return (-EIO);
 316}
 317
 318
 319/* Wakeup from interrupt */
 320static void osst_sleep_done(void *data, char *sense, int result, int resid)
 321{
 322        struct osst_request *SRpnt = data;
 323        struct osst_tape *STp = SRpnt->stp;
 324
 325        memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE);
 326        STp->buffer->cmdstat.midlevel_result = SRpnt->result = result;
 327#if DEBUG
 328        STp->write_pending = 0;
 329#endif
 330        if (SRpnt->waiting)
 331                complete(SRpnt->waiting);
 332}
 333
 334/* osst_request memory management */
 335static struct osst_request *osst_allocate_request(void)
 336{
 337        return kzalloc(sizeof(struct osst_request), GFP_KERNEL);
 338}
 339
 340static void osst_release_request(struct osst_request *streq)
 341{
 342        kfree(streq);
 343}
 344
 345/* Do the scsi command. Waits until command performed if do_wait is true.
 346   Otherwise osst_write_behind_check() is used to check that the command
 347   has finished. */
 348static  struct osst_request * osst_do_scsi(struct osst_request *SRpnt, struct osst_tape *STp, 
 349        unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
 350{
 351        unsigned char *bp;
 352        unsigned short use_sg;
 353#ifdef OSST_INJECT_ERRORS
 354        static   int   inject = 0;
 355        static   int   repeat = 0;
 356#endif
 357        struct completion *waiting;
 358
 359        /* if async, make sure there's no command outstanding */
 360        if (!do_wait && ((STp->buffer)->last_SRpnt)) {
 361                printk(KERN_ERR "%s: Async command already active.\n",
 362                       tape_name(STp));
 363                if (signal_pending(current))
 364                        (STp->buffer)->syscall_result = (-EINTR);
 365                else
 366                        (STp->buffer)->syscall_result = (-EBUSY);
 367                return NULL;
 368        }
 369
 370        if (SRpnt == NULL) {
 371                SRpnt = osst_allocate_request();
 372                if (SRpnt == NULL) {
 373                        printk(KERN_ERR "%s: Can't allocate SCSI request.\n",
 374                                     tape_name(STp));
 375                        if (signal_pending(current))
 376                                (STp->buffer)->syscall_result = (-EINTR);
 377                        else
 378                                (STp->buffer)->syscall_result = (-EBUSY);
 379                        return NULL;
 380                }
 381                SRpnt->stp = STp;
 382        }
 383
 384        /* If async IO, set last_SRpnt. This ptr tells write_behind_check
 385           which IO is outstanding. It's nulled out when the IO completes. */
 386        if (!do_wait)
 387                (STp->buffer)->last_SRpnt = SRpnt;
 388
 389        waiting = &STp->wait;
 390        init_completion(waiting);
 391        SRpnt->waiting = waiting;
 392
 393        use_sg = (bytes > STp->buffer->sg[0].length) ? STp->buffer->use_sg : 0;
 394        if (use_sg) {
 395                bp = (char *)&(STp->buffer->sg[0]);
 396                if (STp->buffer->sg_segs < use_sg)
 397                        use_sg = STp->buffer->sg_segs;
 398        }
 399        else
 400                bp = (STp->buffer)->b_data;
 401
 402        memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
 403        STp->buffer->cmdstat.have_sense = 0;
 404        STp->buffer->syscall_result = 0;
 405
 406        if (scsi_execute_async(STp->device, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes,
 407                        use_sg, timeout, retries, SRpnt, osst_sleep_done, GFP_KERNEL))
 408                /* could not allocate the buffer or request was too large */
 409                (STp->buffer)->syscall_result = (-EBUSY);
 410        else if (do_wait) {
 411                wait_for_completion(waiting);
 412                SRpnt->waiting = NULL;
 413                STp->buffer->syscall_result = osst_chk_result(STp, SRpnt);
 414#ifdef OSST_INJECT_ERRORS
 415                if (STp->buffer->syscall_result == 0 &&
 416                    cmd[0] == READ_6 &&
 417                    cmd[4] && 
 418                    ( (++ inject % 83) == 29  ||
 419                      (STp->first_frame_position == 240 
 420                                 /* or STp->read_error_frame to fail again on the block calculated above */ &&
 421                                 ++repeat < 3))) {
 422                        printk(OSST_DEB_MSG "%s:D: Injecting read error\n", tape_name(STp));
 423                        STp->buffer->last_result_fatal = 1;
 424                }
 425#endif
 426        }
 427        return SRpnt;
 428}
 429
 430
 431/* Handle the write-behind checking (downs the semaphore) */
 432static void osst_write_behind_check(struct osst_tape *STp)
 433{
 434        struct osst_buffer * STbuffer;
 435
 436        STbuffer = STp->buffer;
 437
 438#if DEBUG
 439        if (STp->write_pending)
 440                STp->nbr_waits++;
 441        else
 442                STp->nbr_finished++;
 443#endif
 444        wait_for_completion(&(STp->wait));
 445        STp->buffer->last_SRpnt->waiting = NULL;
 446
 447        STp->buffer->syscall_result = osst_chk_result(STp, STp->buffer->last_SRpnt);
 448
 449        if (STp->buffer->syscall_result)
 450                STp->buffer->syscall_result =
 451                        osst_write_error_recovery(STp, &(STp->buffer->last_SRpnt), 1);
 452        else
 453                STp->first_frame_position++;
 454
 455        osst_release_request(STp->buffer->last_SRpnt);
 456
 457        if (STbuffer->writing < STbuffer->buffer_bytes)
 458                printk(KERN_WARNING "osst :A: write_behind_check: something left in buffer!\n");
 459
 460        STbuffer->last_SRpnt = NULL;
 461        STbuffer->buffer_bytes -= STbuffer->writing;
 462        STbuffer->writing = 0;
 463
 464        return;
 465}
 466
 467
 468
 469/* Onstream specific Routines */
 470/*
 471 * Initialize the OnStream AUX
 472 */
 473static void osst_init_aux(struct osst_tape * STp, int frame_type, int frame_seq_number,
 474                                         int logical_blk_num, int blk_sz, int blk_cnt)
 475{
 476        os_aux_t       *aux = STp->buffer->aux;
 477        os_partition_t *par = &aux->partition;
 478        os_dat_t       *dat = &aux->dat;
 479
 480        if (STp->raw) return;
 481
 482        memset(aux, 0, sizeof(*aux));
 483        aux->format_id = htonl(0);
 484        memcpy(aux->application_sig, "LIN4", 4);
 485        aux->hdwr = htonl(0);
 486        aux->frame_type = frame_type;
 487
 488        switch (frame_type) {
 489          case  OS_FRAME_TYPE_HEADER:
 490                aux->update_frame_cntr    = htonl(STp->update_frame_cntr);
 491                par->partition_num        = OS_CONFIG_PARTITION;
 492                par->par_desc_ver         = OS_PARTITION_VERSION;
 493                par->wrt_pass_cntr        = htons(0xffff);
 494                /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
 495                par->first_frame_ppos     = htonl(0);
 496                par->last_frame_ppos      = htonl(0xbb7);
 497                aux->frame_seq_num        = htonl(0);
 498                aux->logical_blk_num_high = htonl(0);
 499                aux->logical_blk_num      = htonl(0);
 500                aux->next_mark_ppos       = htonl(STp->first_mark_ppos);
 501                break;
 502          case  OS_FRAME_TYPE_DATA:
 503          case  OS_FRAME_TYPE_MARKER:
 504                dat->dat_sz = 8;
 505                dat->reserved1 = 0;
 506                dat->entry_cnt = 1;
 507                dat->reserved3 = 0;
 508                dat->dat_list[0].blk_sz   = htonl(blk_sz);
 509                dat->dat_list[0].blk_cnt  = htons(blk_cnt);
 510                dat->dat_list[0].flags    = frame_type==OS_FRAME_TYPE_MARKER?
 511                                                        OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA;
 512                dat->dat_list[0].reserved = 0;
 513          case  OS_FRAME_TYPE_EOD:
 514                aux->update_frame_cntr    = htonl(0);
 515                par->partition_num        = OS_DATA_PARTITION;
 516                par->par_desc_ver         = OS_PARTITION_VERSION;
 517                par->wrt_pass_cntr        = htons(STp->wrt_pass_cntr);
 518                par->first_frame_ppos     = htonl(STp->first_data_ppos);
 519                par->last_frame_ppos      = htonl(STp->capacity);
 520                aux->frame_seq_num        = htonl(frame_seq_number);
 521                aux->logical_blk_num_high = htonl(0);
 522                aux->logical_blk_num      = htonl(logical_blk_num);
 523                break;
 524          default: ; /* probably FILL */
 525        }
 526        aux->filemark_cnt = htonl(STp->filemark_cnt);
 527        aux->phys_fm = htonl(0xffffffff);
 528        aux->last_mark_ppos = htonl(STp->last_mark_ppos);
 529        aux->last_mark_lbn  = htonl(STp->last_mark_lbn);
 530}
 531
 532/*
 533 * Verify that we have the correct tape frame
 534 */
 535static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int quiet)
 536{
 537        char               * name = tape_name(STp);
 538        os_aux_t           * aux  = STp->buffer->aux;
 539        os_partition_t     * par  = &(aux->partition);
 540        struct st_partstat * STps = &(STp->ps[STp->partition]);
 541        int                  blk_cnt, blk_sz, i;
 542
 543        if (STp->raw) {
 544                if (STp->buffer->syscall_result) {
 545                        for (i=0; i < STp->buffer->sg_segs; i++)
 546                                memset(page_address(sg_page(&STp->buffer->sg[i])),
 547                                       0, STp->buffer->sg[i].length);
 548                        strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
 549                } else
 550                        STp->buffer->buffer_bytes = OS_FRAME_SIZE;
 551                return 1;
 552        }
 553        if (STp->buffer->syscall_result) {
 554#if DEBUG
 555                printk(OSST_DEB_MSG "%s:D: Skipping frame, read error\n", name);
 556#endif
 557                return 0;
 558        }
 559        if (ntohl(aux->format_id) != 0) {
 560#if DEBUG
 561                printk(OSST_DEB_MSG "%s:D: Skipping frame, format_id %u\n", name, ntohl(aux->format_id));
 562#endif
 563                goto err_out;
 564        }
 565        if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 &&
 566            (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) {
 567#if DEBUG
 568                printk(OSST_DEB_MSG "%s:D: Skipping frame, incorrect application signature\n", name);
 569#endif
 570                goto err_out;
 571        }
 572        if (par->partition_num != OS_DATA_PARTITION) {
 573                if (!STp->linux_media || STp->linux_media_version != 2) {
 574#if DEBUG
 575                        printk(OSST_DEB_MSG "%s:D: Skipping frame, partition num %d\n",
 576                                            name, par->partition_num);
 577#endif
 578                        goto err_out;
 579                }
 580        }
 581        if (par->par_desc_ver != OS_PARTITION_VERSION) {
 582#if DEBUG
 583                printk(OSST_DEB_MSG "%s:D: Skipping frame, partition version %d\n", name, par->par_desc_ver);
 584#endif
 585                goto err_out;
 586        }
 587        if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) {
 588#if DEBUG
 589                printk(OSST_DEB_MSG "%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n", 
 590                                    name, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr);
 591#endif
 592                goto err_out;
 593        }
 594        if (aux->frame_type != OS_FRAME_TYPE_DATA &&
 595            aux->frame_type != OS_FRAME_TYPE_EOD &&
 596            aux->frame_type != OS_FRAME_TYPE_MARKER) {
 597                if (!quiet) {
 598#if DEBUG
 599                        printk(OSST_DEB_MSG "%s:D: Skipping frame, frame type %x\n", name, aux->frame_type);
 600#endif
 601                }
 602                goto err_out;
 603        }
 604        if (aux->frame_type == OS_FRAME_TYPE_EOD &&
 605            STp->first_frame_position < STp->eod_frame_ppos) {
 606                printk(KERN_INFO "%s:I: Skipping premature EOD frame %d\n", name,
 607                                 STp->first_frame_position);
 608                goto err_out;
 609        }
 610        if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
 611                if (!quiet) {
 612#if DEBUG
 613                        printk(OSST_DEB_MSG "%s:D: Skipping frame, sequence number %u (expected %d)\n", 
 614                                            name, ntohl(aux->frame_seq_num), frame_seq_number);
 615#endif
 616                }
 617                goto err_out;
 618        }
 619        if (aux->frame_type == OS_FRAME_TYPE_MARKER) {
 620                STps->eof = ST_FM_HIT;
 621
 622                i = ntohl(aux->filemark_cnt);
 623                if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt ||
 624                    STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) {
 625#if DEBUG
 626                        printk(OSST_DEB_MSG "%s:D: %s filemark %d at frame pos %d\n", name,
 627                                  STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected",
 628                                  i, STp->first_frame_position - 1);
 629#endif
 630                        STp->header_cache->dat_fm_tab.fm_tab_ent[i] = htonl(STp->first_frame_position - 1);
 631                        if (i >= STp->filemark_cnt)
 632                                 STp->filemark_cnt = i+1;
 633                }
 634        }
 635        if (aux->frame_type == OS_FRAME_TYPE_EOD) {
 636                STps->eof = ST_EOD_1;
 637                STp->frame_in_buffer = 1;
 638        }
 639        if (aux->frame_type == OS_FRAME_TYPE_DATA) {
 640                blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt);
 641                blk_sz  = ntohl(aux->dat.dat_list[0].blk_sz);
 642                STp->buffer->buffer_bytes = blk_cnt * blk_sz;
 643                STp->buffer->read_pointer = 0;
 644                STp->frame_in_buffer = 1;
 645
 646                /* See what block size was used to write file */
 647                if (STp->block_size != blk_sz && blk_sz > 0) {
 648                        printk(KERN_INFO
 649                "%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
 650                                name, blk_sz<1024?blk_sz:blk_sz/1024,blk_sz<1024?'b':'k',
 651                                STp->block_size<1024?STp->block_size:STp->block_size/1024,
 652                                STp->block_size<1024?'b':'k');
 653                        STp->block_size            = blk_sz;
 654                        STp->buffer->buffer_blocks = OS_DATA_SIZE / blk_sz;
 655                }
 656                STps->eof = ST_NOEOF;
 657        }
 658        STp->frame_seq_number = ntohl(aux->frame_seq_num);
 659        STp->logical_blk_num  = ntohl(aux->logical_blk_num);
 660        return 1;
 661
 662err_out:
 663        if (STp->read_error_frame == 0)
 664                STp->read_error_frame = STp->first_frame_position - 1;
 665        return 0;
 666}
 667
 668/*
 669 * Wait for the unit to become Ready
 670 */
 671static int osst_wait_ready(struct osst_tape * STp, struct osst_request ** aSRpnt,
 672                                 unsigned timeout, int initial_delay)
 673{
 674        unsigned char           cmd[MAX_COMMAND_SIZE];
 675        struct osst_request   * SRpnt;
 676        unsigned long           startwait = jiffies;
 677#if DEBUG
 678        int                     dbg  = debugging;
 679        char                  * name = tape_name(STp);
 680
 681        printk(OSST_DEB_MSG "%s:D: Reached onstream wait ready\n", name);
 682#endif
 683
 684        if (initial_delay > 0)
 685                msleep(jiffies_to_msecs(initial_delay));
 686
 687        memset(cmd, 0, MAX_COMMAND_SIZE);
 688        cmd[0] = TEST_UNIT_READY;
 689
 690        SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 691        *aSRpnt = SRpnt;
 692        if (!SRpnt) return (-EBUSY);
 693
 694        while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
 695               (( SRpnt->sense[2]  == 2 && SRpnt->sense[12] == 4    &&
 696                 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)    ) ||
 697                ( SRpnt->sense[2]  == 6 && SRpnt->sense[12] == 0x28 &&
 698                  SRpnt->sense[13] == 0                                        )  )) {
 699#if DEBUG
 700            if (debugging) {
 701                printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait ready\n", name);
 702                printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
 703                debugging = 0;
 704            }
 705#endif
 706            msleep(100);
 707
 708            memset(cmd, 0, MAX_COMMAND_SIZE);
 709            cmd[0] = TEST_UNIT_READY;
 710
 711            SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 712        }
 713        *aSRpnt = SRpnt;
 714#if DEBUG
 715        debugging = dbg;
 716#endif
 717        if ( STp->buffer->syscall_result &&
 718             osst_write_error_recovery(STp, aSRpnt, 0) ) {
 719#if DEBUG
 720            printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait ready\n", name);
 721            printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
 722                        STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
 723                        SRpnt->sense[12], SRpnt->sense[13]);
 724#endif
 725            return (-EIO);
 726        }
 727#if DEBUG
 728        printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait ready\n", name);
 729#endif
 730        return 0;
 731}
 732
 733/*
 734 * Wait for a tape to be inserted in the unit
 735 */
 736static int osst_wait_for_medium(struct osst_tape * STp, struct osst_request ** aSRpnt, unsigned timeout)
 737{
 738        unsigned char           cmd[MAX_COMMAND_SIZE];
 739        struct osst_request   * SRpnt;
 740        unsigned long           startwait = jiffies;
 741#if DEBUG
 742        int                     dbg = debugging;
 743        char                  * name = tape_name(STp);
 744
 745        printk(OSST_DEB_MSG "%s:D: Reached onstream wait for medium\n", name);
 746#endif
 747
 748        memset(cmd, 0, MAX_COMMAND_SIZE);
 749        cmd[0] = TEST_UNIT_READY;
 750
 751        SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 752        *aSRpnt = SRpnt;
 753        if (!SRpnt) return (-EBUSY);
 754
 755        while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
 756                SRpnt->sense[2] == 2 && SRpnt->sense[12] == 0x3a && SRpnt->sense[13] == 0  ) {
 757#if DEBUG
 758            if (debugging) {
 759                printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait medium\n", name);
 760                printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
 761                debugging = 0;
 762            }
 763#endif
 764            msleep(100);
 765
 766            memset(cmd, 0, MAX_COMMAND_SIZE);
 767            cmd[0] = TEST_UNIT_READY;
 768
 769            SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 770        }
 771        *aSRpnt = SRpnt;
 772#if DEBUG
 773        debugging = dbg;
 774#endif
 775        if ( STp->buffer->syscall_result     && SRpnt->sense[2]  != 2 &&
 776             SRpnt->sense[12] != 4 && SRpnt->sense[13] == 1) {
 777#if DEBUG
 778            printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait medium\n", name);
 779            printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
 780                        STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
 781                        SRpnt->sense[12], SRpnt->sense[13]);
 782#endif
 783            return 0;
 784        }
 785#if DEBUG
 786        printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait medium\n", name);
 787#endif
 788        return 1;
 789}
 790
 791static int osst_position_tape_and_confirm(struct osst_tape * STp, struct osst_request ** aSRpnt, int frame)
 792{
 793        int     retval;
 794
 795        osst_wait_ready(STp, aSRpnt, 15 * 60, 0);                       /* TODO - can this catch a write error? */
 796        retval = osst_set_frame_position(STp, aSRpnt, frame, 0);
 797        if (retval) return (retval);
 798        osst_wait_ready(STp, aSRpnt, 15 * 60, OSST_WAIT_POSITION_COMPLETE);
 799        return (osst_get_frame_position(STp, aSRpnt));
 800}
 801
 802/*
 803 * Wait for write(s) to complete
 804 */
 805static int osst_flush_drive_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt)
 806{
 807        unsigned char           cmd[MAX_COMMAND_SIZE];
 808        struct osst_request   * SRpnt;
 809        int                     result = 0;
 810        int                     delay  = OSST_WAIT_WRITE_COMPLETE;
 811#if DEBUG
 812        char                  * name = tape_name(STp);
 813
 814        printk(OSST_DEB_MSG "%s:D: Reached onstream flush drive buffer (write filemark)\n", name);
 815#endif
 816
 817        memset(cmd, 0, MAX_COMMAND_SIZE);
 818        cmd[0] = WRITE_FILEMARKS;
 819        cmd[1] = 1;
 820
 821        SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
 822        *aSRpnt = SRpnt;
 823        if (!SRpnt) return (-EBUSY);
 824        if (STp->buffer->syscall_result) {
 825                if ((SRpnt->sense[2] & 0x0f) == 2 && SRpnt->sense[12] == 4) {
 826                        if (SRpnt->sense[13] == 8) {
 827                                delay = OSST_WAIT_LONG_WRITE_COMPLETE;
 828                        }
 829                } else
 830                        result = osst_write_error_recovery(STp, aSRpnt, 0);
 831        }
 832        result |= osst_wait_ready(STp, aSRpnt, 5 * 60, delay);
 833        STp->ps[STp->partition].rw = OS_WRITING_COMPLETE;
 834
 835        return (result);
 836}
 837
 838#define OSST_POLL_PER_SEC 10
 839static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int curr, int minlast, int to)
 840{
 841        unsigned long   startwait = jiffies;
 842        char          * name      = tape_name(STp);
 843#if DEBUG
 844        char       notyetprinted  = 1;
 845#endif
 846        if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
 847                printk(KERN_ERR "%s:A: Waiting for frame without having initialized read!\n", name);
 848
 849        while (time_before (jiffies, startwait + to*HZ))
 850        { 
 851                int result;
 852                result = osst_get_frame_position(STp, aSRpnt);
 853                if (result == -EIO)
 854                        if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
 855                                return 0;       /* successful recovery leaves drive ready for frame */
 856                if (result < 0) break;
 857                if (STp->first_frame_position == curr &&
 858                    ((minlast < 0 &&
 859                      (signed)STp->last_frame_position > (signed)curr + minlast) ||
 860                     (minlast >= 0 && STp->cur_frames > minlast)
 861                    ) && result >= 0)
 862                {
 863#if DEBUG                       
 864                        if (debugging || time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC))
 865                                printk (OSST_DEB_MSG
 866                                        "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
 867                                        name, curr, curr+minlast, STp->first_frame_position,
 868                                        STp->last_frame_position, STp->cur_frames,
 869                                        result, (jiffies-startwait)/HZ, 
 870                                        (((jiffies-startwait)%HZ)*10)/HZ);
 871#endif
 872                        return 0;
 873                }
 874#if DEBUG
 875                if (time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC) && notyetprinted)
 876                {
 877                        printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
 878                                name, curr, curr+minlast, STp->first_frame_position,
 879                                STp->last_frame_position, STp->cur_frames, result);
 880                        notyetprinted--;
 881                }
 882#endif
 883                msleep(1000 / OSST_POLL_PER_SEC);
 884        }
 885#if DEBUG
 886        printk (OSST_DEB_MSG "%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
 887                name, curr, curr+minlast, STp->first_frame_position,
 888                STp->last_frame_position, STp->cur_frames,
 889                (jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);
 890#endif  
 891        return -EBUSY;
 892}
 893
 894static int osst_recover_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int writing)
 895{
 896        struct osst_request   * SRpnt;
 897        unsigned char           cmd[MAX_COMMAND_SIZE];
 898        unsigned long           startwait = jiffies;
 899        int                     retval    = 1;
 900        char                  * name      = tape_name(STp);
 901                                                                                                                                
 902        if (writing) {
 903                char    mybuf[24];
 904                char  * olddata = STp->buffer->b_data;
 905                int     oldsize = STp->buffer->buffer_size;
 906
 907                /* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
 908
 909                memset(cmd, 0, MAX_COMMAND_SIZE);
 910                cmd[0] = WRITE_FILEMARKS;
 911                cmd[1] = 1;
 912                SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
 913                                                                MAX_RETRIES, 1);
 914
 915                while (retval && time_before (jiffies, startwait + 5*60*HZ)) {
 916
 917                        if (STp->buffer->syscall_result && (SRpnt->sense[2] & 0x0f) != 2) {
 918
 919                                /* some failure - not just not-ready */
 920                                retval = osst_write_error_recovery(STp, aSRpnt, 0);
 921                                break;
 922                        }
 923                        schedule_timeout_interruptible(HZ / OSST_POLL_PER_SEC);
 924
 925                        STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
 926                        memset(cmd, 0, MAX_COMMAND_SIZE);
 927                        cmd[0] = READ_POSITION;
 928
 929                        SRpnt = osst_do_scsi(SRpnt, STp, cmd, 20, DMA_FROM_DEVICE, STp->timeout,
 930                                                                                MAX_RETRIES, 1);
 931
 932                        retval = ( STp->buffer->syscall_result || (STp->buffer)->b_data[15] > 25 );
 933                        STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
 934                }
 935                if (retval)
 936                        printk(KERN_ERR "%s:E: Device did not succeed to write buffered data\n", name);
 937        } else
 938                /* TODO - figure out which error conditions can be handled */
 939                if (STp->buffer->syscall_result)
 940                        printk(KERN_WARNING
 941                                "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name,
 942                                        (*aSRpnt)->sense[ 2] & 0x0f,
 943                                        (*aSRpnt)->sense[12],
 944                                        (*aSRpnt)->sense[13]);
 945
 946        return retval;
 947}
 948
 949/*
 950 * Read the next OnStream tape frame at the current location
 951 */
 952static int osst_read_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int timeout)
 953{
 954        unsigned char           cmd[MAX_COMMAND_SIZE];
 955        struct osst_request   * SRpnt;
 956        int                     retval = 0;
 957#if DEBUG
 958        os_aux_t              * aux    = STp->buffer->aux;
 959        char                  * name   = tape_name(STp);
 960#endif
 961
 962        if (STp->poll)
 963                if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout))
 964                        retval = osst_recover_wait_frame(STp, aSRpnt, 0);
 965
 966        memset(cmd, 0, MAX_COMMAND_SIZE);
 967        cmd[0] = READ_6;
 968        cmd[1] = 1;
 969        cmd[4] = 1;
 970
 971#if DEBUG
 972        if (debugging)
 973                printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
 974#endif
 975        SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
 976                                      STp->timeout, MAX_RETRIES, 1);
 977        *aSRpnt = SRpnt;
 978        if (!SRpnt)
 979                return (-EBUSY);
 980
 981        if ((STp->buffer)->syscall_result) {
 982            retval = 1;
 983            if (STp->read_error_frame == 0) {
 984                STp->read_error_frame = STp->first_frame_position;
 985#if DEBUG
 986                printk(OSST_DEB_MSG "%s:D: Recording read error at %d\n", name, STp->read_error_frame);
 987#endif
 988            }
 989#if DEBUG
 990            if (debugging)
 991                printk(OSST_DEB_MSG "%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
 992                   name,
 993                   SRpnt->sense[0], SRpnt->sense[1],
 994                   SRpnt->sense[2], SRpnt->sense[3],
 995                   SRpnt->sense[4], SRpnt->sense[5],
 996                   SRpnt->sense[6], SRpnt->sense[7]);
 997#endif
 998        }
 999        else
1000            STp->first_frame_position++;
1001#if DEBUG
1002        if (debugging) {
1003           char sig[8]; int i;
1004           for (i=0;i<4;i++)
1005                   sig[i] = aux->application_sig[i]<32?'^':aux->application_sig[i];
1006           sig[4] = '\0';
1007           printk(OSST_DEB_MSG 
1008                "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name, sig,
1009                        ntohl(aux->update_frame_cntr), ntohs(aux->partition.wrt_pass_cntr),
1010                        aux->frame_type==1?"EOD":aux->frame_type==2?"MARK":
1011                        aux->frame_type==8?"HEADR":aux->frame_type==0x80?"DATA":"FILL", 
1012                        ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
1013                        ntohs(aux->dat.dat_list[0].blk_cnt), ntohl(aux->dat.dat_list[0].blk_sz) );
1014           if (aux->frame_type==2)
1015                printk(OSST_DEB_MSG "%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name,
1016                        ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->last_mark_lbn));
1017           printk(OSST_DEB_MSG "%s:D: Exit read frame from OnStream tape with code %d\n", name, retval);
1018        }
1019#endif
1020        return (retval);
1021}
1022
1023static int osst_initiate_read(struct osst_tape * STp, struct osst_request ** aSRpnt)
1024{
1025        struct st_partstat    * STps   = &(STp->ps[STp->partition]);
1026        struct osst_request   * SRpnt  ;
1027        unsigned char           cmd[MAX_COMMAND_SIZE];
1028        int                     retval = 0;
1029        char                  * name   = tape_name(STp);
1030
1031        if (STps->rw != ST_READING) {         /* Initialize read operation */
1032                if (STps->rw == ST_WRITING || STp->dirty) {
1033                        STp->write_type = OS_WRITE_DATA;
1034                        osst_flush_write_buffer(STp, aSRpnt);
1035                        osst_flush_drive_buffer(STp, aSRpnt);
1036                }
1037                STps->rw = ST_READING;
1038                STp->frame_in_buffer = 0;
1039
1040                /*
1041                 *      Issue a read 0 command to get the OnStream drive
1042                 *      read frames into its buffer.
1043                 */
1044                memset(cmd, 0, MAX_COMMAND_SIZE);
1045                cmd[0] = READ_6;
1046                cmd[1] = 1;
1047
1048#if DEBUG
1049                printk(OSST_DEB_MSG "%s:D: Start Read Ahead on OnStream tape\n", name);
1050#endif
1051                SRpnt   = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
1052                *aSRpnt = SRpnt;
1053                if ((retval = STp->buffer->syscall_result))
1054                        printk(KERN_WARNING "%s:W: Error starting read ahead\n", name);
1055        }
1056
1057        return retval;
1058}
1059
1060static int osst_get_logical_frame(struct osst_tape * STp, struct osst_request ** aSRpnt,
1061                                                int frame_seq_number, int quiet)
1062{
1063        struct st_partstat * STps  = &(STp->ps[STp->partition]);
1064        char               * name  = tape_name(STp);
1065        int                  cnt   = 0,
1066                             bad   = 0,
1067                             past  = 0,
1068                             x,
1069                             position;
1070
1071        /*
1072         * If we want just any frame (-1) and there is a frame in the buffer, return it
1073         */
1074        if (frame_seq_number == -1 && STp->frame_in_buffer) {
1075#if DEBUG
1076                printk(OSST_DEB_MSG "%s:D: Frame %d still in buffer\n", name, STp->frame_seq_number);
1077#endif
1078                return (STps->eof);
1079        }
1080        /*
1081         * Search and wait for the next logical tape frame
1082         */
1083        while (1) {
1084                if (cnt++ > 400) {
1085                        printk(KERN_ERR "%s:E: Couldn't find logical frame %d, aborting\n",
1086                                            name, frame_seq_number);
1087                        if (STp->read_error_frame) {
1088                                osst_set_frame_position(STp, aSRpnt, STp->read_error_frame, 0);
1089#if DEBUG
1090                                printk(OSST_DEB_MSG "%s:D: Repositioning tape to bad frame %d\n",
1091                                                    name, STp->read_error_frame);
1092#endif
1093                                STp->read_error_frame = 0;
1094                                STp->abort_count++;
1095                        }
1096                        return (-EIO);
1097                }
1098#if DEBUG
1099                if (debugging)
1100                        printk(OSST_DEB_MSG "%s:D: Looking for frame %d, attempt %d\n",
1101                                          name, frame_seq_number, cnt);
1102#endif
1103                if ( osst_initiate_read(STp, aSRpnt)
1104                || ( (!STp->frame_in_buffer) && osst_read_frame(STp, aSRpnt, 30) ) ) {
1105                        if (STp->raw)
1106                                return (-EIO);
1107                        position = osst_get_frame_position(STp, aSRpnt);
1108                        if (position >= 0xbae && position < 0xbb8)
1109                                position = 0xbb8;
1110                        else if (position > STp->eod_frame_ppos || ++bad == 10) {
1111                                position = STp->read_error_frame - 1;
1112                                bad = 0;
1113                        }
1114                        else {
1115                                position += 29;
1116                                cnt      += 19;
1117                        }
1118#if DEBUG
1119                        printk(OSST_DEB_MSG "%s:D: Bad frame detected, positioning tape to block %d\n",
1120                                         name, position);
1121#endif
1122                        osst_set_frame_position(STp, aSRpnt, position, 0);
1123                        continue;
1124                }
1125                if (osst_verify_frame(STp, frame_seq_number, quiet))
1126                        break;
1127                if (osst_verify_frame(STp, -1, quiet)) {
1128                        x = ntohl(STp->buffer->aux->frame_seq_num);
1129                        if (STp->fast_open) {
1130                                printk(KERN_WARNING
1131                                       "%s:W: Found logical frame %d instead of %d after fast open\n",
1132                                       name, x, frame_seq_number);
1133                                STp->header_ok = 0;
1134                                STp->read_error_frame = 0;
1135                                return (-EIO);
1136                        }
1137                        if (x > frame_seq_number) {
1138                                if (++past > 3) {
1139                                        /* positioning backwards did not bring us to the desired frame */
1140                                        position = STp->read_error_frame - 1;
1141                                }
1142                                else {
1143                                        position = osst_get_frame_position(STp, aSRpnt)
1144                                                 + frame_seq_number - x - 1;
1145
1146                                        if (STp->first_frame_position >= 3000 && position < 3000)
1147                                                position -= 10;
1148                                }
1149#if DEBUG
1150                                printk(OSST_DEB_MSG
1151                                       "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1152                                                name, x, frame_seq_number,
1153                                                STp->first_frame_position - position);
1154#endif
1155                                osst_set_frame_position(STp, aSRpnt, position, 0);
1156                                cnt += 10;
1157                        }
1158                        else
1159                                past = 0;
1160                }
1161                if (osst_get_frame_position(STp, aSRpnt) == 0xbaf) {
1162#if DEBUG
1163                        printk(OSST_DEB_MSG "%s:D: Skipping config partition\n", name);
1164#endif
1165                        osst_set_frame_position(STp, aSRpnt, 0xbb8, 0);
1166                        cnt--;
1167                }
1168                STp->frame_in_buffer = 0;
1169        }
1170        if (cnt > 1) {
1171                STp->recover_count++;
1172                STp->recover_erreg++;
1173                printk(KERN_WARNING "%s:I: Don't worry, Read error at position %d recovered\n", 
1174                                        name, STp->read_error_frame);
1175        }
1176        STp->read_count++;
1177
1178#if DEBUG
1179        if (debugging || STps->eof)
1180                printk(OSST_DEB_MSG
1181                        "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1182                        name, frame_seq_number, STp->frame_seq_number, STps->eof);
1183#endif
1184        STp->fast_open = 0;
1185        STp->read_error_frame = 0;
1186        return (STps->eof);
1187}
1188
1189static int osst_seek_logical_blk(struct osst_tape * STp, struct osst_request ** aSRpnt, int logical_blk_num)
1190{
1191        struct st_partstat * STps = &(STp->ps[STp->partition]);
1192        char               * name = tape_name(STp);
1193        int     retries    = 0;
1194        int     frame_seq_estimate, ppos_estimate, move;
1195        
1196        if (logical_blk_num < 0) logical_blk_num = 0;
1197#if DEBUG
1198        printk(OSST_DEB_MSG "%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1199                                name, logical_blk_num, STp->logical_blk_num, 
1200                                STp->block_size<1024?STp->block_size:STp->block_size/1024,
1201                                STp->block_size<1024?'b':'k');
1202#endif
1203        /* Do we know where we are? */
1204        if (STps->drv_block >= 0) {
1205                move                = logical_blk_num - STp->logical_blk_num;
1206                if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1207                move               /= (OS_DATA_SIZE / STp->block_size);
1208                frame_seq_estimate  = STp->frame_seq_number + move;
1209        } else
1210                frame_seq_estimate  = logical_blk_num * STp->block_size / OS_DATA_SIZE;
1211
1212        if (frame_seq_estimate < 2980) ppos_estimate = frame_seq_estimate + 10;
1213        else                           ppos_estimate = frame_seq_estimate + 20;
1214        while (++retries < 10) {
1215           if (ppos_estimate > STp->eod_frame_ppos-2) {
1216               frame_seq_estimate += STp->eod_frame_ppos - 2 - ppos_estimate;
1217               ppos_estimate       = STp->eod_frame_ppos - 2;
1218           }
1219           if (frame_seq_estimate < 0) {
1220               frame_seq_estimate = 0;
1221               ppos_estimate      = 10;
1222           }
1223           osst_set_frame_position(STp, aSRpnt, ppos_estimate, 0);
1224           if (osst_get_logical_frame(STp, aSRpnt, frame_seq_estimate, 1) >= 0) {
1225              /* we've located the estimated frame, now does it have our block? */
1226              if (logical_blk_num <  STp->logical_blk_num ||
1227                  logical_blk_num >= STp->logical_blk_num + ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt)) {
1228                 if (STps->eof == ST_FM_HIT)
1229                    move = logical_blk_num < STp->logical_blk_num? -2 : 1;
1230                 else {
1231                    move                = logical_blk_num - STp->logical_blk_num;
1232                    if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1233                    move               /= (OS_DATA_SIZE / STp->block_size);
1234                 }
1235                 if (!move) move = logical_blk_num > STp->logical_blk_num ? 1 : -1;
1236#if DEBUG
1237                 printk(OSST_DEB_MSG
1238                        "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1239                                name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate, 
1240                                STp->logical_blk_num, logical_blk_num, move);
1241#endif
1242                 frame_seq_estimate += move;
1243                 ppos_estimate      += move;
1244                 continue;
1245              } else {
1246                 STp->buffer->read_pointer  = (logical_blk_num - STp->logical_blk_num) * STp->block_size;
1247                 STp->buffer->buffer_bytes -= STp->buffer->read_pointer;
1248                 STp->logical_blk_num       =  logical_blk_num;
1249#if DEBUG
1250                 printk(OSST_DEB_MSG 
1251                        "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1252                                name, ppos_estimate, STp->frame_seq_number, STp->frame_in_buffer, 
1253                                STp->buffer->buffer_bytes, STp->buffer->read_pointer / STp->block_size, 
1254                                STp->block_size);
1255#endif
1256                 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1257                 if (STps->eof == ST_FM_HIT) {
1258                     STps->drv_file++;
1259                     STps->drv_block = 0;
1260                 } else {
1261                     STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1262                                          STp->logical_blk_num -
1263                                             (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1264                                        -1;
1265                 }
1266                 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1267                 return 0;
1268              }
1269           }
1270           if (osst_get_logical_frame(STp, aSRpnt, -1, 1) < 0)
1271              goto error;
1272           /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1273#if DEBUG
1274           printk(OSST_DEB_MSG "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n", 
1275                           name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate, 
1276                           STp->logical_blk_num, logical_blk_num);
1277#endif
1278           if (frame_seq_estimate != STp->frame_seq_number)
1279              ppos_estimate += frame_seq_estimate - STp->frame_seq_number;
1280           else
1281              break;
1282        }
1283error:
1284        printk(KERN_ERR "%s:E: Couldn't seek to logical block %d (at %d), %d retries\n", 
1285                            name, logical_blk_num, STp->logical_blk_num, retries);
1286        return (-EIO);
1287}
1288
1289/* The values below are based on the OnStream frame payload size of 32K == 2**15,
1290 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1291 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1292 * inside each frame. Finaly, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1293 */
1294#define OSST_FRAME_SHIFT  6
1295#define OSST_SECTOR_SHIFT 9
1296#define OSST_SECTOR_MASK  0x03F
1297
1298static int osst_get_sector(struct osst_tape * STp, struct osst_request ** aSRpnt)
1299{
1300        int     sector;
1301#if DEBUG
1302        char  * name = tape_name(STp);
1303        
1304        printk(OSST_DEB_MSG 
1305                "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1306                name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1307                STp->ps[STp->partition].drv_file, STp->ps[STp->partition].drv_block, 
1308                STp->ps[STp->partition].rw == ST_WRITING?'w':'r',
1309                STp->ps[STp->partition].rw == ST_WRITING?STp->buffer->buffer_bytes:
1310                STp->buffer->read_pointer, STp->ps[STp->partition].eof);
1311#endif
1312        /* do we know where we are inside a file? */
1313        if (STp->ps[STp->partition].drv_block >= 0) {
1314                sector = (STp->frame_in_buffer ? STp->first_frame_position-1 :
1315                                STp->first_frame_position) << OSST_FRAME_SHIFT;
1316                if (STp->ps[STp->partition].rw == ST_WRITING)
1317                        sector |= (STp->buffer->buffer_bytes >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1318                else
1319                        sector |= (STp->buffer->read_pointer >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1320        } else {
1321                sector = osst_get_frame_position(STp, aSRpnt);
1322                if (sector > 0)
1323                        sector <<= OSST_FRAME_SHIFT;
1324        }
1325        return sector;
1326}
1327
1328static int osst_seek_sector(struct osst_tape * STp, struct osst_request ** aSRpnt, int sector)
1329{
1330        struct st_partstat * STps   = &(STp->ps[STp->partition]);
1331        int                  frame  = sector >> OSST_FRAME_SHIFT,
1332                             offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT, 
1333                             r;
1334#if DEBUG
1335        char          * name = tape_name(STp);
1336
1337        printk(OSST_DEB_MSG "%s:D: Seeking sector %d in frame %d at offset %d\n",
1338                                name, sector, frame, offset);
1339#endif
1340        if (frame < 0 || frame >= STp->capacity) return (-ENXIO);
1341
1342        if (frame <= STp->first_data_ppos) {
1343                STp->frame_seq_number = STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;
1344                return (osst_set_frame_position(STp, aSRpnt, frame, 0));
1345        }
1346        r = osst_set_frame_position(STp, aSRpnt, offset?frame:frame-1, 0);
1347        if (r < 0) return r;
1348
1349        r = osst_get_logical_frame(STp, aSRpnt, -1, 1);
1350        if (r < 0) return r;
1351
1352        if (osst_get_frame_position(STp, aSRpnt) != (offset?frame+1:frame)) return (-EIO);
1353
1354        if (offset) {
1355                STp->logical_blk_num      += offset / STp->block_size;
1356                STp->buffer->read_pointer  = offset;
1357                STp->buffer->buffer_bytes -= offset;
1358        } else {
1359                STp->frame_seq_number++;
1360                STp->frame_in_buffer       = 0;
1361                STp->logical_blk_num      += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1362                STp->buffer->buffer_bytes  = STp->buffer->read_pointer = 0;
1363        }
1364        STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1365        if (STps->eof == ST_FM_HIT) {
1366                STps->drv_file++;
1367                STps->drv_block = 0;
1368        } else {
1369                STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1370                                    STp->logical_blk_num -
1371                                        (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1372                                  -1;
1373        }
1374        STps->eof       = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1375#if DEBUG
1376        printk(OSST_DEB_MSG 
1377                "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1378                name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1379                STps->drv_file, STps->drv_block, STp->buffer->read_pointer, STps->eof);
1380#endif
1381        return 0;
1382}
1383
1384/*
1385 * Read back the drive's internal buffer contents, as a part
1386 * of the write error recovery mechanism for old OnStream
1387 * firmware revisions.
1388 * Precondition for this function to work: all frames in the
1389 * drive's buffer must be of one type (DATA, MARK or EOD)!
1390 */
1391static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct osst_request ** aSRpnt,
1392                                                unsigned int frame, unsigned int skip, int pending)
1393{
1394        struct osst_request   * SRpnt = * aSRpnt;
1395        unsigned char         * buffer, * p;
1396        unsigned char           cmd[MAX_COMMAND_SIZE];
1397        int                     flag, new_frame, i;
1398        int                     nframes          = STp->cur_frames;
1399        int                     blks_per_frame   = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1400        int                     frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
1401                                                - (nframes + pending - 1);
1402        int                     logical_blk_num  = ntohl(STp->buffer->aux->logical_blk_num) 
1403                                                - (nframes + pending - 1) * blks_per_frame;
1404        char                  * name             = tape_name(STp);
1405        unsigned long           startwait        = jiffies;
1406#if DEBUG
1407        int                     dbg              = debugging;
1408#endif
1409
1410        if ((buffer = (unsigned char *)vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
1411                return (-EIO);
1412
1413        printk(KERN_INFO "%s:I: Reading back %d frames from drive buffer%s\n",
1414                         name, nframes, pending?" and one that was pending":"");
1415
1416        osst_copy_from_buffer(STp->buffer, (p = &buffer[nframes * OS_DATA_SIZE]));
1417#if DEBUG
1418        if (pending && debugging)
1419                printk(OSST_DEB_MSG "%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1420                                name, frame_seq_number + nframes,
1421                                logical_blk_num + nframes * blks_per_frame,
1422                                p[0], p[1], p[2], p[3]);
1423#endif
1424        for (i = 0, p = buffer; i < nframes; i++, p += OS_DATA_SIZE) {
1425
1426                memset(cmd, 0, MAX_COMMAND_SIZE);
1427                cmd[0] = 0x3C;          /* Buffer Read           */
1428                cmd[1] = 6;             /* Retrieve Faulty Block */
1429                cmd[7] = 32768 >> 8;
1430                cmd[8] = 32768 & 0xff;
1431
1432                SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1433                                            STp->timeout, MAX_RETRIES, 1);
1434        
1435                if ((STp->buffer)->syscall_result || !SRpnt) {
1436                        printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
1437                        vfree(buffer);
1438                        *aSRpnt = SRpnt;
1439                        return (-EIO);
1440                }
1441                osst_copy_from_buffer(STp->buffer, p);
1442#if DEBUG
1443                if (debugging)
1444                        printk(OSST_DEB_MSG "%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1445                                          name, frame_seq_number + i, p[0], p[1], p[2], p[3]);
1446#endif
1447        }
1448        *aSRpnt = SRpnt;
1449        osst_get_frame_position(STp, aSRpnt);
1450
1451#if DEBUG
1452        printk(OSST_DEB_MSG "%s:D: Frames left in buffer: %d\n", name, STp->cur_frames);
1453#endif
1454        /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1455        /* In the header we don't actually re-write the frames that fail, just the ones after them */
1456
1457        for (flag=1, new_frame=frame, p=buffer, i=0; i < nframes + pending; ) {
1458
1459                if (flag) {
1460                        if (STp->write_type == OS_WRITE_HEADER) {
1461                                i += skip;
1462                                p += skip * OS_DATA_SIZE;
1463                        }
1464                        else if (new_frame < 2990 && new_frame+skip+nframes+pending >= 2990)
1465                                new_frame = 3000-i;
1466                        else
1467                                new_frame += skip;
1468#if DEBUG
1469                        printk(OSST_DEB_MSG "%s:D: Position to frame %d, write fseq %d\n",
1470                                                name, new_frame+i, frame_seq_number+i);
1471#endif
1472                        osst_set_frame_position(STp, aSRpnt, new_frame + i, 0);
1473                        osst_wait_ready(STp, aSRpnt, 60, OSST_WAIT_POSITION_COMPLETE);
1474                        osst_get_frame_position(STp, aSRpnt);
1475                        SRpnt = * aSRpnt;
1476
1477                        if (new_frame > frame + 1000) {
1478                                printk(KERN_ERR "%s:E: Failed to find writable tape media\n", name);
1479                                vfree(buffer);
1480                                return (-EIO);
1481                        }
1482                        if ( i >= nframes + pending ) break;
1483                        flag = 0;
1484                }
1485                osst_copy_to_buffer(STp->buffer, p);
1486                /*
1487                 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1488                 */
1489                osst_init_aux(STp, STp->buffer->aux->frame_type, frame_seq_number+i,
1490                                logical_blk_num + i*blks_per_frame,
1491                                ntohl(STp->buffer->aux->dat.dat_list[0].blk_sz), blks_per_frame);
1492                memset(cmd, 0, MAX_COMMAND_SIZE);
1493                cmd[0] = WRITE_6;
1494                cmd[1] = 1;
1495                cmd[4] = 1;
1496
1497#if DEBUG
1498                if (debugging)
1499                        printk(OSST_DEB_MSG
1500                                "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1501                                name, new_frame+i, frame_seq_number+i, logical_blk_num + i*blks_per_frame,
1502                                p[0], p[1], p[2], p[3]);
1503#endif
1504                SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1505                                            STp->timeout, MAX_RETRIES, 1);
1506
1507                if (STp->buffer->syscall_result)
1508                        flag = 1;
1509                else {
1510                        p += OS_DATA_SIZE; i++;
1511
1512                        /* if we just sent the last frame, wait till all successfully written */
1513                        if ( i == nframes + pending ) {
1514#if DEBUG
1515                                printk(OSST_DEB_MSG "%s:D: Check re-write successful\n", name);
1516#endif
1517                                memset(cmd, 0, MAX_COMMAND_SIZE);
1518                                cmd[0] = WRITE_FILEMARKS;
1519                                cmd[1] = 1;
1520                                SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
1521                                                            STp->timeout, MAX_RETRIES, 1);
1522#if DEBUG
1523                                if (debugging) {
1524                                        printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1525                                        printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1526                                        debugging = 0;
1527                                }
1528#endif
1529                                flag = STp->buffer->syscall_result;
1530                                while ( !flag && time_before(jiffies, startwait + 60*HZ) ) {
1531
1532                                        memset(cmd, 0, MAX_COMMAND_SIZE);
1533                                        cmd[0] = TEST_UNIT_READY;
1534
1535                                        SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
1536                                                                                                MAX_RETRIES, 1);
1537
1538                                        if (SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
1539                                            (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)) {
1540                                                /* in the process of becoming ready */
1541                                                msleep(100);
1542                                                continue;
1543                                        }
1544                                        if (STp->buffer->syscall_result)
1545                                                flag = 1;
1546                                        break;
1547                                }
1548#if DEBUG
1549                                debugging = dbg;
1550                                printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1551#endif
1552                        }
1553                }
1554                *aSRpnt = SRpnt;
1555                if (flag) {
1556                        if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1557                             SRpnt->sense[12]         ==  0 &&
1558                             SRpnt->sense[13]         ==  2) {
1559                                printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name);
1560                                vfree(buffer);
1561                                return (-EIO);                  /* hit end of tape = fail */
1562                        }
1563                        i = ((SRpnt->sense[3] << 24) |
1564                             (SRpnt->sense[4] << 16) |
1565                             (SRpnt->sense[5] <<  8) |
1566                              SRpnt->sense[6]        ) - new_frame;
1567                        p = &buffer[i * OS_DATA_SIZE];
1568#if DEBUG
1569                        printk(OSST_DEB_MSG "%s:D: Additional write error at %d\n", name, new_frame+i);
1570#endif
1571                        osst_get_frame_position(STp, aSRpnt);
1572#if DEBUG
1573                        printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1574                                          name, STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
1575#endif
1576                }
1577        }
1578        if (flag) {
1579                /* error recovery did not successfully complete */
1580                printk(KERN_ERR "%s:D: Write error recovery failed in %s\n", name,
1581                                STp->write_type == OS_WRITE_HEADER?"header":"body");
1582        }
1583        if (!pending)
1584                osst_copy_to_buffer(STp->buffer, p);    /* so buffer content == at entry in all cases */
1585        vfree(buffer);
1586        return 0;
1587}
1588
1589static int osst_reposition_and_retry(struct osst_tape * STp, struct osst_request ** aSRpnt,
1590                                        unsigned int frame, unsigned int skip, int pending)
1591{
1592        unsigned char           cmd[MAX_COMMAND_SIZE];
1593        struct osst_request   * SRpnt;
1594        char                  * name      = tape_name(STp);
1595        int                     expected  = 0;
1596        int                     attempts  = 1000 / skip;
1597        int                     flag      = 1;
1598        unsigned long           startwait = jiffies;
1599#if DEBUG
1600        int                     dbg       = debugging;
1601#endif
1602
1603        while (attempts && time_before(jiffies, startwait + 60*HZ)) {
1604                if (flag) {
1605#if DEBUG
1606                        debugging = dbg;
1607#endif
1608                        if (frame < 2990 && frame+skip+STp->cur_frames+pending >= 2990)
1609                                frame = 3000-skip;
1610                        expected = frame+skip+STp->cur_frames+pending;
1611#if DEBUG
1612                        printk(OSST_DEB_MSG "%s:D: Position to fppos %d, re-write from fseq %d\n",
1613                                          name, frame+skip, STp->frame_seq_number-STp->cur_frames-pending);
1614#endif
1615                        osst_set_frame_position(STp, aSRpnt, frame + skip, 1);
1616                        flag = 0;
1617                        attempts--;
1618                        schedule_timeout_interruptible(msecs_to_jiffies(100));
1619                }
1620                if (osst_get_frame_position(STp, aSRpnt) < 0) {         /* additional write error */
1621#if DEBUG
1622                        printk(OSST_DEB_MSG "%s:D: Addl error, host %d, tape %d, buffer %d\n",
1623                                          name, STp->first_frame_position,
1624                                          STp->last_frame_position, STp->cur_frames);
1625#endif
1626                        frame = STp->last_frame_position;
1627                        flag = 1;
1628                        continue;
1629                }
1630                if (pending && STp->cur_frames < 50) {
1631
1632                        memset(cmd, 0, MAX_COMMAND_SIZE);
1633                        cmd[0] = WRITE_6;
1634                        cmd[1] = 1;
1635                        cmd[4] = 1;
1636#if DEBUG
1637                        printk(OSST_DEB_MSG "%s:D: About to write pending fseq %d at fppos %d\n",
1638                                          name, STp->frame_seq_number-1, STp->first_frame_position);
1639#endif
1640                        SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1641                                                      STp->timeout, MAX_RETRIES, 1);
1642                        *aSRpnt = SRpnt;
1643
1644                        if (STp->buffer->syscall_result) {              /* additional write error */
1645                                if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1646                                     SRpnt->sense[12]         ==  0 &&
1647                                     SRpnt->sense[13]         ==  2) {
1648                                        printk(KERN_ERR
1649                                               "%s:E: Volume overflow in write error recovery\n",
1650                                               name);
1651                                        break;                          /* hit end of tape = fail */
1652                                }
1653                                flag = 1;
1654                        }
1655                        else
1656                                pending = 0;
1657
1658                        continue;
1659                }
1660                if (STp->cur_frames == 0) {
1661#if DEBUG
1662                        debugging = dbg;
1663                        printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1664#endif
1665                        if (STp->first_frame_position != expected) {
1666                                printk(KERN_ERR "%s:A: Actual position %d - expected %d\n", 
1667                                                name, STp->first_frame_position, expected);
1668                                return (-EIO);
1669                        }
1670                        return 0;
1671                }
1672#if DEBUG
1673                if (debugging) {
1674                        printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1675                        printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1676                        debugging = 0;
1677                }
1678#endif
1679                schedule_timeout_interruptible(msecs_to_jiffies(100));
1680        }
1681        printk(KERN_ERR "%s:E: Failed to find valid tape media\n", name);
1682#if DEBUG
1683        debugging = dbg;
1684#endif
1685        return (-EIO);
1686}
1687
1688/*
1689 * Error recovery algorithm for the OnStream tape.
1690 */
1691
1692static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending)
1693{
1694        struct osst_request * SRpnt  = * aSRpnt;
1695        struct st_partstat  * STps   = & STp->ps[STp->partition];
1696        char                * name   = tape_name(STp);
1697        int                   retval = 0;
1698        int                   rw_state;
1699        unsigned int          frame, skip;
1700
1701        rw_state = STps->rw;
1702
1703        if ((SRpnt->sense[ 2] & 0x0f) != 3
1704          || SRpnt->sense[12]         != 12
1705          || SRpnt->sense[13]         != 0) {
1706#if DEBUG
1707                printk(OSST_DEB_MSG "%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name,
1708                        SRpnt->sense[2], SRpnt->sense[12], SRpnt->sense[13]);
1709#endif
1710                return (-EIO);
1711        }
1712        frame = (SRpnt->sense[3] << 24) |
1713                (SRpnt->sense[4] << 16) |
1714                (SRpnt->sense[5] <<  8) |
1715                 SRpnt->sense[6];
1716        skip  =  SRpnt->sense[9];
1717 
1718#if DEBUG
1719        printk(OSST_DEB_MSG "%s:D: Detected physical bad frame at %u, advised to skip %d\n", name, frame, skip);
1720#endif
1721        osst_get_frame_position(STp, aSRpnt);
1722#if DEBUG
1723        printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d\n",
1724                        name, STp->first_frame_position, STp->last_frame_position);
1725#endif
1726        switch (STp->write_type) {
1727           case OS_WRITE_DATA:
1728           case OS_WRITE_EOD:
1729           case OS_WRITE_NEW_MARK:
1730                printk(KERN_WARNING 
1731                        "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1732                        name, STp->cur_frames, frame, (frame + skip > 3000 && frame < 3000)?3000:frame + skip);
1733                if (STp->os_fw_rev >= 10600)
1734                        retval = osst_reposition_and_retry(STp, aSRpnt, frame, skip, pending);
1735                else
1736                        retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, skip, pending);
1737                printk(KERN_WARNING "%s:%s: %sWrite error%srecovered\n", name,
1738                                retval?"E"    :"I",
1739                                retval?""     :"Don't worry, ",
1740                                retval?" not ":" ");
1741                break;
1742           case OS_WRITE_LAST_MARK:
1743                printk(KERN_ERR "%s:E: Bad frame in update last marker, fatal\n", name);
1744                osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1745                retval = -EIO;
1746                break;
1747           case OS_WRITE_HEADER:
1748                printk(KERN_WARNING "%s:I: Bad frame in header partition, skipped\n", name);
1749                retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, 1, pending);
1750                break;
1751           default:
1752                printk(KERN_INFO "%s:I: Bad frame in filler, ignored\n", name);
1753                osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1754        }
1755        osst_get_frame_position(STp, aSRpnt);
1756#if DEBUG
1757        printk(OSST_DEB_MSG "%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n", 
1758                        name, STp->cur_frames, STp->first_frame_position, STp->last_frame_position);
1759        printk(OSST_DEB_MSG "%s:D: next logical frame to write: %d\n", name, STp->logical_blk_num);
1760#endif
1761        if (retval == 0) {
1762                STp->recover_count++;
1763                STp->recover_erreg++;
1764        } else
1765                STp->abort_count++;
1766
1767        STps->rw = rw_state;
1768        return retval;
1769}
1770
1771static int osst_space_over_filemarks_backward(struct osst_tape * STp, struct osst_request ** aSRpnt,
1772                                                                 int mt_op, int mt_count)
1773{
1774        char  * name = tape_name(STp);
1775        int     cnt;
1776        int     last_mark_ppos = -1;
1777
1778#if DEBUG
1779        printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_backwards %d %d\n", name, mt_op, mt_count);
1780#endif
1781        if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1782#if DEBUG
1783                printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name);
1784#endif
1785                return -EIO;
1786        }
1787        if (STp->linux_media_version >= 4) {
1788                /*
1789                 * direct lookup in header filemark list
1790                 */
1791                cnt = ntohl(STp->buffer->aux->filemark_cnt);
1792                if (STp->header_ok                         && 
1793                    STp->header_cache != NULL              &&
1794                    (cnt - mt_count)  >= 0                 &&
1795                    (cnt - mt_count)   < OS_FM_TAB_MAX     &&
1796                    (cnt - mt_count)   < STp->filemark_cnt &&
1797                    STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] == STp->buffer->aux->last_mark_ppos)
1798
1799                        last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt - mt_count]);
1800#if DEBUG
1801                if (STp->header_cache == NULL || (cnt - mt_count) < 0 || (cnt - mt_count) >= OS_FM_TAB_MAX)
1802                        printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1803                               STp->header_cache == NULL?"lack of header cache":"count out of range");
1804                else
1805                        printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1806                                name, cnt,
1807                                ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1808                                 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] ==
1809                                         STp->buffer->aux->last_mark_ppos))?"match":"error",
1810                               mt_count, last_mark_ppos);
1811#endif
1812                if (last_mark_ppos > 10 && last_mark_ppos < STp->eod_frame_ppos) {
1813                        osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1814                        if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1815#if DEBUG
1816                                printk(OSST_DEB_MSG 
1817                                        "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1818#endif
1819                                return (-EIO);
1820                        }
1821                        if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1822                                printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1823                                                 name, last_mark_ppos);
1824                                return (-EIO);
1825                        }
1826                        goto found;
1827                }
1828#if DEBUG
1829                printk(OSST_DEB_MSG "%s:D: Reverting to scan filemark backwards\n", name);
1830#endif
1831        }
1832        cnt = 0;
1833        while (cnt != mt_count) {
1834                last_mark_ppos = ntohl(STp->buffer->aux->last_mark_ppos);
1835                if (last_mark_ppos == -1)
1836                        return (-EIO);
1837#if DEBUG
1838                printk(OSST_DEB_MSG "%s:D: Positioning to last mark at %d\n", name, last_mark_ppos);
1839#endif
1840                osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1841                cnt++;
1842                if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1843#if DEBUG
1844                        printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1845#endif
1846                        return (-EIO);
1847                }
1848                if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1849                        printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1850                                         name, last_mark_ppos);
1851                        return (-EIO);
1852                }
1853        }
1854found:
1855        if (mt_op == MTBSFM) {
1856                STp->frame_seq_number++;
1857                STp->frame_in_buffer      = 0;
1858                STp->buffer->buffer_bytes = 0;
1859                STp->buffer->read_pointer = 0;
1860                STp->logical_blk_num     += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1861        }
1862        return 0;
1863}
1864
1865/*
1866 * ADRL 1.1 compatible "slow" space filemarks fwd version
1867 *
1868 * Just scans for the filemark sequentially.
1869 */
1870static int osst_space_over_filemarks_forward_slow(struct osst_tape * STp, struct osst_request ** aSRpnt,
1871                                                                     int mt_op, int mt_count)
1872{
1873        int     cnt = 0;
1874#if DEBUG
1875        char  * name = tape_name(STp);
1876
1877        printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name, mt_op, mt_count);
1878#endif
1879        if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1880#if DEBUG
1881                printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1882#endif
1883                return (-EIO);
1884        }
1885        while (1) {
1886                if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1887#if DEBUG
1888                        printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1889#endif
1890                        return (-EIO);
1891                }
1892                if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1893                        cnt++;
1894                if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1895#if DEBUG
1896                        printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
1897#endif
1898                        if (STp->first_frame_position > STp->eod_frame_ppos+1) {
1899#if DEBUG
1900                                printk(OSST_DEB_MSG "%s:D: EOD position corrected (%d=>%d)\n",
1901                                                name, STp->eod_frame_ppos, STp->first_frame_position-1);
1902#endif
1903                                STp->eod_frame_ppos = STp->first_frame_position-1;
1904                        }
1905                        return (-EIO);
1906                }
1907                if (cnt == mt_count)
1908                        break;
1909                STp->frame_in_buffer = 0;
1910        }
1911        if (mt_op == MTFSF) {
1912                STp->frame_seq_number++;
1913                STp->frame_in_buffer      = 0;
1914                STp->buffer->buffer_bytes = 0;
1915                STp->buffer->read_pointer = 0;
1916                STp->logical_blk_num     += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1917        }
1918        return 0;
1919}
1920
1921/*
1922 * Fast linux specific version of OnStream FSF
1923 */
1924static int osst_space_over_filemarks_forward_fast(struct osst_tape * STp, struct osst_request ** aSRpnt,
1925                                                                     int mt_op, int mt_count)
1926{
1927        char  * name = tape_name(STp);
1928        int     cnt  = 0,
1929                next_mark_ppos = -1;
1930
1931#if DEBUG
1932        printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name, mt_op, mt_count);
1933#endif
1934        if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1935#if DEBUG
1936                printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1937#endif
1938                return (-EIO);
1939        }
1940
1941        if (STp->linux_media_version >= 4) {
1942                /*
1943                 * direct lookup in header filemark list
1944                 */
1945                cnt = ntohl(STp->buffer->aux->filemark_cnt) - 1;
1946                if (STp->header_ok                         && 
1947                    STp->header_cache != NULL              &&
1948                    (cnt + mt_count)   < OS_FM_TAB_MAX     &&
1949                    (cnt + mt_count)   < STp->filemark_cnt &&
1950                    ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1951                     (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] == STp->buffer->aux->last_mark_ppos)))
1952
1953                        next_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt + mt_count]);
1954#if DEBUG
1955                if (STp->header_cache == NULL || (cnt + mt_count) >= OS_FM_TAB_MAX)
1956                        printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1957                               STp->header_cache == NULL?"lack of header cache":"count out of range");
1958                else
1959                        printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1960                               name, cnt,
1961                               ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1962                                (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] ==
1963                                         STp->buffer->aux->last_mark_ppos))?"match":"error",
1964                               mt_count, next_mark_ppos);
1965#endif
1966                if (next_mark_ppos <= 10 || next_mark_ppos > STp->eod_frame_ppos) {
1967#if DEBUG
1968                        printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
1969#endif
1970                        return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
1971                } else {
1972                        osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
1973                        if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1974#if DEBUG
1975                                printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
1976                                                 name);
1977#endif
1978                                return (-EIO);
1979                        }
1980                        if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1981                                printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1982                                                 name, next_mark_ppos);
1983                                return (-EIO);
1984                        }
1985                        if (ntohl(STp->buffer->aux->filemark_cnt) != cnt + mt_count) {
1986                                printk(KERN_WARNING "%s:W: Expected to find marker %d at ppos %d, not %d\n",
1987                                                 name, cnt+mt_count, next_mark_ppos,
1988                                                 ntohl(STp->buffer->aux->filemark_cnt));
1989                                return (-EIO);
1990                        }
1991                }
1992        } else {
1993                /*
1994                 * Find nearest (usually previous) marker, then jump from marker to marker
1995                 */
1996                while (1) {
1997                        if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1998                                break;
1999                        if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
2000#if DEBUG
2001                                printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
2002#endif
2003                                return (-EIO);
2004                        }
2005                        if (ntohl(STp->buffer->aux->filemark_cnt) == 0) {
2006                                if (STp->first_mark_ppos == -1) {
2007#if DEBUG
2008                                        printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2009#endif
2010                                        return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2011                                }
2012                                osst_position_tape_and_confirm(STp, aSRpnt, STp->first_mark_ppos);
2013                                if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2014#if DEBUG
2015                                        printk(OSST_DEB_MSG
2016                                               "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
2017                                               name);
2018#endif
2019                                        return (-EIO);
2020                                }
2021                                if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2022                                        printk(KERN_WARNING "%s:W: Expected to find filemark at %d\n",
2023                                                         name, STp->first_mark_ppos);
2024                                        return (-EIO);
2025                                }
2026                        } else {
2027                                if (osst_space_over_filemarks_backward(STp, aSRpnt, MTBSF, 1) < 0)
2028                                        return (-EIO);
2029                                mt_count++;
2030                        }
2031                }
2032                cnt++;
2033                while (cnt != mt_count) {
2034                        next_mark_ppos = ntohl(STp->buffer->aux->next_mark_ppos);
2035                        if (!next_mark_ppos || next_mark_ppos > STp->eod_frame_ppos) {
2036#if DEBUG
2037                                printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2038#endif
2039                                return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count - cnt);
2040                        }
2041#if DEBUG
2042                        else printk(OSST_DEB_MSG "%s:D: Positioning to next mark at %d\n", name, next_mark_ppos);
2043#endif
2044                        osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2045                        cnt++;
2046                        if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2047#if DEBUG
2048                                printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2049                                                 name);
2050#endif
2051                                return (-EIO);
2052                        }
2053                        if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2054                                printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2055                                                 name, next_mark_ppos);
2056                                return (-EIO);
2057                        }
2058                }
2059        }
2060        if (mt_op == MTFSF) {
2061                STp->frame_seq_number++;
2062                STp->frame_in_buffer      = 0;
2063                STp->buffer->buffer_bytes = 0;
2064                STp->buffer->read_pointer = 0;
2065                STp->logical_blk_num     += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
2066        }
2067        return 0;
2068}
2069
2070/*
2071 * In debug mode, we want to see as many errors as possible
2072 * to test the error recovery mechanism.
2073 */
2074#if DEBUG
2075static void osst_set_retries(struct osst_tape * STp, struct osst_request ** aSRpnt, int retries)
2076{
2077        unsigned char           cmd[MAX_COMMAND_SIZE];
2078        struct osst_request   * SRpnt  = * aSRpnt;
2079        char                  * name   = tape_name(STp);
2080
2081        memset(cmd, 0, MAX_COMMAND_SIZE);
2082        cmd[0] = MODE_SELECT;
2083        cmd[1] = 0x10;
2084        cmd[4] = NUMBER_RETRIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2085
2086        (STp->buffer)->b_data[0] = cmd[4] - 1;
2087        (STp->buffer)->b_data[1] = 0;                   /* Medium Type - ignoring */
2088        (STp->buffer)->b_data[2] = 0;                   /* Reserved */
2089        (STp->buffer)->b_data[3] = 0;                   /* Block Descriptor Length */
2090        (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = NUMBER_RETRIES_PAGE | (1 << 7);
2091        (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 2;
2092        (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 4;
2093        (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = retries;
2094
2095        if (debugging)
2096            printk(OSST_DEB_MSG "%s:D: Setting number of retries on OnStream tape to %d\n", name, retries);
2097
2098        SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2099        *aSRpnt = SRpnt;
2100
2101        if ((STp->buffer)->syscall_result)
2102            printk (KERN_ERR "%s:D: Couldn't set retries to %d\n", name, retries);
2103}
2104#endif
2105
2106
2107static int osst_write_filemark(struct osst_tape * STp, struct osst_request ** aSRpnt)
2108{
2109        int     result;
2110        int     this_mark_ppos = STp->first_frame_position;
2111        int     this_mark_lbn  = STp->logical_blk_num;
2112#if DEBUG
2113        char  * name = tape_name(STp);
2114#endif
2115
2116        if (STp->raw) return 0;
2117
2118        STp->write_type = OS_WRITE_NEW_MARK;
2119#if DEBUG
2120        printk(OSST_DEB_MSG "%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n", 
2121               name, STp->filemark_cnt, this_mark_ppos, STp->frame_seq_number, this_mark_lbn);
2122#endif
2123        STp->dirty = 1;
2124        result  = osst_flush_write_buffer(STp, aSRpnt);
2125        result |= osst_flush_drive_buffer(STp, aSRpnt);
2126        STp->last_mark_ppos = this_mark_ppos;
2127        STp->last_mark_lbn  = this_mark_lbn;
2128        if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX)
2129                STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos);
2130        if (STp->filemark_cnt++ == 0)
2131                STp->first_mark_ppos = this_mark_ppos;
2132        return result;
2133}
2134
2135static int osst_write_eod(struct osst_tape * STp, struct osst_request ** aSRpnt)
2136{
2137        int     result;
2138#if DEBUG
2139        char  * name = tape_name(STp);
2140#endif
2141
2142        if (STp->raw) return 0;
2143
2144        STp->write_type = OS_WRITE_EOD;
2145        STp->eod_frame_ppos = STp->first_frame_position;
2146#if DEBUG
2147        printk(OSST_DEB_MSG "%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name,
2148                        STp->eod_frame_ppos, STp->frame_seq_number, STp->logical_blk_num);
2149#endif
2150        STp->dirty = 1;
2151
2152        result  = osst_flush_write_buffer(STp, aSRpnt); 
2153        result |= osst_flush_drive_buffer(STp, aSRpnt);
2154        STp->eod_frame_lfa = --(STp->frame_seq_number);
2155        return result;
2156}
2157
2158static int osst_write_filler(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2159{
2160        char * name = tape_name(STp);
2161
2162#if DEBUG
2163        printk(OSST_DEB_MSG "%s:D: Reached onstream write filler group %d\n", name, where);
2164#endif
2165        osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2166        osst_set_frame_position(STp, aSRpnt, where, 0);
2167        STp->write_type = OS_WRITE_FILLER;
2168        while (count--) {
2169                memcpy(STp->buffer->b_data, "Filler", 6);
2170                STp->buffer->buffer_bytes = 6;
2171                STp->dirty = 1;
2172                if (osst_flush_write_buffer(STp, aSRpnt)) {
2173                        printk(KERN_INFO "%s:I: Couldn't write filler frame\n", name);
2174                        return (-EIO);
2175                }
2176        }
2177#if DEBUG
2178        printk(OSST_DEB_MSG "%s:D: Exiting onstream write filler group\n", name);
2179#endif
2180        return osst_flush_drive_buffer(STp, aSRpnt);
2181}
2182
2183static int __osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2184{
2185        char * name = tape_name(STp);
2186        int     result;
2187
2188#if DEBUG
2189        printk(OSST_DEB_MSG "%s:D: Reached onstream write header group %d\n", name, where);
2190#endif
2191        osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2192        osst_set_frame_position(STp, aSRpnt, where, 0);
2193        STp->write_type = OS_WRITE_HEADER;
2194        while (count--) {
2195                osst_copy_to_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2196                STp->buffer->buffer_bytes = sizeof(os_header_t);
2197                STp->dirty = 1;
2198                if (osst_flush_write_buffer(STp, aSRpnt)) {
2199                        printk(KERN_INFO "%s:I: Couldn't write header frame\n", name);
2200                        return (-EIO);
2201                }
2202        }
2203        result = osst_flush_drive_buffer(STp, aSRpnt);
2204#if DEBUG
2205        printk(OSST_DEB_MSG "%s:D: Write onstream header group %s\n", name, result?"failed":"done");
2206#endif
2207        return result;
2208}
2209
2210static int osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int locate_eod)
2211{
2212        os_header_t * header;
2213        int           result;
2214        char        * name = tape_name(STp);
2215
2216#if DEBUG
2217        printk(OSST_DEB_MSG "%s:D: Writing tape header\n", name);
2218#endif
2219        if (STp->raw) return 0;
2220
2221        if (STp->header_cache == NULL) {
2222                if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2223                        printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2224                        return (-ENOMEM);
2225                }
2226                memset(STp->header_cache, 0, sizeof(os_header_t));
2227#if DEBUG
2228                printk(OSST_DEB_MSG "%s:D: Allocated and cleared memory for header cache\n", name);
2229#endif
2230        }
2231        if (STp->header_ok) STp->update_frame_cntr++;
2232        else                STp->update_frame_cntr = 0;
2233
2234        header = STp->header_cache;
2235        strcpy(header->ident_str, "ADR_SEQ");
2236        header->major_rev      = 1;
2237        header->minor_rev      = 4;
2238        header->ext_trk_tb_off = htons(17192);
2239        header->pt_par_num     = 1;
2240        header->partition[0].partition_num              = OS_DATA_PARTITION;
2241        header->partition[0].par_desc_ver               = OS_PARTITION_VERSION;
2242        header->partition[0].wrt_pass_cntr              = htons(STp->wrt_pass_cntr);
2243        header->partition[0].first_frame_ppos           = htonl(STp->first_data_ppos);
2244        header->partition[0].last_frame_ppos            = htonl(STp->capacity);
2245        header->partition[0].eod_frame_ppos             = htonl(STp->eod_frame_ppos);
2246        header->cfg_col_width                           = htonl(20);
2247        header->dat_col_width                           = htonl(1500);
2248        header->qfa_col_width                           = htonl(0);
2249        header->ext_track_tb.nr_stream_part             = 1;
2250        header->ext_track_tb.et_ent_sz                  = 32;
2251        header->ext_track_tb.dat_ext_trk_ey.et_part_num = 0;
2252        header->ext_track_tb.dat_ext_trk_ey.fmt         = 1;
2253        header->ext_track_tb.dat_ext_trk_ey.fm_tab_off  = htons(17736);
2254        header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi = 0;
2255        header->ext_track_tb.dat_ext_trk_ey.last_hlb    = htonl(STp->eod_frame_lfa);
2256        header->ext_track_tb.dat_ext_trk_ey.last_pp     = htonl(STp->eod_frame_ppos);
2257        header->dat_fm_tab.fm_part_num                  = 0;
2258        header->dat_fm_tab.fm_tab_ent_sz                = 4;
2259        header->dat_fm_tab.fm_tab_ent_cnt               = htons(STp->filemark_cnt<OS_FM_TAB_MAX?
2260                                                                STp->filemark_cnt:OS_FM_TAB_MAX);
2261
2262        result  = __osst_write_header(STp, aSRpnt, 0xbae, 5);
2263        if (STp->update_frame_cntr == 0)
2264                    osst_write_filler(STp, aSRpnt, 0xbb3, 5);
2265        result &= __osst_write_header(STp, aSRpnt,     5, 5);
2266
2267        if (locate_eod) {
2268#if DEBUG
2269                printk(OSST_DEB_MSG "%s:D: Locating back to eod frame addr %d\n", name, STp->eod_frame_ppos);
2270#endif
2271                osst_set_frame_position(STp, aSRpnt, STp->eod_frame_ppos, 0);
2272        }
2273        if (result)
2274                printk(KERN_ERR "%s:E: Write header failed\n", name);
2275        else {
2276                memcpy(STp->application_sig, "LIN4", 4);
2277                STp->linux_media         = 1;
2278                STp->linux_media_version = 4;
2279                STp->header_ok           = 1;
2280        }
2281        return result;
2282}
2283
2284static int osst_reset_header(struct osst_tape * STp, struct osst_request ** aSRpnt)
2285{
2286        if (STp->header_cache != NULL)
2287                memset(STp->header_cache, 0, sizeof(os_header_t));
2288
2289        STp->logical_blk_num = STp->frame_seq_number = 0;
2290        STp->frame_in_buffer = 0;
2291        STp->eod_frame_ppos = STp->first_data_ppos = 0x0000000A;
2292        STp->filemark_cnt = 0;
2293        STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2294        return osst_write_header(STp, aSRpnt, 1);
2295}
2296
2297static int __osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt, int ppos)
2298{
2299        char        * name = tape_name(STp);
2300        os_header_t * header;
2301        os_aux_t    * aux;
2302        char          id_string[8];
2303        int           linux_media_version,
2304                      update_frame_cntr;
2305
2306        if (STp->raw)
2307                return 1;
2308
2309        if (ppos == 5 || ppos == 0xbae || STp->buffer->syscall_result) {
2310                if (osst_set_frame_position(STp, aSRpnt, ppos, 0))
2311                        printk(KERN_WARNING "%s:W: Couldn't position tape\n", name);
2312                osst_wait_ready(STp, aSRpnt, 60 * 15, 0);
2313                if (osst_initiate_read (STp, aSRpnt)) {
2314                        printk(KERN_WARNING "%s:W: Couldn't initiate read\n", name);
2315                        return 0;
2316                }
2317        }
2318        if (osst_read_frame(STp, aSRpnt, 180)) {
2319#if DEBUG
2320                printk(OSST_DEB_MSG "%s:D: Couldn't read header frame\n", name);
2321#endif
2322                return 0;
2323        }
2324        header = (os_header_t *) STp->buffer->b_data;   /* warning: only first segment addressable */
2325        aux = STp->buffer->aux;
2326        if (aux->frame_type != OS_FRAME_TYPE_HEADER) {
2327#if DEBUG
2328                printk(OSST_DEB_MSG "%s:D: Skipping non-header frame (%d)\n", name, ppos);
2329#endif
2330                return 0;
2331        }
2332        if (ntohl(aux->frame_seq_num)              != 0                   ||
2333            ntohl(aux->logical_blk_num)            != 0                   ||
2334                  aux->partition.partition_num     != OS_CONFIG_PARTITION ||
2335            ntohl(aux->partition.first_frame_ppos) != 0                   ||
2336            ntohl(aux->partition.last_frame_ppos)  != 0xbb7               ) {
2337#if DEBUG
2338                printk(OSST_DEB_MSG "%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name,
2339                                ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
2340                                aux->partition.partition_num, ntohl(aux->partition.first_frame_ppos),
2341                                ntohl(aux->partition.last_frame_ppos));
2342#endif
2343                return 0;
2344        }
2345        if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0 &&
2346            strncmp(header->ident_str, "ADR-SEQ", 7) != 0) {
2347                strlcpy(id_string, header->ident_str, 8);
2348#if DEBUG
2349                printk(OSST_DEB_MSG "%s:D: Invalid header identification string %s\n", name, id_string);
2350#endif
2351                return 0;
2352        }
2353        update_frame_cntr = ntohl(aux->update_frame_cntr);
2354        if (update_frame_cntr < STp->update_frame_cntr) {
2355#if DEBUG
2356                printk(OSST_DEB_MSG "%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2357                                   name, ppos, update_frame_cntr, STp->update_frame_cntr);
2358#endif
2359                return 0;
2360        }
2361        if (header->major_rev != 1 || header->minor_rev != 4 ) {
2362#if DEBUG
2363                printk(OSST_DEB_MSG "%s:D: %s revision %d.%d detected (1.4 supported)\n", 
2364                                 name, (header->major_rev != 1 || header->minor_rev < 2 || 
2365                                       header->minor_rev  > 4 )? "Invalid" : "Warning:",
2366                                 header->major_rev, header->minor_rev);
2367#endif
2368                if (header->major_rev != 1 || header->minor_rev < 2 || header->minor_rev > 4)
2369                        return 0;
2370        }
2371#if DEBUG
2372        if (header->pt_par_num != 1)
2373                printk(KERN_INFO "%s:W: %d partitions defined, only one supported\n", 
2374                                 name, header->pt_par_num);
2375#endif
2376        memcpy(id_string, aux->application_sig, 4);
2377        id_string[4] = 0;
2378        if (memcmp(id_string, "LIN", 3) == 0) {
2379                STp->linux_media = 1;
2380                linux_media_version = id_string[3] - '0';
2381                if (linux_media_version != 4)
2382                        printk(KERN_INFO "%s:I: Linux media version %d detected (current 4)\n",
2383                                         name, linux_media_version);
2384        } else {
2385                printk(KERN_WARNING "%s:W: Non Linux media detected (%s)\n", name, id_string);
2386                return 0;
2387        }
2388        if (linux_media_version < STp->linux_media_version) {
2389#if DEBUG
2390                printk(OSST_DEB_MSG "%s:D: Skipping frame %d with linux_media_version %d\n",
2391                                  name, ppos, linux_media_version);
2392#endif
2393                return 0;
2394        }
2395        if (linux_media_version > STp->linux_media_version) {
2396#if DEBUG
2397                printk(OSST_DEB_MSG "%s:D: Frame %d sets linux_media_version to %d\n",
2398                                   name, ppos, linux_media_version);
2399#endif
2400                memcpy(STp->application_sig, id_string, 5);
2401                STp->linux_media_version = linux_media_version;
2402                STp->update_frame_cntr = -1;
2403        }
2404        if (update_frame_cntr > STp->update_frame_cntr) {
2405#if DEBUG
2406                printk(OSST_DEB_MSG "%s:D: Frame %d sets update_frame_counter to %d\n",
2407                                   name, ppos, update_frame_cntr);
2408#endif
2409                if (STp->header_cache == NULL) {
2410                        if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2411                                printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2412                                return 0;
2413                        }
2414#if DEBUG
2415                        printk(OSST_DEB_MSG "%s:D: Allocated memory for header cache\n", name);
2416#endif
2417                }
2418                osst_copy_from_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2419                header = STp->header_cache;     /* further accesses from cached (full) copy */
2420
2421                STp->wrt_pass_cntr     = ntohs(header->partition[0].wrt_pass_cntr);
2422                STp->first_data_ppos   = ntohl(header->partition[0].first_frame_ppos);
2423                STp->eod_frame_ppos    = ntohl(header->partition[0].eod_frame_ppos);
2424                STp->eod_frame_lfa     = ntohl(header->ext_track_tb.dat_ext_trk_ey.last_hlb);
2425                STp->filemark_cnt      = ntohl(aux->filemark_cnt);
2426                STp->first_mark_ppos   = ntohl(aux->next_mark_ppos);
2427                STp->last_mark_ppos    = ntohl(aux->last_mark_ppos);
2428                STp->last_mark_lbn     = ntohl(aux->last_mark_lbn);
2429                STp->update_frame_cntr = update_frame_cntr;
2430#if DEBUG
2431        printk(OSST_DEB_MSG "%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2432                          name, STp->wrt_pass_cntr, STp->update_frame_cntr, STp->filemark_cnt);
2433        printk(OSST_DEB_MSG "%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name,
2434                          STp->first_data_ppos,
2435                          ntohl(header->partition[0].last_frame_ppos),
2436                          ntohl(header->partition[0].eod_frame_ppos));
2437        printk(OSST_DEB_MSG "%s:D: first mark on tape = %d, last = %d, eod frame = %d\n", 
2438                          name, STp->first_mark_ppos, STp->last_mark_ppos, STp->eod_frame_ppos);
2439#endif
2440                if (header->minor_rev < 4 && STp->linux_media_version == 4) {
2441#if DEBUG
2442                        printk(OSST_DEB_MSG "%s:D: Moving filemark list to ADR 1.4 location\n", name);
2443#endif
2444                        memcpy((void *)header->dat_fm_tab.fm_tab_ent, 
2445                               (void *)header->old_filemark_list, sizeof(header->dat_fm_tab.fm_tab_ent));
2446                        memset((void *)header->old_filemark_list, 0, sizeof(header->old_filemark_list));
2447                }
2448                if (header->minor_rev == 4   &&
2449                    (header->ext_trk_tb_off                          != htons(17192)               ||
2450                     header->partition[0].partition_num              != OS_DATA_PARTITION          ||
2451                     header->partition[0].par_desc_ver               != OS_PARTITION_VERSION       ||
2452                     header->partition[0].last_frame_ppos            != htonl(STp->capacity)       ||
2453                     header->cfg_col_width                           != htonl(20)                  ||
2454                     header->dat_col_width                           != htonl(1500)                ||
2455                     header->qfa_col_width                           != htonl(0)                   ||
2456                     header->ext_track_tb.nr_stream_part             != 1                          ||
2457                     header->ext_track_tb.et_ent_sz                  != 32                         ||
2458                     header->ext_track_tb.dat_ext_trk_ey.et_part_num != OS_DATA_PARTITION          ||
2459                     header->ext_track_tb.dat_ext_trk_ey.fmt         != 1                          ||
2460                     header->ext_track_tb.dat_ext_trk_ey.fm_tab_off  != htons(17736)               ||
2461                     header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi != 0                          ||
2462                     header->ext_track_tb.dat_ext_trk_ey.last_pp     != htonl(STp->eod_frame_ppos) ||
2463                     header->dat_fm_tab.fm_part_num                  != OS_DATA_PARTITION          ||
2464                     header->dat_fm_tab.fm_tab_ent_sz                != 4                          ||
2465                     header->dat_fm_tab.fm_tab_ent_cnt               !=
2466                             htons(STp->filemark_cnt<OS_FM_TAB_MAX?STp->filemark_cnt:OS_FM_TAB_MAX)))
2467                        printk(KERN_WARNING "%s:W: Failed consistency check ADR 1.4 format\n", name);
2468
2469        }
2470
2471        return 1;
2472}
2473
2474static int osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt)
2475{
2476        int     position, ppos;
2477        int     first, last;
2478        int     valid = 0;
2479        char  * name  = tape_name(STp);
2480
2481        position = osst_get_frame_position(STp, aSRpnt);
2482
2483        if (STp->raw) {
2484                STp->header_ok = STp->linux_media = 1;
2485                STp->linux_media_version = 0;
2486                return 1;
2487        }
2488        STp->header_ok = STp->linux_media = STp->linux_media_version = 0;
2489        STp->wrt_pass_cntr = STp->update_frame_cntr = -1;
2490        STp->eod_frame_ppos = STp->first_data_ppos = -1;
2491        STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2492#if DEBUG
2493        printk(OSST_DEB_MSG "%s:D: Reading header\n", name);
2494#endif
2495
2496        /* optimization for speed - if we are positioned at ppos 10, read second group first  */        
2497        /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2498
2499        first = position==10?0xbae: 5;
2500        last  = position==10?0xbb3:10;
2501
2502        for (ppos = first; ppos < last; ppos++)
2503                if (__osst_analyze_headers(STp, aSRpnt, ppos))
2504                        valid = 1;
2505
2506        first = position==10? 5:0xbae;
2507        last  = position==10?10:0xbb3;
2508
2509        for (ppos = first; ppos < last; ppos++)
2510                if (__osst_analyze_headers(STp, aSRpnt, ppos))
2511                        valid = 1;
2512
2513        if (!valid) {
2514                printk(KERN_ERR "%s:E: Failed to find valid ADRL header, new media?\n", name);
2515                STp->eod_frame_ppos = STp->first_data_ppos = 0;
2516                osst_set_frame_position(STp, aSRpnt, 10, 0);
2517                return 0;
2518        }
2519        if (position <= STp->first_data_ppos) {
2520                position = STp->first_data_ppos;
2521                STp->ps[0].drv_file = STp->ps[0].drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
2522        }
2523        osst_set_frame_position(STp, aSRpnt, position, 0);
2524        STp->header_ok = 1;
2525
2526        return 1;
2527}
2528
2529static int osst_verify_position(struct osst_tape * STp, struct osst_request ** aSRpnt)
2530{
2531        int     frame_position  = STp->first_frame_position;
2532        int     frame_seq_numbr = STp->frame_seq_number;
2533        int     logical_blk_num = STp->logical_blk_num;
2534        int     halfway_frame   = STp->frame_in_buffer;
2535        int     read_pointer    = STp->buffer->read_pointer;
2536        int     prev_mark_ppos  = -1;
2537        int     actual_mark_ppos, i, n;
2538#if DEBUG
2539        char  * name = tape_name(STp);
2540
2541        printk(OSST_DEB_MSG "%s:D: Verify that the tape is really the one we think before writing\n", name);
2542#endif
2543        osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2544        if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2545#if DEBUG
2546                printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in verify_position\n", name);
2547#endif
2548                return (-EIO);
2549        }
2550        if (STp->linux_media_version >= 4) {
2551                for (i=0; i<STp->filemark_cnt; i++)
2552                        if ((n=ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i])) < frame_position)
2553                                prev_mark_ppos = n;
2554        } else
2555                prev_mark_ppos = frame_position - 1;  /* usually - we don't really know */
2556        actual_mark_ppos = STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER ?
2557                                frame_position - 1 : ntohl(STp->buffer->aux->last_mark_ppos);
2558        if (frame_position  != STp->first_frame_position                   ||
2559            frame_seq_numbr != STp->frame_seq_number + (halfway_frame?0:1) ||
2560            prev_mark_ppos  != actual_mark_ppos                            ) {
2561#if DEBUG
2562                printk(OSST_DEB_MSG "%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name,
2563                                  STp->first_frame_position, frame_position, 
2564                                  STp->frame_seq_number + (halfway_frame?0:1),
2565                                  frame_seq_numbr, actual_mark_ppos, prev_mark_ppos);
2566#endif
2567                return (-EIO);
2568        }
2569        if (halfway_frame) {
2570                /* prepare buffer for append and rewrite on top of original */
2571                osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2572                STp->buffer->buffer_bytes  = read_pointer;
2573                STp->ps[STp->partition].rw = ST_WRITING;
2574                STp->dirty                 = 1;
2575        }
2576        STp->frame_in_buffer  = halfway_frame;
2577        STp->frame_seq_number = frame_seq_numbr;
2578        STp->logical_blk_num  = logical_blk_num;
2579        return 0;
2580}
2581
2582/* Acc. to OnStream, the vers. numbering is the following:
2583 * X.XX for released versions (X=digit), 
2584 * XXXY for unreleased versions (Y=letter)
2585 * Ordering 1.05 < 106A < 106B < ...  < 106a < ... < 1.06
2586 * This fn makes monoton numbers out of this scheme ...
2587 */
2588static unsigned int osst_parse_firmware_rev (const char * str)
2589{
2590        if (str[1] == '.') {
2591                return (str[0]-'0')*10000
2592                        +(str[2]-'0')*1000
2593                        +(str[3]-'0')*100;
2594        } else {
2595                return (str[0]-'0')*10000
2596                        +(str[1]-'0')*1000
2597                        +(str[2]-'0')*100 - 100
2598                        +(str[3]-'@');
2599        }
2600}
2601
2602/*
2603 * Configure the OnStream SCII tape drive for default operation
2604 */
2605static int osst_configure_onstream(struct osst_tape *STp, struct osst_request ** aSRpnt)
2606{
2607        unsigned char                  cmd[MAX_COMMAND_SIZE];
2608        char                         * name = tape_name(STp);
2609        struct osst_request          * SRpnt = * aSRpnt;
2610        osst_mode_parameter_header_t * header;
2611        osst_block_size_page_t       * bs;
2612        osst_capabilities_page_t     * cp;
2613        osst_tape_paramtr_page_t     * prm;
2614        int                            drive_buffer_size;
2615
2616        if (STp->ready != ST_READY) {
2617#if DEBUG
2618            printk(OSST_DEB_MSG "%s:D: Not Ready\n", name);
2619#endif
2620            return (-EIO);
2621        }
2622        
2623        if (STp->os_fw_rev < 10600) {
2624            printk(KERN_INFO "%s:I: Old OnStream firmware revision detected (%s),\n", name, STp->device->rev);
2625            printk(KERN_INFO "%s:I: an upgrade to version 1.06 or above is recommended\n", name);
2626        }
2627
2628        /*
2629         * Configure 32.5KB (data+aux) frame size.
2630         * Get the current frame size from the block size mode page
2631         */
2632        memset(cmd, 0, MAX_COMMAND_SIZE);
2633        cmd[0] = MODE_SENSE;
2634        cmd[1] = 8;
2635        cmd[2] = BLOCK_SIZE_PAGE;
2636        cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2637
2638        SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2639        if (SRpnt == NULL) {
2640#if DEBUG
2641            printk(OSST_DEB_MSG "osst :D: Busy\n");
2642#endif
2643            return (-EBUSY);
2644        }
2645        *aSRpnt = SRpnt;
2646        if ((STp->buffer)->syscall_result != 0) {
2647            printk (KERN_ERR "%s:E: Can't get tape block size mode page\n", name);
2648            return (-EIO);
2649        }
2650
2651        header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2652        bs = (osst_block_size_page_t *) ((STp->buffer)->b_data + sizeof(osst_mode_parameter_header_t) + header->bdl);
2653
2654#if DEBUG
2655        printk(OSST_DEB_MSG "%s:D: 32KB play back: %s\n",   name, bs->play32     ? "Yes" : "No");
2656        printk(OSST_DEB_MSG "%s:D: 32.5KB play back: %s\n", name, bs->play32_5   ? "Yes" : "No");
2657        printk(OSST_DEB_MSG "%s:D: 32KB record: %s\n",      name, bs->record32   ? "Yes" : "No");
2658        printk(OSST_DEB_MSG "%s:D: 32.5KB record: %s\n",    name, bs->record32_5 ? "Yes" : "No");
2659#endif
2660
2661        /*
2662         * Configure default auto columns mode, 32.5KB transfer mode
2663         */ 
2664        bs->one = 1;
2665        bs->play32 = 0;
2666        bs->play32_5 = 1;
2667        bs->record32 = 0;
2668        bs->record32_5 = 1;
2669
2670        memset(cmd, 0, MAX_COMMAND_SIZE);
2671        cmd[0] = MODE_SELECT;
2672        cmd[1] = 0x10;
2673        cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2674
2675        SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2676        *aSRpnt = SRpnt;
2677        if ((STp->buffer)->syscall_result != 0) {
2678            printk (KERN_ERR "%s:E: Couldn't set tape block size mode page\n", name);
2679            return (-EIO);
2680        }
2681
2682#if DEBUG
2683        printk(KERN_INFO "%s:D: Drive Block Size changed to 32.5K\n", name);
2684         /*
2685         * In debug mode, we want to see as many errors as possible
2686         * to test the error recovery mechanism.
2687         */
2688        osst_set_retries(STp, aSRpnt, 0);
2689        SRpnt = * aSRpnt;
2690#endif
2691
2692        /*
2693         * Set vendor name to 'LIN4' for "Linux support version 4".
2694         */
2695
2696        memset(cmd, 0, MAX_COMMAND_SIZE);
2697        cmd[0] = MODE_SELECT;
2698        cmd[1] = 0x10;
2699        cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
2700
2701        header->mode_data_length = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH - 1;
2702        header->medium_type      = 0;   /* Medium Type - ignoring */
2703        header->dsp              = 0;   /* Reserved */
2704        header->bdl              = 0;   /* Block Descriptor Length */
2705        
2706        (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = VENDOR_IDENT_PAGE | (1 << 7);
2707        (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 6;
2708        (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 'L';
2709        (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 'I';
2710        (STp->buffer)->b_data[MODE_HEADER_LENGTH + 4] = 'N';
2711        (STp->buffer)->b_data[MODE_HEADER_LENGTH + 5] = '4';
2712        (STp->buffer)->b_data[MODE_HEADER_LENGTH + 6] = 0;
2713        (STp->buffer)->b_data[MODE_HEADER_LENGTH + 7] = 0;
2714
2715        SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2716        *aSRpnt = SRpnt;
2717
2718        if ((STp->buffer)->syscall_result != 0) {
2719            printk (KERN_ERR "%s:E: Couldn't set vendor name to %s\n", name, 
2720                        (char *) ((STp->buffer)->b_data + MODE_HEADER_LENGTH + 2));
2721            return (-EIO);
2722        }
2723
2724        memset(cmd, 0, MAX_COMMAND_SIZE);
2725        cmd[0] = MODE_SENSE;
2726        cmd[1] = 8;
2727        cmd[2] = CAPABILITIES_PAGE;
2728        cmd[4] = CAPABILITIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2729
2730        SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2731        *aSRpnt = SRpnt;
2732
2733        if ((STp->buffer)->syscall_result != 0) {
2734            printk (KERN_ERR "%s:E: Can't get capabilities page\n", name);
2735            return (-EIO);
2736        }
2737
2738        header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2739        cp     = (osst_capabilities_page_t    *) ((STp->buffer)->b_data +
2740                 sizeof(osst_mode_parameter_header_t) + header->bdl);
2741
2742        drive_buffer_size = ntohs(cp->buffer_size) / 2;
2743
2744        memset(cmd, 0, MAX_COMMAND_SIZE);
2745        cmd[0] = MODE_SENSE;
2746        cmd[1] = 8;
2747        cmd[2] = TAPE_PARAMTR_PAGE;
2748        cmd[4] = TAPE_PARAMTR_PAGE_LENGTH + MODE_HEADER_LENGTH;
2749
2750        SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2751        *aSRpnt = SRpnt;
2752
2753        if ((STp->buffer)->syscall_result != 0) {
2754            printk (KERN_ERR "%s:E: Can't get tape parameter page\n", name);
2755            return (-EIO);
2756        }
2757
2758        header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2759        prm    = (osst_tape_paramtr_page_t    *) ((STp->buffer)->b_data +
2760                 sizeof(osst_mode_parameter_header_t) + header->bdl);
2761
2762        STp->density  = prm->density;
2763        STp->capacity = ntohs(prm->segtrk) * ntohs(prm->trks);
2764#if DEBUG
2765        printk(OSST_DEB_MSG "%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2766                          name, STp->density, STp->capacity / 32, drive_buffer_size);
2767#endif
2768
2769        return 0;
2770        
2771}
2772
2773
2774/* Step over EOF if it has been inadvertently crossed (ioctl not used because
2775   it messes up the block number). */
2776static int cross_eof(struct osst_tape *STp, struct osst_request ** aSRpnt, int forward)
2777{
2778        int     result;
2779        char  * name = tape_name(STp);
2780
2781#if DEBUG
2782        if (debugging)
2783                printk(OSST_DEB_MSG "%s:D: Stepping over filemark %s.\n",
2784                                  name, forward ? "forward" : "backward");
2785#endif
2786
2787        if (forward) {
2788           /* assumes that the filemark is already read by the drive, so this is low cost */
2789           result = osst_space_over_filemarks_forward_slow(STp, aSRpnt, MTFSF, 1);
2790        }
2791        else
2792           /* assumes this is only called if we just read the filemark! */
2793           result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - 1);
2794
2795        if (result < 0)
2796           printk(KERN_WARNING "%s:W: Stepping over filemark %s failed.\n",
2797                                name, forward ? "forward" : "backward");
2798
2799        return result;
2800}
2801
2802
2803/* Get the tape position. */
2804
2805static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt)
2806{
2807        unsigned char           scmd[MAX_COMMAND_SIZE];
2808        struct osst_request   * SRpnt;
2809        int                     result = 0;
2810        char                  * name   = tape_name(STp);
2811
2812        /* KG: We want to be able to use it for checking Write Buffer availability
2813         *  and thus don't want to risk to overwrite anything. Exchange buffers ... */
2814        char            mybuf[24];
2815        char          * olddata = STp->buffer->b_data;
2816        int             oldsize = STp->buffer->buffer_size;
2817
2818        if (STp->ready != ST_READY) return (-EIO);
2819
2820        memset (scmd, 0, MAX_COMMAND_SIZE);
2821        scmd[0] = READ_POSITION;
2822
2823        STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2824        SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2825                                      STp->timeout, MAX_RETRIES, 1);
2826        if (!SRpnt) {
2827                STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2828                return (-EBUSY);
2829        }
2830        *aSRpnt = SRpnt;
2831
2832        if (STp->buffer->syscall_result)
2833                result = ((SRpnt->sense[2] & 0x0f) == 3) ? -EIO : -EINVAL;      /* 3: Write Error */
2834
2835        if (result == -EINVAL)
2836                printk(KERN_ERR "%s:E: Can't read tape position.\n", name);
2837        else {
2838                if (result == -EIO) {   /* re-read position - this needs to preserve media errors */
2839                        unsigned char mysense[16];
2840                        memcpy (mysense, SRpnt->sense, 16);
2841                        memset (scmd, 0, MAX_COMMAND_SIZE);
2842                        scmd[0] = READ_POSITION;
2843                        STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2844                        SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2845                                                    STp->timeout, MAX_RETRIES, 1);
2846#if DEBUG
2847                        printk(OSST_DEB_MSG "%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2848                                        name, mysense[2], mysense[12], mysense[13], STp->buffer->syscall_result?"":"ok:",
2849                                        SRpnt->sense[2],SRpnt->sense[12],SRpnt->sense[13]);
2850#endif
2851                        if (!STp->buffer->syscall_result)
2852                                memcpy (SRpnt->sense, mysense, 16);
2853                        else
2854                                printk(KERN_WARNING "%s:W: Double error in get position\n", name);
2855                }
2856                STp->first_frame_position = ((STp->buffer)->b_data[4] << 24)
2857                                          + ((STp->buffer)->b_data[5] << 16)
2858                                          + ((STp->buffer)->b_data[6] << 8)
2859                                          +  (STp->buffer)->b_data[7];
2860                STp->last_frame_position  = ((STp->buffer)->b_data[ 8] << 24)
2861                                          + ((STp->buffer)->b_data[ 9] << 16)
2862                                          + ((STp->buffer)->b_data[10] <<  8)
2863                                          +  (STp->buffer)->b_data[11];
2864                STp->cur_frames           =  (STp->buffer)->b_data[15];
2865#if DEBUG
2866                if (debugging) {
2867                        printk(OSST_DEB_MSG "%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name,
2868                                            STp->first_frame_position, STp->last_frame_position,
2869                                            ((STp->buffer)->b_data[0]&0x80)?" (BOP)":
2870                                            ((STp->buffer)->b_data[0]&0x40)?" (EOP)":"",
2871                                            STp->cur_frames);
2872                }
2873#endif
2874                if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
2875#if DEBUG
2876                        printk(OSST_DEB_MSG "%s:D: Correcting read position %d, %d, %d\n", name,
2877                                        STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
2878#endif
2879                        STp->first_frame_position = STp->last_frame_position;
2880                }
2881        }
2882        STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2883
2884        return (result == 0 ? STp->first_frame_position : result);
2885}
2886
2887
2888/* Set the tape block */
2889static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int ppos, int skip)
2890{
2891        unsigned char           scmd[MAX_COMMAND_SIZE];
2892        struct osst_request   * SRpnt;
2893        struct st_partstat    * STps;
2894        int                     result = 0;
2895        int                     pp     = (ppos == 3000 && !skip)? 0 : ppos;
2896        char                  * name   = tape_name(STp);
2897
2898        if (STp->ready != ST_READY) return (-EIO);
2899
2900        STps = &(STp->ps[STp->partition]);
2901
2902        if (ppos < 0 || ppos > STp->capacity) {
2903                printk(KERN_WARNING "%s:W: Reposition request %d out of range\n", name, ppos);
2904                pp = ppos = ppos < 0 ? 0 : (STp->capacity - 1);
2905                result = (-EINVAL);
2906        }
2907
2908        do {
2909#if DEBUG
2910                if (debugging)
2911                        printk(OSST_DEB_MSG "%s:D: Setting ppos to %d.\n", name, pp);
2912#endif
2913                memset (scmd, 0, MAX_COMMAND_SIZE);
2914                scmd[0] = SEEK_10;
2915                scmd[1] = 1;
2916                scmd[3] = (pp >> 24);
2917                scmd[4] = (pp >> 16);
2918                scmd[5] = (pp >> 8);
2919                scmd[6] =  pp;
2920                if (skip)
2921                        scmd[9] = 0x80;
2922
2923                SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, DMA_NONE, STp->long_timeout,
2924                                                                MAX_RETRIES, 1);
2925                if (!SRpnt)
2926                        return (-EBUSY);
2927                *aSRpnt  = SRpnt;
2928
2929                if ((STp->buffer)->syscall_result != 0) {
2930#if DEBUG
2931                        printk(OSST_DEB_MSG "%s:D: SEEK command from %d to %d failed.\n",
2932                                        name, STp->first_frame_position, pp);
2933#endif
2934                        result = (-EIO);
2935                }
2936                if (pp != ppos)
2937                        osst_wait_ready(STp, aSRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
2938        } while ((pp != ppos) && (pp = ppos));
2939        STp->first_frame_position = STp->last_frame_position = ppos;
2940        STps->eof = ST_NOEOF;
2941        STps->at_sm = 0;
2942        STps->rw = ST_IDLE;
2943        STp->frame_in_buffer = 0;
2944        return result;
2945}
2946
2947static int osst_write_trailer(struct osst_tape *STp, struct osst_request ** aSRpnt, int leave_at_EOT)
2948{
2949        struct st_partstat * STps = &(STp->ps[STp->partition]);
2950        int result = 0;
2951
2952        if (STp->write_type != OS_WRITE_NEW_MARK) {
2953                /* true unless the user wrote the filemark for us */
2954                result = osst_flush_drive_buffer(STp, aSRpnt);
2955                if (result < 0) goto out;
2956                result = osst_write_filemark(STp, aSRpnt);
2957                if (result < 0) goto out;
2958
2959                if (STps->drv_file >= 0)
2960                        STps->drv_file++ ;
2961                STps->drv_block = 0;
2962        }
2963        result = osst_write_eod(STp, aSRpnt);
2964        osst_write_header(STp, aSRpnt, leave_at_EOT);
2965
2966        STps->eof = ST_FM;
2967out:
2968        return result;
2969}
2970
2971/* osst versions of st functions - augmented and stripped to suit OnStream only */
2972
2973/* Flush the write buffer (never need to write if variable blocksize). */
2974static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt)
2975{
2976        int                     offset, transfer, blks = 0;
2977        int                     result = 0;
2978        unsigned char           cmd[MAX_COMMAND_SIZE];
2979        struct osst_request   * SRpnt = *aSRpnt;
2980        struct st_partstat    * STps;
2981        char                  * name = tape_name(STp);
2982
2983        if ((STp->buffer)->writing) {
2984                if (SRpnt == (STp->buffer)->last_SRpnt)
2985#if DEBUG
2986                        { printk(OSST_DEB_MSG
2987         "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name);
2988#endif
2989                        *aSRpnt = SRpnt = NULL;
2990#if DEBUG
2991                        } else if (SRpnt)
2992                                printk(OSST_DEB_MSG
2993         "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name);
2994#endif  
2995                osst_write_behind_check(STp);
2996                if ((STp->buffer)->syscall_result) {
2997#if DEBUG
2998                        if (debugging)
2999                                printk(OSST_DEB_MSG "%s:D: Async write error (flush) %x.\n",
3000                                       name, (STp->buffer)->midlevel_result);
3001#endif
3002                        if ((STp->buffer)->midlevel_result == INT_MAX)
3003                                return (-ENOSPC);
3004                        return (-EIO);
3005                }
3006        }
3007
3008        result = 0;
3009        if (STp->dirty == 1) {
3010
3011                STp->write_count++;
3012                STps     = &(STp->ps[STp->partition]);
3013                STps->rw = ST_WRITING;
3014                offset   = STp->buffer->buffer_bytes;
3015                blks     = (offset + STp->block_size - 1) / STp->block_size;
3016                transfer = OS_FRAME_SIZE;
3017                
3018                if (offset < OS_DATA_SIZE)
3019                        osst_zero_buffer_tail(STp->buffer);
3020
3021                if (STp->poll)
3022                        if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120))
3023                                result = osst_recover_wait_frame(STp, aSRpnt, 1);
3024
3025                memset(cmd, 0, MAX_COMMAND_SIZE);
3026                cmd[0] = WRITE_6;
3027                cmd[1] = 1;
3028                cmd[4] = 1;
3029
3030                switch  (STp->write_type) {
3031                   case OS_WRITE_DATA:
3032#if DEBUG
3033                        if (debugging)
3034                                printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
3035                                        name, blks, STp->frame_seq_number, 
3036                                        STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3037#endif
3038                        osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3039                                      STp->logical_blk_num - blks, STp->block_size, blks);
3040                        break;
3041                   case OS_WRITE_EOD:
3042                        osst_init_aux(STp, OS_FRAME_TYPE_EOD, STp->frame_seq_number++,
3043                                      STp->logical_blk_num, 0, 0);
3044                        break;
3045                   case OS_WRITE_NEW_MARK:
3046                        osst_init_aux(STp, OS_FRAME_TYPE_MARKER, STp->frame_seq_number++,
3047                                      STp->logical_blk_num++, 0, blks=1);
3048                        break;
3049                   case OS_WRITE_HEADER:
3050                        osst_init_aux(STp, OS_FRAME_TYPE_HEADER, 0, 0, 0, blks=0);
3051                        break;
3052                default: /* probably FILLER */
3053                        osst_init_aux(STp, OS_FRAME_TYPE_FILL, 0, 0, 0, 0);
3054                }
3055#if DEBUG
3056                if (debugging)
3057                        printk(OSST_DEB_MSG "%s:D: Flushing %d bytes, Transfering %d bytes in %d lblocks.\n",
3058                                                 name, offset, transfer, blks);
3059#endif
3060
3061                SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, DMA_TO_DEVICE,
3062                                              STp->timeout, MAX_RETRIES, 1);
3063                *aSRpnt = SRpnt;
3064                if (!SRpnt)
3065                        return (-EBUSY);
3066
3067                if ((STp->buffer)->syscall_result != 0) {
3068#if DEBUG
3069                        printk(OSST_DEB_MSG
3070                                "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3071                                name, SRpnt->sense[0], SRpnt->sense[2],
3072                                SRpnt->sense[12], SRpnt->sense[13]);
3073#endif
3074                        if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3075                            (SRpnt->sense[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
3076                            (SRpnt->sense[2] & 0x0f) == NO_SENSE) {
3077                                STp->dirty = 0;
3078                                (STp->buffer)->buffer_bytes = 0;
3079                                result = (-ENOSPC);
3080                        }
3081                        else {
3082                                if (osst_write_error_recovery(STp, aSRpnt, 1)) {
3083                                        printk(KERN_ERR "%s:E: Error on flush write.\n", name);
3084                                        result = (-EIO);
3085                                }
3086                        }
3087                        STps->drv_block = (-1);         /* FIXME - even if write recovery succeeds? */
3088                }
3089                else {
3090                        STp->first_frame_position++;
3091                        STp->dirty = 0;
3092                        (STp->buffer)->buffer_bytes = 0;
3093                }
3094        }
3095#if DEBUG
3096        printk(OSST_DEB_MSG "%s:D: Exit flush write buffer with code %d\n", name, result);
3097#endif
3098        return result;
3099}
3100
3101
3102/* Flush the tape buffer. The tape will be positioned correctly unless
3103   seek_next is true. */
3104static int osst_flush_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt, int seek_next)
3105{
3106        struct st_partstat * STps;
3107        int    backspace = 0, result = 0;
3108#if DEBUG
3109        char * name = tape_name(STp);
3110#endif
3111
3112        /*
3113         * If there was a bus reset, block further access
3114         * to this device.
3115         */
3116        if( STp->pos_unknown)
3117                return (-EIO);
3118
3119        if (STp->ready != ST_READY)
3120                return 0;
3121
3122        STps = &(STp->ps[STp->partition]);
3123        if (STps->rw == ST_WRITING || STp->dirty) {     /* Writing */
3124                STp->write_type = OS_WRITE_DATA;
3125                return osst_flush_write_buffer(STp, aSRpnt);
3126        }
3127        if (STp->block_size == 0)
3128                return 0;
3129
3130#if DEBUG
3131        printk(OSST_DEB_MSG "%s:D: Reached flush (read) buffer\n", name);
3132#endif
3133
3134        if (!STp->can_bsr) {
3135                backspace = ((STp->buffer)->buffer_bytes + (STp->buffer)->read_pointer) / STp->block_size -
3136                            ((STp->buffer)->read_pointer + STp->block_size - 1        ) / STp->block_size ;
3137                (STp->buffer)->buffer_bytes = 0;
3138                (STp->buffer)->read_pointer = 0;
3139                STp->frame_in_buffer = 0;               /* FIXME is this relevant w. OSST? */
3140        }
3141
3142        if (!seek_next) {
3143                if (STps->eof == ST_FM_HIT) {
3144                        result = cross_eof(STp, aSRpnt, 0); /* Back over the EOF hit */
3145                        if (!result)
3146                                STps->eof = ST_NOEOF;
3147                        else {
3148                                if (STps->drv_file >= 0)
3149                                        STps->drv_file++;
3150                                STps->drv_block = 0;
3151                        }
3152                }
3153                if (!result && backspace > 0)   /* TODO -- design and run a test case for this */
3154                        result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - backspace);
3155        }
3156        else if (STps->eof == ST_FM_HIT) {
3157                if (STps->drv_file >= 0)
3158                        STps->drv_file++;
3159                STps->drv_block = 0;
3160                STps->eof = ST_NOEOF;
3161        }
3162
3163        return result;
3164}
3165
3166static int osst_write_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int synchronous)
3167{
3168        unsigned char           cmd[MAX_COMMAND_SIZE];
3169        struct osst_request   * SRpnt;
3170        int                     blks;
3171#if DEBUG
3172        char                  * name = tape_name(STp);
3173#endif
3174
3175        if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) { /* _must_ preserve buffer! */
3176#if DEBUG
3177                printk(OSST_DEB_MSG "%s:D: Reaching config partition.\n", name);
3178#endif
3179                if (osst_flush_drive_buffer(STp, aSRpnt) < 0) {
3180                        return (-EIO);
3181                }
3182                /* error recovery may have bumped us past the header partition */
3183                if (osst_get_frame_position(STp, aSRpnt) < 0xbb8) {
3184#if DEBUG
3185                        printk(OSST_DEB_MSG "%s:D: Skipping over config partition.\n", name);
3186#endif
3187                osst_position_tape_and_confirm(STp, aSRpnt, 0xbb8);
3188                }
3189        }
3190
3191        if (STp->poll)
3192                if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -48, 120))
3193                        if (osst_recover_wait_frame(STp, aSRpnt, 1))
3194                                return (-EIO);
3195
3196//      osst_build_stats(STp, &SRpnt);
3197
3198        STp->ps[STp->partition].rw = ST_WRITING;
3199        STp->write_type            = OS_WRITE_DATA;
3200                        
3201        memset(cmd, 0, MAX_COMMAND_SIZE);
3202        cmd[0]   = WRITE_6;
3203        cmd[1]   = 1;
3204        cmd[4]   = 1;                                           /* one frame at a time... */
3205        blks     = STp->buffer->buffer_bytes / STp->block_size;
3206#if DEBUG
3207        if (debugging)
3208                printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name, blks, 
3209                        STp->frame_seq_number, STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3210#endif
3211        osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3212                      STp->logical_blk_num - blks, STp->block_size, blks);
3213
3214#if DEBUG
3215        if (!synchronous)
3216                STp->write_pending = 1;
3217#endif
3218        SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE, STp->timeout,
3219                                                                        MAX_RETRIES, synchronous);
3220        if (!SRpnt)
3221                return (-EBUSY);
3222        *aSRpnt = SRpnt;
3223
3224        if (synchronous) {
3225                if (STp->buffer->syscall_result != 0) {
3226#if DEBUG
3227                        if (debugging)
3228                                printk(OSST_DEB_MSG "%s:D: Error on write:\n", name);
3229#endif
3230                        if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3231                            (SRpnt->sense[2] & 0x40)) {
3232                                if ((SRpnt->sense[2] & 0x0f) == VOLUME_OVERFLOW)
3233                                        return (-ENOSPC);
3234                        }
3235                        else {
3236                                if (osst_write_error_recovery(STp, aSRpnt, 1))
3237                                        return (-EIO);
3238                        }
3239                }
3240                else
3241                        STp->first_frame_position++;
3242        }
3243
3244        STp->write_count++;
3245
3246        return 0;
3247}
3248
3249/* Lock or unlock the drive door. Don't use when struct osst_request allocated. */
3250static int do_door_lock(struct osst_tape * STp, int do_lock)
3251{
3252        int retval, cmd;
3253
3254        cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK;
3255#if DEBUG
3256        printk(OSST_DEB_MSG "%s:D: %socking drive door.\n", tape_name(STp), do_lock ? "L" : "Unl");
3257#endif
3258        retval = scsi_ioctl(STp->device, cmd, NULL);
3259        if (!retval) {
3260                STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
3261        }
3262        else {
3263                STp->door_locked = ST_LOCK_FAILS;
3264        }
3265        return retval;
3266}
3267
3268/* Set the internal state after reset */
3269static void reset_state(struct osst_tape *STp)
3270{
3271        int i;
3272        struct st_partstat *STps;
3273
3274        STp->pos_unknown = 0;
3275        for (i = 0; i < ST_NBR_PARTITIONS; i++) {
3276                STps = &(STp->ps[i]);
3277                STps->rw = ST_IDLE;
3278                STps->eof = ST_NOEOF;
3279                STps->at_sm = 0;
3280                STps->last_block_valid = 0;
3281                STps->drv_block = -1;
3282                STps->drv_file = -1;
3283        }
3284}
3285                                
3286
3287/* Entry points to osst */
3288
3289/* Write command */
3290static ssize_t osst_write(struct file * filp, const char __user * buf, size_t count, loff_t *ppos)
3291{
3292        ssize_t               total, retval = 0;
3293        ssize_t               i, do_count, blks, transfer;
3294        int                   write_threshold;
3295        int                   doing_write = 0;
3296        const char   __user * b_point;
3297        struct osst_request * SRpnt = NULL;
3298        struct st_modedef   * STm;
3299        struct st_partstat  * STps;
3300        struct osst_tape    * STp  = filp->private_data;
3301        char                * name = tape_name(STp);
3302
3303
3304        if (mutex_lock_interruptible(&STp->lock))
3305                return (-ERESTARTSYS);
3306
3307        /*
3308         * If we are in the middle of error recovery, don't let anyone
3309         * else try and use this device.  Also, if error recovery fails, it
3310         * may try and take the device offline, in which case all further
3311         * access to the device is prohibited.
3312         */
3313        if( !scsi_block_when_processing_errors(STp->device) ) {
3314                retval = (-ENXIO);
3315                goto out;
3316        }
3317        
3318        if (STp->ready != ST_READY) {
3319                if (STp->ready == ST_NO_TAPE)
3320                        retval = (-ENOMEDIUM);
3321                else
3322                        retval = (-EIO);
3323                goto out;
3324        }
3325        STm = &(STp->modes[STp->current_mode]);
3326        if (!STm->defined) {
3327                retval = (-ENXIO);
3328                goto out;
3329        }
3330        if (count == 0)
3331                goto out;
3332
3333        /*
3334         * If there was a bus reset, block further access
3335         * to this device.
3336         */
3337        if (STp->pos_unknown) {
3338                retval = (-EIO);
3339                goto out;
3340        }
3341
3342#if DEBUG
3343        if (!STp->in_use) {
3344                printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3345                retval = (-EIO);
3346                goto out;
3347        }
3348#endif
3349
3350        if (STp->write_prot) {
3351                retval = (-EACCES);
3352                goto out;
3353        }
3354
3355        /* Write must be integral number of blocks */
3356        if (STp->block_size != 0 && (count % STp->block_size) != 0) {
3357                printk(KERN_ERR "%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3358                                       name, count, STp->block_size<1024?
3359                                       STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3360                retval = (-EINVAL);
3361                goto out;
3362        }
3363
3364        if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) {
3365                printk(KERN_ERR "%s:E: Write truncated at EOM early warning (frame %d).\n",
3366                                       name, STp->first_frame_position);
3367                retval = (-ENOSPC);
3368                goto out;
3369        }
3370
3371        if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3372                STp->door_locked = ST_LOCKED_AUTO;
3373
3374        STps = &(STp->ps[STp->partition]);
3375
3376        if (STps->rw == ST_READING) {
3377#if DEBUG
3378                printk(OSST_DEB_MSG "%s:D: Switching from read to write at file %d, block %d\n", name, 
3379                                        STps->drv_file, STps->drv_block);
3380#endif
3381                retval = osst_flush_buffer(STp, &SRpnt, 0);
3382                if (retval)
3383                        goto out;
3384                STps->rw = ST_IDLE;
3385        }
3386        if (STps->rw != ST_WRITING) {
3387                /* Are we totally rewriting this tape? */
3388                if (!STp->header_ok ||
3389                    (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
3390                    (STps->drv_file == 0 && STps->drv_block == 0)) {
3391                        STp->wrt_pass_cntr++;
3392#if DEBUG
3393                        printk(OSST_DEB_MSG "%s:D: Allocating next write pass counter: %d\n",
3394                                                  name, STp->wrt_pass_cntr);
3395#endif
3396                        osst_reset_header(STp, &SRpnt);
3397                        STps->drv_file = STps->drv_block = 0;
3398                }
3399                /* Do we know where we'll be writing on the tape? */
3400                else {
3401                        if ((STp->fast_open && osst_verify_position(STp, &SRpnt)) ||
3402                                        STps->drv_file < 0 || STps->drv_block < 0) {
3403                                if (STp->first_frame_position == STp->eod_frame_ppos) { /* at EOD */
3404                                        STps->drv_file = STp->filemark_cnt;
3405                                        STps->drv_block = 0;
3406                                }
3407                                else {
3408                                        /* We have no idea where the tape is positioned - give up */
3409#if DEBUG
3410                                        printk(OSST_DEB_MSG
3411                                                "%s:D: Cannot write at indeterminate position.\n", name);
3412#endif
3413                                        retval = (-EIO);
3414                                        goto out;
3415                                }
3416                        }         
3417                        if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) {
3418                                STp->filemark_cnt = STps->drv_file;
3419                                STp->last_mark_ppos =
3420                                        ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]);
3421                                printk(KERN_WARNING
3422                                        "%s:W: Overwriting file %d with old write pass counter %d\n",
3423                                                name, STps->drv_file, STp->wrt_pass_cntr);
3424                                printk(KERN_WARNING
3425                                        "%s:W: may lead to stale data being accepted on reading back!\n",
3426                                                name);
3427#if DEBUG
3428                                printk(OSST_DEB_MSG
3429                                  "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3430                                        name, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn);
3431#endif
3432                        }
3433                }
3434                STp->fast_open = 0;
3435        }
3436        if (!STp->header_ok) {
3437#if DEBUG
3438                printk(OSST_DEB_MSG "%s:D: Write cannot proceed without valid headers\n", name);
3439#endif
3440                retval = (-EIO);
3441                goto out;
3442        }
3443
3444        if ((STp->buffer)->writing) {
3445if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name, __LINE__);
3446                osst_write_behind_check(STp);
3447                if ((STp->buffer)->syscall_result) {
3448#if DEBUG
3449                if (debugging)
3450                        printk(OSST_DEB_MSG "%s:D: Async write error (write) %x.\n", name,
3451                                                 (STp->buffer)->midlevel_result);
3452#endif
3453                if ((STp->buffer)->midlevel_result == INT_MAX)
3454                        STps->eof = ST_EOM_OK;
3455                else
3456                        STps->eof = ST_EOM_ERROR;
3457                }
3458        }
3459        if (STps->eof == ST_EOM_OK) {
3460                retval = (-ENOSPC);
3461                goto out;
3462        }
3463        else if (STps->eof == ST_EOM_ERROR) {
3464                retval = (-EIO);
3465                goto out;
3466        }
3467
3468        /* Check the buffer readability in cases where copy_user might catch
3469                 the problems after some tape movement. */
3470        if ((copy_from_user(&i, buf, 1) != 0 ||
3471             copy_from_user(&i, buf + count - 1, 1) != 0)) {
3472                retval = (-EFAULT);
3473                goto out;
3474        }
3475
3476        if (!STm->do_buffer_writes) {
3477                write_threshold = 1;
3478        }
3479        else
3480                write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;
3481        if (!STm->do_async_writes)
3482                write_threshold--;
3483
3484        total = count;
3485#if DEBUG
3486        if (debugging)
3487                printk(OSST_DEB_MSG "%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3488                                name, (int) count, STps->drv_file, STps->drv_block,
3489                                STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
3490#endif
3491        b_point = buf;
3492        while ((STp->buffer)->buffer_bytes + count > write_threshold)
3493        {
3494                doing_write = 1;
3495                do_count = (STp->buffer)->buffer_blocks * STp->block_size -
3496                           (STp->buffer)->buffer_bytes;
3497                if (do_count > count)
3498                        do_count = count;
3499
3500                i = append_to_buffer(b_point, STp->buffer, do_count);
3501                if (i) {
3502                        retval = i;
3503                        goto out;
3504                }
3505
3506                blks = do_count / STp->block_size;
3507                STp->logical_blk_num += blks;  /* logical_blk_num is incremented as data is moved from user */
3508  
3509                i = osst_write_frame(STp, &SRpnt, 1);
3510
3511                if (i == (-ENOSPC)) {
3512                        transfer = STp->buffer->writing;        /* FIXME -- check this logic */
3513                        if (transfer <= do_count) {
3514                                filp->f_pos += do_count - transfer;
3515                                count -= do_count - transfer;
3516                                if (STps->drv_block >= 0) {
3517                                        STps->drv_block += (do_count - transfer) / STp->block_size;
3518                                }
3519                                STps->eof = ST_EOM_OK;
3520                                retval = (-ENOSPC);             /* EOM within current request */
3521#if DEBUG
3522                                if (debugging)
3523                                      printk(OSST_DEB_MSG "%s:D: EOM with %d bytes unwritten.\n",
3524                                                             name, (int) transfer);
3525#endif
3526                        }
3527                        else {
3528                                STps->eof = ST_EOM_ERROR;
3529                                STps->drv_block = (-1);         /* Too cautious? */
3530                                retval = (-EIO);                /* EOM for old data */
3531#if DEBUG
3532                                if (debugging)
3533                                      printk(OSST_DEB_MSG "%s:D: EOM with lost data.\n", name);
3534#endif
3535                        }
3536                }
3537                else
3538                        retval = i;
3539                        
3540                if (retval < 0) {
3541                        if (SRpnt != NULL) {
3542                                osst_release_request(SRpnt);
3543                                SRpnt = NULL;
3544                        }
3545                        STp->buffer->buffer_bytes = 0;
3546                        STp->dirty = 0;
3547                        if (count < total)
3548                                retval = total - count;
3549                        goto out;
3550                }
3551
3552                filp->f_pos += do_count;
3553                b_point += do_count;
3554                count -= do_count;
3555                if (STps->drv_block >= 0) {
3556                        STps->drv_block += blks;
3557                }
3558                STp->buffer->buffer_bytes = 0;
3559                STp->dirty = 0;
3560        }  /* end while write threshold exceeded */
3561
3562        if (count != 0) {
3563                STp->dirty = 1;
3564                i = append_to_buffer(b_point, STp->buffer, count);
3565                if (i) {
3566                        retval = i;
3567                        goto out;
3568                }
3569                blks = count / STp->block_size;
3570                STp->logical_blk_num += blks;
3571                if (STps->drv_block >= 0) {
3572                        STps->drv_block += blks;
3573                }
3574                filp->f_pos += count;
3575                count = 0;
3576        }
3577
3578        if (doing_write && (STp->buffer)->syscall_result != 0) {
3579                retval = (STp->buffer)->syscall_result;
3580                goto out;
3581        }
3582
3583        if (STm->do_async_writes && ((STp->buffer)->buffer_bytes >= STp->write_threshold)) { 
3584                /* Schedule an asynchronous write */
3585                (STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
3586                                           STp->block_size) * STp->block_size;
3587                STp->dirty = !((STp->buffer)->writing ==
3588                                          (STp->buffer)->buffer_bytes);
3589
3590                i = osst_write_frame(STp, &SRpnt, 0);
3591                if (i < 0) {
3592                        retval = (-EIO);
3593                        goto out;
3594                }
3595                SRpnt = NULL;                   /* Prevent releasing this request! */
3596        }
3597        STps->at_sm &= (total == 0);
3598        if (total > 0)
3599                STps->eof = ST_NOEOF;
3600
3601        retval = total;
3602
3603out:
3604        if (SRpnt != NULL) osst_release_request(SRpnt);
3605
3606        mutex_unlock(&STp->lock);
3607
3608        return retval;
3609}
3610
3611
3612/* Read command */
3613static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, loff_t *ppos)
3614{
3615        ssize_t               total, retval = 0;
3616        ssize_t               i, transfer;
3617        int                   special;
3618        struct st_modedef   * STm;
3619        struct st_partstat  * STps;
3620        struct osst_request * SRpnt = NULL;
3621        struct osst_tape    * STp   = filp->private_data;
3622        char                * name  = tape_name(STp);
3623
3624
3625        if (mutex_lock_interruptible(&STp->lock))
3626                return (-ERESTARTSYS);
3627
3628        /*
3629         * If we are in the middle of error recovery, don't let anyone
3630         * else try and use this device.  Also, if error recovery fails, it
3631         * may try and take the device offline, in which case all further
3632         * access to the device is prohibited.
3633         */
3634        if( !scsi_block_when_processing_errors(STp->device) ) {
3635                retval = (-ENXIO);
3636                goto out;
3637        }
3638        
3639        if (STp->ready != ST_READY) {
3640                if (STp->ready == ST_NO_TAPE)
3641                        retval = (-ENOMEDIUM);
3642                else
3643                        retval = (-EIO);
3644                goto out;
3645        }
3646        STm = &(STp->modes[STp->current_mode]);
3647        if (!STm->defined) {
3648                retval = (-ENXIO);
3649                goto out;
3650        }
3651#if DEBUG
3652        if (!STp->in_use) {
3653                printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3654                retval = (-EIO);
3655                goto out;
3656        }
3657#endif
3658        /* Must have initialized medium */
3659        if (!STp->header_ok) {
3660                retval = (-EIO);
3661                goto out;
3662        }
3663
3664        if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3665                STp->door_locked = ST_LOCKED_AUTO;
3666
3667        STps = &(STp->ps[STp->partition]);
3668        if (STps->rw == ST_WRITING) {
3669                retval = osst_flush_buffer(STp, &SRpnt, 0);
3670                if (retval)
3671                        goto out;
3672                STps->rw = ST_IDLE;
3673                /* FIXME -- this may leave the tape without EOD and up2date headers */
3674        }
3675
3676        if ((count % STp->block_size) != 0) {
3677                printk(KERN_WARNING
3678                    "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name, count,
3679                    STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3680        }
3681
3682#if DEBUG
3683        if (debugging && STps->eof != ST_NOEOF)
3684                printk(OSST_DEB_MSG "%s:D: EOF/EOM flag up (%d). Bytes %d\n", name,
3685                                     STps->eof, (STp->buffer)->buffer_bytes);
3686#endif
3687        if ((STp->buffer)->buffer_bytes == 0 &&
3688             STps->eof >= ST_EOD_1) {
3689                if (STps->eof < ST_EOD) {
3690                        STps->eof += 1;
3691                        retval = 0;
3692                        goto out;
3693                }
3694                retval = (-EIO);  /* EOM or Blank Check */
3695                goto out;
3696        }
3697
3698        /* Check the buffer writability before any tape movement. Don't alter
3699                 buffer data. */
3700        if (copy_from_user(&i, buf, 1)             != 0 ||
3701            copy_to_user  (buf, &i, 1)             != 0 ||
3702            copy_from_user(&i, buf + count - 1, 1) != 0 ||
3703            copy_to_user  (buf + count - 1, &i, 1) != 0) {
3704                retval = (-EFAULT);
3705                goto out;
3706        }
3707
3708        /* Loop until enough data in buffer or a special condition found */
3709        for (total = 0, special = 0; total < count - STp->block_size + 1 && !special; ) {
3710
3711                /* Get new data if the buffer is empty */
3712                if ((STp->buffer)->buffer_bytes == 0) {
3713                        if (STps->eof == ST_FM_HIT)
3714                                break;
3715                        special = osst_get_logical_frame(STp, &SRpnt, STp->frame_seq_number, 0);
3716                        if (special < 0) {                      /* No need to continue read */
3717                                STp->frame_in_buffer = 0;
3718                                retval = special;
3719                                goto out;
3720                        }
3721                }
3722
3723                /* Move the data from driver buffer to user buffer */
3724                if ((STp->buffer)->buffer_bytes > 0) {
3725#if DEBUG
3726                        if (debugging && STps->eof != ST_NOEOF)
3727                            printk(OSST_DEB_MSG "%s:D: EOF up (%d). Left %d, needed %d.\n", name,
3728                                                 STps->eof, (STp->buffer)->buffer_bytes, (int) (count - total));
3729#endif
3730                        /* force multiple of block size, note block_size may have been adjusted */
3731                        transfer = (((STp->buffer)->buffer_bytes < count - total ?
3732                                     (STp->buffer)->buffer_bytes : count - total)/
3733                                        STp->block_size) * STp->block_size;
3734
3735                        if (transfer == 0) {
3736                                printk(KERN_WARNING
3737                                  "%s:W: Nothing can be transfered, requested %Zd, tape block size (%d%c).\n",
3738                                        name, count, STp->block_size < 1024?
3739                                        STp->block_size:STp->block_size/1024,
3740                                        STp->block_size<1024?'b':'k');
3741                                break;
3742                        }
3743                        i = from_buffer(STp->buffer, buf, transfer);
3744                        if (i)  {
3745                                retval = i;
3746                                goto out;
3747                        }
3748                        STp->logical_blk_num += transfer / STp->block_size;
3749                        STps->drv_block      += transfer / STp->block_size;
3750                        filp->f_pos          += transfer;
3751                        buf                  += transfer;
3752                        total                += transfer;
3753                }
3754 
3755                if ((STp->buffer)->buffer_bytes == 0) {
3756#if DEBUG
3757                        if (debugging)
3758                                printk(OSST_DEB_MSG "%s:D: Finished with frame %d\n",
3759                                                name, STp->frame_seq_number);
3760#endif
3761                        STp->frame_in_buffer = 0;
3762                        STp->frame_seq_number++;              /* frame to look for next time */
3763                }
3764        } /* for (total = 0, special = 0; total < count && !special; ) */
3765
3766        /* Change the eof state if no data from tape or buffer */
3767        if (total == 0) {
3768                if (STps->eof == ST_FM_HIT) {
3769                        STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD_2:ST_FM;
3770                        STps->drv_block = 0;
3771                        if (STps->drv_file >= 0)
3772                                STps->drv_file++;
3773                }
3774                else if (STps->eof == ST_EOD_1) {
3775                        STps->eof = ST_EOD_2;
3776                        if (STps->drv_block > 0 && STps->drv_file >= 0)
3777                                STps->drv_file++;
3778                        STps->drv_block = 0;
3779                }
3780                else if (STps->eof == ST_EOD_2)
3781                        STps->eof = ST_EOD;
3782        }
3783        else if (STps->eof == ST_FM)
3784                STps->eof = ST_NOEOF;
3785
3786        retval = total;
3787
3788out:
3789        if (SRpnt != NULL) osst_release_request(SRpnt);
3790
3791        mutex_unlock(&STp->lock);
3792
3793        return retval;
3794}
3795
3796
3797/* Set the driver options */
3798static void osst_log_options(struct osst_tape *STp, struct st_modedef *STm, char *name)
3799{
3800  printk(KERN_INFO
3801"%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3802         name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
3803         STm->do_read_ahead);
3804  printk(KERN_INFO
3805"%s:I:    can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3806         name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
3807  printk(KERN_INFO
3808"%s:I:    defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3809         name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
3810         STp->scsi2_logical);
3811  printk(KERN_INFO
3812"%s:I:    sysv: %d\n", name, STm->sysv);
3813#if DEBUG
3814  printk(KERN_INFO
3815         "%s:D:    debugging: %d\n",
3816         name, debugging);
3817#endif
3818}
3819
3820
3821static int osst_set_options(struct osst_tape *STp, long options)
3822{
3823        int                 value;
3824        long                code;
3825        struct st_modedef * STm;
3826        char              * name = tape_name(STp);
3827
3828        STm = &(STp->modes[STp->current_mode]);
3829        if (!STm->defined) {
3830                memcpy(STm, &(STp->modes[0]), sizeof(*STm));
3831                modes_defined = 1;
3832#if DEBUG
3833                if (debugging)
3834                        printk(OSST_DEB_MSG "%s:D: Initialized mode %d definition from mode 0\n",
3835                                             name, STp->current_mode);
3836#endif
3837        }
3838
3839        code = options & MT_ST_OPTIONS;
3840        if (code == MT_ST_BOOLEANS) {
3841                STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
3842                STm->do_async_writes  = (options & MT_ST_ASYNC_WRITES) != 0;
3843                STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
3844                STm->do_read_ahead    = (options & MT_ST_READ_AHEAD) != 0;
3845                STp->two_fm           = (options & MT_ST_TWO_FM) != 0;
3846                STp->fast_mteom       = (options & MT_ST_FAST_MTEOM) != 0;
3847                STp->do_auto_lock     = (options & MT_ST_AUTO_LOCK) != 0;
3848                STp->can_bsr          = (options & MT_ST_CAN_BSR) != 0;
3849                STp->omit_blklims     = (options & MT_ST_NO_BLKLIMS) != 0;
3850                if ((STp->device)->scsi_level >= SCSI_2)
3851                        STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
3852                STp->scsi2_logical    = (options & MT_ST_SCSI2LOGICAL) != 0;
3853                STm->sysv             = (options & MT_ST_SYSV) != 0;
3854#if DEBUG
3855                debugging = (options & MT_ST_DEBUGGING) != 0;
3856#endif
3857                osst_log_options(STp, STm, name);
3858        }
3859        else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
3860                value = (code == MT_ST_SETBOOLEANS);
3861                if ((options & MT_ST_BUFFER_WRITES) != 0)
3862                        STm->do_buffer_writes = value;
3863                if ((options & MT_ST_ASYNC_WRITES) != 0)
3864                        STm->do_async_writes = value;
3865                if ((options & MT_ST_DEF_WRITES) != 0)
3866                        STm->defaults_for_writes = value;
3867                if ((options & MT_ST_READ_AHEAD) != 0)
3868                        STm->do_read_ahead = value;
3869                if ((options & MT_ST_TWO_FM) != 0)
3870                        STp->two_fm = value;
3871                if ((options & MT_ST_FAST_MTEOM) != 0)
3872                        STp->fast_mteom = value;
3873                if ((options & MT_ST_AUTO_LOCK) != 0)
3874                        STp->do_auto_lock = value;
3875                if ((options & MT_ST_CAN_BSR) != 0)
3876                        STp->can_bsr = value;
3877                if ((options & MT_ST_NO_BLKLIMS) != 0)
3878                        STp->omit_blklims = value;
3879                if ((STp->device)->scsi_level >= SCSI_2 &&
3880                    (options & MT_ST_CAN_PARTITIONS) != 0)
3881                        STp->can_partitions = value;
3882                if ((options & MT_ST_SCSI2LOGICAL) != 0)
3883                        STp->scsi2_logical = value;
3884                if ((options & MT_ST_SYSV) != 0)
3885                        STm->sysv = value;
3886#if DEBUG
3887                if ((options & MT_ST_DEBUGGING) != 0)
3888                        debugging = value;
3889#endif
3890                osst_log_options(STp, STm, name);
3891        }
3892        else if (code == MT_ST_WRITE_THRESHOLD) {
3893                value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
3894                if (value < 1 || value > osst_buffer_size) {
3895                        printk(KERN_WARNING "%s:W: Write threshold %d too small or too large.\n",
3896                                             name, value);
3897                        return (-EIO);
3898                }
3899                STp->write_threshold = value;
3900                printk(KERN_INFO "%s:I: Write threshold set to %d bytes.\n",
3901                                  name, value);
3902        }
3903        else if (code == MT_ST_DEF_BLKSIZE) {
3904                value = (options & ~MT_ST_OPTIONS);
3905                if (value == ~MT_ST_OPTIONS) {
3906                        STm->default_blksize = (-1);
3907                        printk(KERN_INFO "%s:I: Default block size disabled.\n", name);
3908                }
3909                else {
3910                        if (value < 512 || value > OS_DATA_SIZE || OS_DATA_SIZE % value) {
3911                                printk(KERN_WARNING "%s:W: Default block size cannot be set to %d.\n",
3912                                                         name, value);
3913                                return (-EINVAL);
3914                        }
3915                        STm->default_blksize = value;
3916                        printk(KERN_INFO "%s:I: Default block size set to %d bytes.\n",
3917                                          name, STm->default_blksize);
3918                }
3919        }
3920        else if (code == MT_ST_TIMEOUTS) {
3921                value = (options & ~MT_ST_OPTIONS);
3922                if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
3923                        STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
3924                        printk(KERN_INFO "%s:I: Long timeout set to %d seconds.\n", name,
3925                                             (value & ~MT_ST_SET_LONG_TIMEOUT));
3926                }
3927                else {
3928                        STp->timeout = value * HZ;
3929                        printk(KERN_INFO "%s:I: Normal timeout set to %d seconds.\n", name, value);
3930                }
3931        }
3932        else if (code == MT_ST_DEF_OPTIONS) {
3933                code = (options & ~MT_ST_CLEAR_DEFAULT);
3934                value = (options & MT_ST_CLEAR_DEFAULT);
3935                if (code == MT_ST_DEF_DENSITY) {
3936                        if (value == MT_ST_CLEAR_DEFAULT) {
3937                                STm->default_density = (-1);
3938                                printk(KERN_INFO "%s:I: Density default disabled.\n", name);
3939                        }
3940                        else {
3941                                STm->default_density = value & 0xff;
3942                                printk(KERN_INFO "%s:I: Density default set to %x\n",
3943                                                  name, STm->default_density);
3944                        }
3945                }
3946                else if (code == MT_ST_DEF_DRVBUFFER) {
3947                        if (value == MT_ST_CLEAR_DEFAULT) {
3948                                STp->default_drvbuffer = 0xff;
3949                                printk(KERN_INFO "%s:I: Drive buffer default disabled.\n", name);
3950                        }
3951                        else {
3952                                STp->default_drvbuffer = value & 7;
3953                                printk(KERN_INFO "%s:I: Drive buffer default set to %x\n",
3954                                                  name, STp->default_drvbuffer);
3955                        }
3956                }
3957                else if (code == MT_ST_DEF_COMPRESSION) {
3958                        if (value == MT_ST_CLEAR_DEFAULT) {
3959                                STm->default_compression = ST_DONT_TOUCH;
3960                                printk(KERN_INFO "%s:I: Compression default disabled.\n", name);
3961                        }
3962                        else {
3963                                STm->default_compression = (value & 1 ? ST_YES : ST_NO);
3964                                printk(KERN_INFO "%s:I: Compression default set to %x\n",
3965                                                  name, (value & 1));
3966                        }
3967                }
3968        }
3969        else
3970                return (-EIO);
3971
3972        return 0;
3973}
3974
3975
3976/* Internal ioctl function */
3977static int osst_int_ioctl(struct osst_tape * STp, struct osst_request ** aSRpnt,
3978                             unsigned int cmd_in, unsigned long arg)
3979{
3980        int                     timeout;
3981        long                    ltmp;
3982        int                     i, ioctl_result;
3983        int                     chg_eof = 1;
3984        unsigned char           cmd[MAX_COMMAND_SIZE];
3985        struct osst_request   * SRpnt = * aSRpnt;
3986        struct st_partstat    * STps;
3987        int                     fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
3988        int                     datalen = 0, direction = DMA_NONE;
3989        char                  * name = tape_name(STp);
3990
3991        if (STp->ready != ST_READY && cmd_in != MTLOAD) {
3992                if (STp->ready == ST_NO_TAPE)
3993                        return (-ENOMEDIUM);
3994                else
3995                        return (-EIO);
3996        }
3997        timeout = STp->long_timeout;
3998        STps = &(STp->ps[STp->partition]);
3999        fileno = STps->drv_file;
4000        blkno = STps->drv_block;
4001        at_sm = STps->at_sm;
4002        frame_seq_numbr = STp->frame_seq_number;
4003        logical_blk_num = STp->logical_blk_num;
4004
4005        memset(cmd, 0, MAX_COMMAND_SIZE);
4006        switch (cmd_in) {
4007         case MTFSFM:
4008                chg_eof = 0; /* Changed from the FSF after this */
4009         case MTFSF:
4010                if (STp->raw)
4011                   return (-EIO);
4012                if (STp->linux_media)
4013                   ioctl_result = osst_space_over_filemarks_forward_fast(STp, &SRpnt, cmd_in, arg);
4014                else
4015                   ioctl_result = osst_space_over_filemarks_forward_slow(STp, &SRpnt, cmd_in, arg);
4016                if (fileno >= 0)
4017                   fileno += arg;
4018                blkno = 0;
4019                at_sm &= (arg == 0);
4020                goto os_bypass;
4021
4022         case MTBSF:
4023                chg_eof = 0; /* Changed from the FSF after this */
4024         case MTBSFM:
4025                if (STp->raw)
4026                   return (-EIO);
4027                ioctl_result = osst_space_over_filemarks_backward(STp, &SRpnt, cmd_in, arg);
4028                if (fileno >= 0)
4029                   fileno -= arg;
4030                blkno = (-1);  /* We can't know the block number */
4031                at_sm &= (arg == 0);
4032                goto os_bypass;
4033
4034         case MTFSR:
4035         case MTBSR:
4036#if DEBUG
4037                if (debugging)
4038                   printk(OSST_DEB_MSG "%s:D: Skipping %lu blocks %s from logical block %d\n",
4039                                name, arg, cmd_in==MTFSR?"forward":"backward", logical_blk_num);
4040#endif
4041                if (cmd_in == MTFSR) {
4042                   logical_blk_num += arg;
4043                   if (blkno >= 0) blkno += arg;
4044                }
4045                else {
4046                   logical_blk_num -= arg;
4047                   if (blkno >= 0) blkno -= arg;
4048                }
4049                ioctl_result = osst_seek_logical_blk(STp, &SRpnt, logical_blk_num);
4050                fileno = STps->drv_file;
4051                blkno  = STps->drv_block;
4052                at_sm &= (arg == 0);
4053                goto os_bypass;
4054
4055         case MTFSS:
4056                cmd[0] = SPACE;
4057                cmd[1] = 0x04; /* Space Setmarks */   /* FIXME -- OS can't do this? */
4058                cmd[2] = (arg >> 16);
4059                cmd[3] = (arg >> 8);
4060                cmd[4] = arg;
4061#if DEBUG
4062                if (debugging)
4063                        printk(OSST_DEB_MSG "%s:D: Spacing tape forward %d setmarks.\n", name,
4064                cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4065#endif
4066                if (arg != 0) {
4067                        blkno = fileno = (-1);
4068                        at_sm = 1;
4069                }
4070                break;
4071         case MTBSS:
4072                cmd[0] = SPACE;
4073                cmd[1] = 0x04; /* Space Setmarks */   /* FIXME -- OS can't do this? */
4074                ltmp = (-arg);
4075                cmd[2] = (ltmp >> 16);
4076                cmd[3] = (ltmp >> 8);
4077                cmd[4] = ltmp;
4078#if DEBUG
4079                if (debugging) {
4080                        if (cmd[2] & 0x80)
4081                           ltmp = 0xff000000;
4082                        ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
4083                        printk(OSST_DEB_MSG "%s:D: Spacing tape backward %ld setmarks.\n",
4084                                                name, (-ltmp));
4085                 }
4086#endif
4087                 if (arg != 0) {
4088                        blkno = fileno = (-1);
4089                        at_sm = 1;
4090                 }
4091                 break;
4092         case MTWEOF:
4093                 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4094                        STp->write_type = OS_WRITE_DATA;
4095                        ioctl_result = osst_flush_write_buffer(STp, &SRpnt);
4096                 } else
4097                        ioctl_result = 0;
4098#if DEBUG
4099                 if (debugging) 
4100                           printk(OSST_DEB_MSG "%s:D: Writing %ld filemark(s).\n", name, arg);
4101#endif
4102                 for (i=0; i<arg; i++)
4103                        ioctl_result |= osst_write_filemark(STp, &SRpnt);
4104                 if (fileno >= 0) fileno += arg;
4105                 if (blkno  >= 0) blkno   = 0;
4106                 goto os_bypass;
4107
4108         case MTWSM:
4109                 if (STp->write_prot)
4110                        return (-EACCES);
4111                 if (!STp->raw)
4112                        return 0;
4113                 cmd[0] = WRITE_FILEMARKS;   /* FIXME -- need OS version */
4114                 if (cmd_in == MTWSM)
4115                         cmd[1] = 2;
4116                 cmd[2] = (arg >> 16);
4117                 cmd[3] = (arg >> 8);
4118                 cmd[4] = arg;
4119                 timeout = STp->timeout;
4120#if DEBUG
4121                 if (debugging) 
4122                           printk(OSST_DEB_MSG "%s:D: Writing %d setmark(s).\n", name,
4123                                  cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4124#endif
4125                 if (fileno >= 0)
4126                        fileno += arg;
4127                 blkno = 0;
4128                 at_sm = (cmd_in == MTWSM);
4129                 break;
4130         case MTOFFL:
4131         case MTLOAD:
4132         case MTUNLOAD:
4133         case MTRETEN:
4134                 cmd[0] = START_STOP;
4135                 cmd[1] = 1;                    /* Don't wait for completion */
4136                 if (cmd_in == MTLOAD) {
4137                     if (STp->ready == ST_NO_TAPE)
4138                         cmd[4] = 4;            /* open tray */
4139                      else
4140                         cmd[4] = 1;            /* load */
4141                 }
4142                 if (cmd_in == MTRETEN)
4143                         cmd[4] = 3;            /* retension then mount */
4144                 if (cmd_in == MTOFFL)
4145                         cmd[4] = 4;            /* rewind then eject */
4146                 timeout = STp->timeout;
4147#if DEBUG
4148                 if (debugging) {
4149                         switch (cmd_in) {
4150                                 case MTUNLOAD:
4151                                         printk(OSST_DEB_MSG "%s:D: Unloading tape.\n", name);
4152                                         break;
4153                                 case MTLOAD:
4154                                         printk(OSST_DEB_MSG "%s:D: Loading tape.\n", name);
4155                                         break;
4156                                 case MTRETEN:
4157                                         printk(OSST_DEB_MSG "%s:D: Retensioning tape.\n", name);
4158                                         break;
4159                                 case MTOFFL:
4160                                         printk(OSST_DEB_MSG "%s:D: Ejecting tape.\n", name);
4161                                         break;
4162                         }
4163                 }
4164#endif
4165       fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4166                 break;
4167         case MTNOP:
4168#if DEBUG
4169                 if (debugging)
4170                         printk(OSST_DEB_MSG "%s:D: No-op on tape.\n", name);
4171#endif
4172                 return 0;  /* Should do something ? */
4173                 break;
4174         case MTEOM:
4175#if DEBUG
4176                if (debugging)
4177                   printk(OSST_DEB_MSG "%s:D: Spacing to end of recorded medium.\n", name);
4178#endif
4179                if ((osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0) ||
4180                            (osst_get_logical_frame(STp, &SRpnt, -1, 0)               < 0)) {
4181                   ioctl_result = -EIO;
4182                   goto os_bypass;
4183                }
4184                if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_EOD) {
4185#if DEBUG
4186                   printk(OSST_DEB_MSG "%s:D: No EOD frame found where expected.\n", name);
4187#endif
4188                   ioctl_result = -EIO;
4189                   goto os_bypass;
4190                }
4191                ioctl_result = osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0);
4192                fileno = STp->filemark_cnt;
4193                blkno  = at_sm = 0;
4194                goto os_bypass;
4195
4196         case MTERASE:
4197                if (STp->write_prot)
4198                   return (-EACCES);
4199                ioctl_result = osst_reset_header(STp, &SRpnt);
4200                i = osst_write_eod(STp, &SRpnt);
4201                if (i < ioctl_result) ioctl_result = i;
4202                i = osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos);
4203                if (i < ioctl_result) ioctl_result = i;
4204                fileno = blkno = at_sm = 0 ;
4205                goto os_bypass;
4206
4207         case MTREW:
4208                cmd[0] = REZERO_UNIT; /* rewind */
4209                cmd[1] = 1;
4210#if DEBUG
4211                if (debugging)
4212                   printk(OSST_DEB_MSG "%s:D: Rewinding tape, Immed=%d.\n", name, cmd[1]);
4213#endif
4214                fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4215                break;
4216
4217         case MTSETBLK:           /* Set block length */
4218                 if ((STps->drv_block == 0 )                      &&
4219                     !STp->dirty                                  &&
4220                     ((STp->buffer)->buffer_bytes == 0)           &&
4221                     ((arg & MT_ST_BLKSIZE_MASK) >= 512 )         && 
4222                     ((arg & MT_ST_BLKSIZE_MASK) <= OS_DATA_SIZE) &&
4223                     !(OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))  ) {
4224                         /*
4225                          * Only allowed to change the block size if you opened the
4226                          * device at the beginning of a file before writing anything.
4227                          * Note, that when reading, changing block_size is futile,
4228                          * as the size used when writing overrides it.
4229                          */
4230                         STp->block_size = (arg & MT_ST_BLKSIZE_MASK);
4231                         printk(KERN_INFO "%s:I: Block size set to %d bytes.\n",
4232                                           name, STp->block_size);
4233                         return 0;
4234                 }
4235         case MTSETDENSITY:       /* Set tape density */
4236         case MTSETDRVBUFFER:     /* Set drive buffering */
4237         case SET_DENS_AND_BLK:   /* Set density and block size */
4238                 chg_eof = 0;
4239                 if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
4240                         return (-EIO);       /* Not allowed if data in buffer */
4241                 if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
4242                     (arg & MT_ST_BLKSIZE_MASK) != 0                    &&
4243                     (arg & MT_ST_BLKSIZE_MASK) != STp->block_size       ) {
4244                         printk(KERN_WARNING "%s:W: Illegal to set block size to %d%s.\n",
4245                                                name, (int)(arg & MT_ST_BLKSIZE_MASK),
4246                                                (OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))?"":" now");
4247                         return (-EINVAL);
4248                 }
4249                 return 0;  /* FIXME silently ignore if block size didn't change */
4250
4251         default:
4252                return (-ENOSYS);
4253        }
4254
4255        SRpnt = osst_do_scsi(SRpnt, STp, cmd, datalen, direction, timeout, MAX_RETRIES, 1);
4256
4257        ioctl_result = (STp->buffer)->syscall_result;
4258
4259        if (!SRpnt) {
4260#if DEBUG
4261                printk(OSST_DEB_MSG "%s:D: Couldn't exec scsi cmd for IOCTL\n", name);
4262#endif
4263                return ioctl_result;
4264        }
4265
4266        if (!ioctl_result) {  /* SCSI command successful */
4267                STp->frame_seq_number = frame_seq_numbr;
4268                STp->logical_blk_num  = logical_blk_num;
4269        }
4270
4271os_bypass:
4272#if DEBUG
4273        if (debugging)
4274                printk(OSST_DEB_MSG "%s:D: IOCTL (%d) Result=%d\n", name, cmd_in, ioctl_result);
4275#endif
4276
4277        if (!ioctl_result) {                            /* success */
4278
4279                if (cmd_in == MTFSFM) {
4280                         fileno--;
4281                         blkno--;
4282                }
4283                if (cmd_in == MTBSFM) {
4284                         fileno++;
4285                         blkno++;
4286                }
4287                STps->drv_block = blkno;
4288                STps->drv_file = fileno;
4289                STps->at_sm = at_sm;
4290
4291                if (cmd_in == MTEOM)
4292                        STps->eof = ST_EOD;
4293                else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) {
4294                        ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num-1);
4295                        STps->drv_block++;
4296                        STp->logical_blk_num++;
4297                        STp->frame_seq_number++;
4298                        STp->frame_in_buffer = 0;
4299                        STp->buffer->read_pointer = 0;
4300                }
4301                else if (cmd_in == MTFSF)
4302                        STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
4303                else if (chg_eof)
4304                        STps->eof = ST_NOEOF;
4305
4306                if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
4307                        STp->rew_at_close = 0;
4308                else if (cmd_in == MTLOAD) {
4309                        for (i=0; i < ST_NBR_PARTITIONS; i++) {
4310                            STp->ps[i].rw = ST_IDLE;
4311                            STp->ps[i].last_block_valid = 0;/* FIXME - where else is this field maintained? */
4312                        }
4313                        STp->partition = 0;
4314                }
4315
4316                if (cmd_in == MTREW) {
4317                        ioctl_result = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos); 
4318                        if (ioctl_result > 0)
4319                                ioctl_result = 0;
4320                }
4321
4322        } else if (cmd_in == MTBSF || cmd_in == MTBSFM ) {
4323                if (osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos) < 0)
4324                        STps->drv_file = STps->drv_block = -1;
4325                else
4326                        STps->drv_file = STps->drv_block = 0;
4327                STps->eof = ST_NOEOF;
4328        } else if (cmd_in == MTFSF || cmd_in == MTFSFM) {
4329                if (osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0)
4330                        STps->drv_file = STps->drv_block = -1;
4331                else {
4332                        STps->drv_file  = STp->filemark_cnt;
4333                        STps->drv_block = 0;
4334                }
4335                STps->eof = ST_EOD;
4336        } else if (cmd_in == MTBSR || cmd_in == MTFSR || cmd_in == MTWEOF || cmd_in == MTEOM) {
4337                STps->drv_file = STps->drv_block = (-1);
4338                STps->eof = ST_NOEOF;
4339                STp->header_ok = 0;
4340        } else if (cmd_in == MTERASE) {
4341                STp->header_ok = 0;
4342        } else if (SRpnt) {  /* SCSI command was not completely successful. */
4343                if (SRpnt->sense[2] & 0x40) {
4344                        STps->eof = ST_EOM_OK;
4345                        STps->drv_block = 0;
4346                }
4347                if (chg_eof)
4348                        STps->eof = ST_NOEOF;
4349
4350                if ((SRpnt->sense[2] & 0x0f) == BLANK_CHECK)
4351                        STps->eof = ST_EOD;
4352
4353                if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60))
4354                        ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
4355        }
4356        *aSRpnt = SRpnt;
4357
4358        return ioctl_result;
4359}
4360
4361
4362/* Open the device */
4363static int __os_scsi_tape_open(struct inode * inode, struct file * filp)
4364{
4365        unsigned short        flags;
4366        int                   i, b_size, new_session = 0, retval = 0;
4367        unsigned char         cmd[MAX_COMMAND_SIZE];
4368        struct osst_request * SRpnt = NULL;
4369        struct osst_tape    * STp;
4370        struct st_modedef   * STm;
4371        struct st_partstat  * STps;
4372        char                * name;
4373        int                   dev  = TAPE_NR(inode);
4374        int                   mode = TAPE_MODE(inode);
4375
4376        /*
4377         * We really want to do nonseekable_open(inode, filp); here, but some
4378         * versions of tar incorrectly call lseek on tapes and bail out if that
4379         * fails.  So we disallow pread() and pwrite(), but permit lseeks.
4380         */
4381        filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
4382
4383        write_lock(&os_scsi_tapes_lock);
4384        if (dev >= osst_max_dev || os_scsi_tapes == NULL ||
4385            (STp = os_scsi_tapes[dev]) == NULL || !STp->device) {
4386                write_unlock(&os_scsi_tapes_lock);
4387                return (-ENXIO);
4388        }
4389
4390        name = tape_name(STp);
4391
4392        if (STp->in_use) {
4393                write_unlock(&os_scsi_tapes_lock);
4394#if DEBUG
4395                printk(OSST_DEB_MSG "%s:D: Device already in use.\n", name);
4396#endif
4397                return (-EBUSY);
4398        }
4399        if (scsi_device_get(STp->device)) {
4400                write_unlock(&os_scsi_tapes_lock);
4401#if DEBUG
4402                printk(OSST_DEB_MSG "%s:D: Failed scsi_device_get.\n", name);
4403#endif
4404                return (-ENXIO);
4405        }
4406        filp->private_data = STp;
4407        STp->in_use = 1;
4408        write_unlock(&os_scsi_tapes_lock);
4409        STp->rew_at_close = TAPE_REWIND(inode);
4410
4411        if( !scsi_block_when_processing_errors(STp->device) ) {
4412                return -ENXIO;
4413        }
4414
4415        if (mode != STp->current_mode) {
4416#if DEBUG
4417                if (debugging)
4418                        printk(OSST_DEB_MSG "%s:D: Mode change from %d to %d.\n",
4419                                               name, STp->current_mode, mode);
4420#endif
4421                new_session = 1;
4422                STp->current_mode = mode;
4423        }
4424        STm = &(STp->modes[STp->current_mode]);
4425
4426        flags = filp->f_flags;
4427        STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
4428
4429        STp->raw = TAPE_IS_RAW(inode);
4430        if (STp->raw)
4431                STp->header_ok = 0;
4432
4433        /* Allocate data segments for this device's tape buffer */
4434        if (!enlarge_buffer(STp->buffer, STp->restr_dma)) {
4435                printk(KERN_ERR "%s:E: Unable to allocate memory segments for tape buffer.\n", name);
4436                retval = (-EOVERFLOW);
4437                goto err_out;
4438        }
4439        if (STp->buffer->buffer_size >= OS_FRAME_SIZE) {
4440                for (i = 0, b_size = 0; 
4441                     (i < STp->buffer->sg_segs) && ((b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE); 
4442                     b_size += STp->buffer->sg[i++].length);
4443                STp->buffer->aux = (os_aux_t *) (page_address(sg_page(&STp->buffer->sg[i])) + OS_DATA_SIZE - b_size);
4444#if DEBUG
4445                printk(OSST_DEB_MSG "%s:D: b_data points to %p in segment 0 at %p\n", name,
4446                        STp->buffer->b_data, page_address(STp->buffer->sg[0].page));
4447                printk(OSST_DEB_MSG "%s:D: AUX points to %p in segment %d at %p\n", name,
4448                         STp->buffer->aux, i, page_address(STp->buffer->sg[i].page));
4449#endif
4450        } else {
4451                STp->buffer->aux = NULL; /* this had better never happen! */
4452                printk(KERN_NOTICE "%s:A: Framesize %d too large for buffer.\n", name, OS_FRAME_SIZE);
4453                retval = (-EIO);
4454                goto err_out;
4455        }
4456        STp->buffer->writing = 0;
4457        STp->buffer->syscall_result = 0;
4458        STp->dirty = 0;
4459        for (i=0; i < ST_NBR_PARTITIONS; i++) {
4460                STps = &(STp->ps[i]);
4461                STps->rw = ST_IDLE;
4462        }
4463        STp->ready = ST_READY;
4464#if DEBUG
4465        STp->nbr_waits = STp->nbr_finished = 0;
4466#endif
4467
4468        memset (cmd, 0, MAX_COMMAND_SIZE);
4469        cmd[0] = TEST_UNIT_READY;
4470
4471        SRpnt = osst_do_scsi(NULL, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
4472        if (!SRpnt) {
4473                retval = (STp->buffer)->syscall_result;         /* FIXME - valid? */
4474                goto err_out;
4475        }
4476        if ((SRpnt->sense[0] & 0x70) == 0x70      &&
4477            (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4478             SRpnt->sense[12]        == 4         ) {
4479#if DEBUG
4480                printk(OSST_DEB_MSG "%s:D: Unit not ready, cause %x\n", name, SRpnt->sense[13]);
4481#endif
4482                if (filp->f_flags & O_NONBLOCK) {
4483                        retval = -EAGAIN;
4484                        goto err_out;
4485                }
4486                if (SRpnt->sense[13] == 2) {    /* initialize command required (LOAD) */
4487                        memset (cmd, 0, MAX_COMMAND_SIZE);
4488                        cmd[0] = START_STOP;
4489                        cmd[1] = 1;
4490                        cmd[4] = 1;
4491                        SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4492                                             STp->timeout, MAX_RETRIES, 1);
4493                }
4494                osst_wait_ready(STp, &SRpnt, (SRpnt->sense[13]==1?15:3) * 60, 0);
4495        }
4496        if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4497            (SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
4498#if DEBUG
4499                printk(OSST_DEB_MSG "%s:D: Unit wants attention\n", name);
4500#endif
4501                STp->header_ok = 0;
4502
4503                for (i=0; i < 10; i++) {
4504
4505                        memset (cmd, 0, MAX_COMMAND_SIZE);
4506                        cmd[0] = TEST_UNIT_READY;
4507
4508                        SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4509                                             STp->timeout, MAX_RETRIES, 1);
4510                        if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4511                            (SRpnt->sense[2] & 0x0f) != UNIT_ATTENTION)
4512                                break;
4513                }
4514
4515                STp->pos_unknown = 0;
4516                STp->partition = STp->new_partition = 0;
4517                if (STp->can_partitions)
4518                        STp->nbr_partitions = 1;  /* This guess will be updated later if necessary */
4519                for (i=0; i < ST_NBR_PARTITIONS; i++) {
4520                        STps = &(STp->ps[i]);
4521                        STps->rw = ST_IDLE;             /* FIXME - seems to be redundant... */
4522                        STps->eof = ST_NOEOF;
4523                        STps->at_sm = 0;
4524                        STps->last_block_valid = 0;
4525                        STps->drv_block = 0;
4526                        STps->drv_file = 0 ;
4527                }
4528                new_session = 1;
4529                STp->recover_count = 0;
4530                STp->abort_count = 0;
4531        }
4532        /*
4533         * if we have valid headers from before, and the drive/tape seem untouched,
4534         * open without reconfiguring and re-reading the headers
4535         */
4536        if (!STp->buffer->syscall_result && STp->header_ok &&
4537            !SRpnt->result && SRpnt->sense[0] == 0) {
4538
4539                memset(cmd, 0, MAX_COMMAND_SIZE);
4540                cmd[0] = MODE_SENSE;
4541                cmd[1] = 8;
4542                cmd[2] = VENDOR_IDENT_PAGE;
4543                cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
4544
4545                SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
4546
4547                if (STp->buffer->syscall_result                     ||
4548                    STp->buffer->b_data[MODE_HEADER_LENGTH + 2] != 'L' ||
4549                    STp->buffer->b_data[MODE_HEADER_LENGTH + 3] != 'I' ||
4550                    STp->buffer->b_data[MODE_HEADER_LENGTH + 4] != 'N' ||
4551                    STp->buffer->b_data[MODE_HEADER_LENGTH + 5] != '4'  ) {
4552#if DEBUG
4553                        printk(OSST_DEB_MSG "%s:D: Signature was changed to %c%c%c%c\n", name,
4554                          STp->buffer->b_data[MODE_HEADER_LENGTH + 2],
4555                          STp->buffer->b_data[MODE_HEADER_LENGTH + 3],
4556                          STp->buffer->b_data[MODE_HEADER_LENGTH + 4],
4557                          STp->buffer->b_data[MODE_HEADER_LENGTH + 5]);
4558#endif
4559                        STp->header_ok = 0;
4560                }
4561                i = STp->first_frame_position;
4562                if (STp->header_ok && i == osst_get_frame_position(STp, &SRpnt)) {
4563                        if (STp->door_locked == ST_UNLOCKED) {
4564                                if (do_door_lock(STp, 1))
4565                                        printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4566                                else
4567                                        STp->door_locked = ST_LOCKED_AUTO;
4568                        }
4569                        if (!STp->frame_in_buffer) {
4570                                STp->block_size = (STm->default_blksize > 0) ?
4571                                                        STm->default_blksize : OS_DATA_SIZE;
4572                                STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
4573                        }
4574                        STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size;
4575                        STp->fast_open = 1;
4576                        osst_release_request(SRpnt);
4577                        return 0;
4578                }
4579#if DEBUG
4580                if (i != STp->first_frame_position)
4581                        printk(OSST_DEB_MSG "%s:D: Tape position changed from %d to %d\n",
4582                                                name, i, STp->first_frame_position);
4583#endif
4584                STp->header_ok = 0;
4585        }
4586        STp->fast_open = 0;
4587
4588        if ((STp->buffer)->syscall_result != 0 &&   /* in all error conditions except no medium */ 
4589            (SRpnt->sense[2] != 2 || SRpnt->sense[12] != 0x3A) ) {
4590
4591                memset(cmd, 0, MAX_COMMAND_SIZE);
4592                cmd[0] = MODE_SELECT;
4593                cmd[1] = 0x10;
4594                cmd[4] = 4 + MODE_HEADER_LENGTH;
4595
4596                (STp->buffer)->b_data[0] = cmd[4] - 1;
4597                (STp->buffer)->b_data[1] = 0;                   /* Medium Type - ignoring */
4598                (STp->buffer)->b_data[2] = 0;                   /* Reserved */
4599                (STp->buffer)->b_data[3] = 0;                   /* Block Descriptor Length */
4600                (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = 0x3f;
4601                (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 1;
4602                (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 2;
4603                (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 3;
4604
4605#if DEBUG
4606                printk(OSST_DEB_MSG "%s:D: Applying soft reset\n", name);
4607#endif
4608                SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
4609
4610                STp->header_ok = 0;
4611
4612                for (i=0; i < 10; i++) {
4613
4614                        memset (cmd, 0, MAX_COMMAND_SIZE);
4615                        cmd[0] = TEST_UNIT_READY;
4616
4617                        SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4618                                                    STp->timeout, MAX_RETRIES, 1);
4619                        if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4620                            (SRpnt->sense[2] & 0x0f) == NOT_READY)
4621                        break;
4622
4623                        if ((SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) {
4624                                STp->pos_unknown = 0;
4625                                STp->partition = STp->new_partition = 0;
4626                                if (STp->can_partitions)
4627                                        STp->nbr_partitions = 1;  /* This guess will be updated later if necessary */
4628                                for (i=0; i < ST_NBR_PARTITIONS; i++) {
4629                                        STps = &(STp->ps[i]);
4630                                        STps->rw = ST_IDLE;
4631                                        STps->eof = ST_NOEOF;
4632                                        STps->at_sm = 0;
4633                                        STps->last_block_valid = 0;
4634                                        STps->drv_block = 0;
4635                                        STps->drv_file = 0 ;
4636                                }
4637                                new_session = 1;
4638                        }
4639                }
4640        }
4641
4642        if (osst_wait_ready(STp, &SRpnt, 15 * 60, 0))           /* FIXME - not allowed with NOBLOCK */
4643                 printk(KERN_INFO "%s:I: Device did not become Ready in open\n", name);
4644
4645        if ((STp->buffer)->syscall_result != 0) {
4646                if ((STp->device)->scsi_level >= SCSI_2 &&
4647                    (SRpnt->sense[0] & 0x70) == 0x70 &&
4648                    (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4649                     SRpnt->sense[12] == 0x3a) { /* Check ASC */
4650                        STp->ready = ST_NO_TAPE;
4651                } else
4652                        STp->ready = ST_NOT_READY;
4653                osst_release_request(SRpnt);
4654                SRpnt = NULL;
4655                STp->density = 0;       /* Clear the erroneous "residue" */
4656                STp->write_prot = 0;
4657                STp->block_size = 0;
4658                STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
4659                STp->partition = STp->new_partition = 0;
4660                STp->door_locked = ST_UNLOCKED;
4661                return 0;
4662        }
4663
4664        osst_configure_onstream(STp, &SRpnt);
4665
4666        STp->block_size = STp->raw ? OS_FRAME_SIZE : (
4667                             (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE);
4668        STp->buffer->buffer_blocks = STp->raw ? 1 : OS_DATA_SIZE / STp->block_size;
4669        STp->buffer->buffer_bytes  =
4670        STp->buffer->read_pointer  =
4671        STp->frame_in_buffer       = 0;
4672
4673#if DEBUG
4674        if (debugging)
4675                printk(OSST_DEB_MSG "%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4676                     name, STp->block_size, OS_FRAME_SIZE, (STp->buffer)->buffer_size,
4677                     (STp->buffer)->buffer_blocks);
4678#endif
4679
4680        if (STp->drv_write_prot) {
4681                STp->write_prot = 1;
4682#if DEBUG
4683                if (debugging)
4684                        printk(OSST_DEB_MSG "%s:D: Write protected\n", name);
4685#endif
4686                if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
4687                        retval = (-EROFS);
4688                        goto err_out;
4689                }
4690        }
4691
4692        if (new_session) {  /* Change the drive parameters for the new mode */
4693#if DEBUG
4694                if (debugging)
4695        printk(OSST_DEB_MSG "%s:D: New Session\n", name);
4696#endif
4697                STp->density_changed = STp->blksize_changed = 0;
4698                STp->compression_changed = 0;
4699        }
4700
4701        /*
4702         * properly position the tape and check the ADR headers
4703         */
4704        if (STp->door_locked == ST_UNLOCKED) {
4705                 if (do_door_lock(STp, 1))
4706                        printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4707                 else
4708                        STp->door_locked = ST_LOCKED_AUTO;
4709        }
4710
4711        osst_analyze_headers(STp, &SRpnt);
4712
4713        osst_release_request(SRpnt);
4714        SRpnt = NULL;
4715
4716        return 0;
4717
4718err_out:
4719        if (SRpnt != NULL)