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