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