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