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