linux/drivers/scsi/osst.c
<<
>>
Prefs
   1/*
   2  SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying
   3  file Documentation/scsi/st.txt for more information.
   4
   5  History:
   6
   7  OnStream SCSI Tape support (osst) cloned from st.c by
   8  Willem Riede (osst@riede.org) Feb 2000
   9  Fixes ... Kurt Garloff <garloff@suse.de> Mar 2000
  10
  11  Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
  12  Contribution and ideas from several people including (in alphabetical
  13  order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
  14  Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
  15
  16  Copyright 1992 - 2002 Kai Makisara / 2000 - 2006 Willem Riede
  17         email osst@riede.org
  18
  19  $Header: /cvsroot/osst/Driver/osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $
  20
  21  Microscopic alterations - Rik Ling, 2000/12/21
  22  Last st.c sync: Tue Oct 15 22:01:04 2002 by makisara
  23  Some small formal changes - aeb, 950809
  24*/
  25
  26static const char * cvsid = "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
  27static const char * osst_version = "0.99.4";
  28
  29/* The "failure to reconnect" firmware bug */
  30#define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
  31#define OSST_FW_NEED_POLL_MAX 10704 /*(108D)*/
  32#define OSST_FW_NEED_POLL(x,d) ((x) >= OSST_FW_NEED_POLL_MIN && (x) <= OSST_FW_NEED_POLL_MAX && d->host->this_id != 7)
  33
  34#include <linux/module.h>
  35
  36#include <linux/fs.h>
  37#include <linux/kernel.h>
  38#include <linux/sched.h>
  39#include <linux/proc_fs.h>
  40#include <linux/mm.h>
  41#include <linux/slab.h>
  42#include <linux/init.h>
  43#include <linux/string.h>
  44#include <linux/errno.h>
  45#include <linux/mtio.h>
  46#include <linux/ioctl.h>
  47#include <linux/fcntl.h>
  48#include <linux/spinlock.h>
  49#include <linux/vmalloc.h>
  50#include <linux/blkdev.h>
  51#include <linux/moduleparam.h>
  52#include <linux/delay.h>
  53#include <linux/jiffies.h>
  54#include <linux/mutex.h>
  55#include <asm/uaccess.h>
  56#include <asm/dma.h>
  57
  58/* The driver prints some debugging information on the console if DEBUG
  59   is defined and non-zero. */
  60#define DEBUG 0
  61
  62/* The message level for the debug messages is currently set to KERN_NOTICE
  63   so that people can easily see the messages. Later when the debugging messages
  64   in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
  65#define OSST_DEB_MSG  KERN_NOTICE
  66
  67#include <scsi/scsi.h>
  68#include <scsi/scsi_dbg.h>
  69#include <scsi/scsi_device.h>
  70#include <scsi/scsi_driver.h>
  71#include <scsi/scsi_eh.h>
  72#include <scsi/scsi_host.h>
  73#include <scsi/scsi_ioctl.h>
  74
  75#define ST_KILOBYTE 1024
  76
  77#include "st.h"
  78#include "osst.h"
  79#include "osst_options.h"
  80#include "osst_detect.h"
  81
  82static DEFINE_MUTEX(osst_int_mutex);
  83static int max_dev = 0;
  84static int write_threshold_kbs = 0;
  85static int max_sg_segs = 0;
  86
  87#ifdef MODULE
  88MODULE_AUTHOR("Willem Riede");
  89MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
  90MODULE_LICENSE("GPL");
  91MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR);
  92MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
  93
  94module_param(max_dev, int, 0444);
  95MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
  96
  97module_param(write_threshold_kbs, int, 0644);
  98MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
  99
 100module_param(max_sg_segs, int, 0644);
 101MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
 102#else
 103static struct osst_dev_parm {
 104       char   *name;
 105       int    *val;
 106} parms[] __initdata = {
 107       { "max_dev",             &max_dev             },
 108       { "write_threshold_kbs", &write_threshold_kbs },
 109       { "max_sg_segs",         &max_sg_segs         }
 110};
 111#endif
 112
 113/* Some default definitions have been moved to osst_options.h */
 114#define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
 115#define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
 116
 117/* The buffer size should fit into the 24 bits for length in the
 118   6-byte SCSI read and write commands. */
 119#if OSST_BUFFER_SIZE >= (2 << 24 - 1)
 120#error "Buffer size should not exceed (2 << 24 - 1) bytes!"
 121#endif
 122
 123#if DEBUG
 124static int debugging = 1;
 125/* uncomment define below to test error recovery */
 126// #define OSST_INJECT_ERRORS 1 
 127#endif
 128
 129/* Do not retry! The drive firmware already retries when appropriate,
 130   and when it tries to tell us something, we had better listen... */
 131#define MAX_RETRIES 0
 132
 133#define NO_TAPE  NOT_READY
 134
 135#define OSST_WAIT_POSITION_COMPLETE   (HZ > 200 ? HZ / 200 : 1)
 136#define OSST_WAIT_WRITE_COMPLETE      (HZ / 12)
 137#define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
 138        
 139#define OSST_TIMEOUT (200 * HZ)
 140#define OSST_LONG_TIMEOUT (1800 * HZ)
 141
 142#define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
 143#define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
 144#define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
 145#define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
 146
 147/* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
 148   24 bits) */
 149#define SET_DENS_AND_BLK 0x10001
 150
 151static int osst_buffer_size       = OSST_BUFFER_SIZE;
 152static int osst_write_threshold   = OSST_WRITE_THRESHOLD;
 153static int osst_max_sg_segs       = OSST_MAX_SG;
 154static int osst_max_dev           = OSST_MAX_TAPES;
 155static int osst_nr_dev;
 156
 157static struct osst_tape **os_scsi_tapes = NULL;
 158static DEFINE_RWLOCK(os_scsi_tapes_lock);
 159
 160static int modes_defined = 0;
 161
 162static struct osst_buffer *new_tape_buffer(int, int, int);
 163static int enlarge_buffer(struct osst_buffer *, int);
 164static void normalize_buffer(struct osst_buffer *);
 165static int append_to_buffer(const char __user *, struct osst_buffer *, int);
 166static int from_buffer(struct osst_buffer *, char __user *, int);
 167static int osst_zero_buffer_tail(struct osst_buffer *);
 168static int osst_copy_to_buffer(struct osst_buffer *, unsigned char *);
 169static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
 170
 171static int osst_probe(struct device *);
 172static int osst_remove(struct device *);
 173
 174static struct scsi_driver osst_template = {
 175        .owner                  = THIS_MODULE,
 176        .gendrv = {
 177                .name           =  "osst",
 178                .probe          = osst_probe,
 179                .remove         = osst_remove,
 180        }
 181};
 182
 183static int osst_int_ioctl(struct osst_tape *STp, struct osst_request ** aSRpnt,
 184                            unsigned int cmd_in, unsigned long arg);
 185
 186static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int frame, int skip);
 187
 188static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt);
 189
 190static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt);
 191
 192static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending);
 193
 194static inline char *tape_name(struct osst_tape *tape)
 195{
 196        return tape->drive->disk_name;
 197}
 198
 199/* Routines that handle the interaction with mid-layer SCSI routines */
 200
 201
 202/* Normalize Sense */
 203static void osst_analyze_sense(struct osst_request *SRpnt, struct st_cmdstatus *s)
 204{
 205        const u8 *ucp;
 206        const u8 *sense = SRpnt->sense;
 207
 208        s->have_sense = scsi_normalize_sense(SRpnt->sense,
 209                                SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
 210        s->flags = 0;
 211
 212        if (s->have_sense) {
 213                s->deferred = 0;
 214                s->remainder_valid =
 215                        scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64);
 216                switch (sense[0] & 0x7f) {
 217                case 0x71:
 218                        s->deferred = 1;
 219                case 0x70:
 220                        s->fixed_format = 1;
 221                        s->flags = sense[2] & 0xe0;
 222                        break;
 223                case 0x73:
 224                        s->deferred = 1;
 225                case 0x72:
 226                        s->fixed_format = 0;
 227                        ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
 228                        s->flags = ucp ? (ucp[3] & 0xe0) : 0;
 229                        break;
 230                }
 231        }
 232}
 233
 234/* Convert the result to success code */
 235static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
 236{
 237        char *name = tape_name(STp);
 238        int result = SRpnt->result;
 239        u8 * sense = SRpnt->sense, scode;
 240#if DEBUG
 241        const char *stp;
 242#endif
 243        struct st_cmdstatus *cmdstatp;
 244
 245        if (!result)
 246                return 0;
 247
 248        cmdstatp = &STp->buffer->cmdstat;
 249        osst_analyze_sense(SRpnt, cmdstatp);
 250
 251        if (cmdstatp->have_sense)
 252                scode = STp->buffer->cmdstat.sense_hdr.sense_key;
 253        else
 254                scode = 0;
 255#if DEBUG
 256        if (debugging) {
 257                printk(OSST_DEB_MSG "%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
 258                   name, result,
 259                   SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
 260                   SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
 261                if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
 262                                  name, scode, sense[12], sense[13]);
 263                if (cmdstatp->have_sense)
 264                        __scsi_print_sense(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, cmd;
3331
3332        cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK;
3333#if DEBUG
3334        printk(OSST_DEB_MSG "%s:D: %socking drive door.\n", tape_name(STp), do_lock ? "L" : "Unl");
3335#endif
3336        retval = scsi_ioctl(STp->device, cmd, NULL);
3337        if (!retval) {
3338                STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
3339        }
3340        else {
3341                STp->door_locked = ST_LOCK_FAILS;
3342        }
3343        return retval;
3344}
3345
3346/* Set the internal state after reset */
3347static void reset_state(struct osst_tape *STp)
3348{
3349        int i;
3350        struct st_partstat *STps;
3351
3352        STp->pos_unknown = 0;
3353        for (i = 0; i < ST_NBR_PARTITIONS; i++) {
3354                STps = &(STp->ps[i]);
3355                STps->rw = ST_IDLE;
3356                STps->eof = ST_NOEOF;
3357                STps->at_sm = 0;
3358                STps->last_block_valid = 0;
3359                STps->drv_block = -1;
3360                STps->drv_file = -1;
3361        }
3362}
3363                                
3364
3365/* Entry points to osst */
3366
3367/* Write command */
3368static ssize_t osst_write(struct file * filp, const char __user * buf, size_t count, loff_t *ppos)
3369{
3370        ssize_t               total, retval = 0;
3371        ssize_t               i, do_count, blks, transfer;
3372        int                   write_threshold;
3373        int                   doing_write = 0;
3374        const char   __user * b_point;
3375        struct osst_request * SRpnt = NULL;
3376        struct st_modedef   * STm;
3377        struct st_partstat  * STps;
3378        struct osst_tape    * STp  = filp->private_data;
3379        char                * name = tape_name(STp);
3380
3381
3382        if (mutex_lock_interruptible(&STp->lock))
3383                return (-ERESTARTSYS);
3384
3385        /*
3386         * If we are in the middle of error recovery, don't let anyone
3387         * else try and use this device.  Also, if error recovery fails, it
3388         * may try and take the device offline, in which case all further
3389         * access to the device is prohibited.
3390         */
3391        if( !scsi_block_when_processing_errors(STp->device) ) {
3392                retval = (-ENXIO);
3393                goto out;
3394        }
3395        
3396        if (STp->ready != ST_READY) {
3397                if (STp->ready == ST_NO_TAPE)
3398                        retval = (-ENOMEDIUM);
3399                else
3400                        retval = (-EIO);
3401                goto out;
3402        }
3403        STm = &(STp->modes[STp->current_mode]);
3404        if (!STm->defined) {
3405                retval = (-ENXIO);
3406                goto out;
3407        }
3408        if (count == 0)
3409                goto out;
3410
3411        /*
3412         * If there was a bus reset, block further access
3413         * to this device.
3414         */
3415        if (STp->pos_unknown) {
3416                retval = (-EIO);
3417                goto out;
3418        }
3419
3420#if DEBUG
3421        if (!STp->in_use) {
3422                printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3423                retval = (-EIO);
3424                goto out;
3425        }
3426#endif
3427
3428        if (STp->write_prot) {
3429                retval = (-EACCES);
3430                goto out;
3431        }
3432
3433        /* Write must be integral number of blocks */
3434        if (STp->block_size != 0 && (count % STp->block_size) != 0) {
3435                printk(KERN_ERR "%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3436                                       name, count, STp->block_size<1024?
3437                                       STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3438                retval = (-EINVAL);
3439                goto out;
3440        }
3441
3442        if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) {
3443                printk(KERN_ERR "%s:E: Write truncated at EOM early warning (frame %d).\n",
3444                                       name, STp->first_frame_position);
3445                retval = (-ENOSPC);
3446                goto out;
3447        }
3448
3449        if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3450                STp->door_locked = ST_LOCKED_AUTO;
3451
3452        STps = &(STp->ps[STp->partition]);
3453
3454        if (STps->rw == ST_READING) {
3455#if DEBUG
3456                printk(OSST_DEB_MSG "%s:D: Switching from read to write at file %d, block %d\n", name, 
3457                                        STps->drv_file, STps->drv_block);
3458#endif
3459                retval = osst_flush_buffer(STp, &SRpnt, 0);
3460                if (retval)
3461                        goto out;
3462                STps->rw = ST_IDLE;
3463        }
3464        if (STps->rw != ST_WRITING) {
3465                /* Are we totally rewriting this tape? */
3466                if (!STp->header_ok ||
3467                    (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
3468                    (STps->drv_file == 0 && STps->drv_block == 0)) {
3469                        STp->wrt_pass_cntr++;
3470#if DEBUG
3471                        printk(OSST_DEB_MSG "%s:D: Allocating next write pass counter: %d\n",
3472                                                  name, STp->wrt_pass_cntr);
3473#endif
3474                        osst_reset_header(STp, &SRpnt);
3475                        STps->drv_file = STps->drv_block = 0;
3476                }
3477                /* Do we know where we'll be writing on the tape? */
3478                else {
3479                        if ((STp->fast_open && osst_verify_position(STp, &SRpnt)) ||
3480                                        STps->drv_file < 0 || STps->drv_block < 0) {
3481                                if (STp->first_frame_position == STp->eod_frame_ppos) { /* at EOD */
3482                                        STps->drv_file = STp->filemark_cnt;
3483                                        STps->drv_block = 0;
3484                                }
3485                                else {
3486                                        /* We have no idea where the tape is positioned - give up */
3487#if DEBUG
3488                                        printk(OSST_DEB_MSG
3489                                                "%s:D: Cannot write at indeterminate position.\n", name);
3490#endif
3491                                        retval = (-EIO);
3492                                        goto out;
3493                                }
3494                        }         
3495                        if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) {
3496                                gmb();
3497                                STp->filemark_cnt = STps->drv_file;
3498                                STp->last_mark_ppos =
3499                                        ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]);
3500                                printk(KERN_WARNING
3501                                        "%s:W: Overwriting file %d with old write pass counter %d\n",
3502                                                name, STps->drv_file, STp->wrt_pass_cntr);
3503                                printk(KERN_WARNING
3504                                        "%s:W: may lead to stale data being accepted on reading back!\n",
3505                                                name);
3506#if DEBUG
3507                                printk(OSST_DEB_MSG
3508                                  "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3509                                        name, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn);
3510#endif
3511                        }
3512                }
3513                STp->fast_open = 0;
3514        }
3515        if (!STp->header_ok) {
3516#if DEBUG
3517                printk(OSST_DEB_MSG "%s:D: Write cannot proceed without valid headers\n", name);
3518#endif
3519                retval = (-EIO);
3520                goto out;
3521        }
3522
3523        if ((STp->buffer)->writing) {
3524if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name, __LINE__);
3525                osst_write_behind_check(STp);
3526                if ((STp->buffer)->syscall_result) {
3527#if DEBUG
3528                if (debugging)
3529                        printk(OSST_DEB_MSG "%s:D: Async write error (write) %x.\n", name,
3530                                                 (STp->buffer)->midlevel_result);
3531#endif
3532                if ((STp->buffer)->midlevel_result == INT_MAX)
3533                        STps->eof = ST_EOM_OK;
3534                else
3535                        STps->eof = ST_EOM_ERROR;
3536                }
3537        }
3538        if (STps->eof == ST_EOM_OK) {
3539                retval = (-ENOSPC);
3540                goto out;
3541        }
3542        else if (STps->eof == ST_EOM_ERROR) {
3543                retval = (-EIO);
3544                goto out;
3545        }
3546
3547        /* Check the buffer readability in cases where copy_user might catch
3548                 the problems after some tape movement. */
3549        if ((copy_from_user(&i, buf, 1) != 0 ||
3550             copy_from_user(&i, buf + count - 1, 1) != 0)) {
3551                retval = (-EFAULT);
3552                goto out;
3553        }
3554
3555        if (!STm->do_buffer_writes) {
3556                write_threshold = 1;
3557        }
3558        else
3559                write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;
3560        if (!STm->do_async_writes)
3561                write_threshold--;
3562
3563        total = count;
3564#if DEBUG
3565        if (debugging)
3566                printk(OSST_DEB_MSG "%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3567                                name, (int) count, STps->drv_file, STps->drv_block,
3568                                STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
3569#endif
3570        b_point = buf;
3571        while ((STp->buffer)->buffer_bytes + count > write_threshold)
3572        {
3573                doing_write = 1;
3574                do_count = (STp->buffer)->buffer_blocks * STp->block_size -
3575                           (STp->buffer)->buffer_bytes;
3576                if (do_count > count)
3577                        do_count = count;
3578
3579                i = append_to_buffer(b_point, STp->buffer, do_count);
3580                if (i) {
3581                        retval = i;
3582                        goto out;
3583                }
3584
3585                blks = do_count / STp->block_size;
3586                STp->logical_blk_num += blks;  /* logical_blk_num is incremented as data is moved from user */
3587  
3588                i = osst_write_frame(STp, &SRpnt, 1);
3589
3590                if (i == (-ENOSPC)) {
3591                        transfer = STp->buffer->writing;        /* FIXME -- check this logic */
3592                        if (transfer <= do_count) {
3593                                *ppos += do_count - transfer;
3594                                count -= do_count - transfer;
3595                                if (STps->drv_block >= 0) {
3596                                        STps->drv_block += (do_count - transfer) / STp->block_size;
3597                                }
3598                                STps->eof = ST_EOM_OK;
3599                                retval = (-ENOSPC);             /* EOM within current request */
3600#if DEBUG
3601                                if (debugging)
3602                                      printk(OSST_DEB_MSG "%s:D: EOM with %d bytes unwritten.\n",
3603                                                             name, (int) transfer);
3604#endif
3605                        }
3606                        else {
3607                                STps->eof = ST_EOM_ERROR;
3608                                STps->drv_block = (-1);         /* Too cautious? */
3609                                retval = (-EIO);                /* EOM for old data */
3610#if DEBUG
3611                                if (debugging)
3612                                      printk(OSST_DEB_MSG "%s:D: EOM with lost data.\n", name);
3613#endif
3614                        }
3615                }
3616                else
3617                        retval = i;
3618                        
3619                if (retval < 0) {
3620                        if (SRpnt != NULL) {
3621                                osst_release_request(SRpnt);
3622                                SRpnt = NULL;
3623                        }
3624                        STp->buffer->buffer_bytes = 0;
3625                        STp->dirty = 0;
3626                        if (count < total)
3627                                retval = total - count;
3628                        goto out;
3629                }
3630
3631                *ppos += do_count;
3632                b_point += do_count;
3633                count -= do_count;
3634                if (STps->drv_block >= 0) {
3635                        STps->drv_block += blks;
3636                }
3637                STp->buffer->buffer_bytes = 0;
3638                STp->dirty = 0;
3639        }  /* end while write threshold exceeded */
3640
3641        if (count != 0) {
3642                STp->dirty = 1;
3643                i = append_to_buffer(b_point, STp->buffer, count);
3644                if (i) {
3645                        retval = i;
3646                        goto out;
3647                }
3648                blks = count / STp->block_size;
3649                STp->logical_blk_num += blks;
3650                if (STps->drv_block >= 0) {
3651                        STps->drv_block += blks;
3652                }
3653                *ppos += count;
3654                count = 0;
3655        }
3656
3657        if (doing_write && (STp->buffer)->syscall_result != 0) {
3658                retval = (STp->buffer)->syscall_result;
3659                goto out;
3660        }
3661
3662        if (STm->do_async_writes && ((STp->buffer)->buffer_bytes >= STp->write_threshold)) { 
3663                /* Schedule an asynchronous write */
3664                (STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
3665                                           STp->block_size) * STp->block_size;
3666                STp->dirty = !((STp->buffer)->writing ==
3667                                          (STp->buffer)->buffer_bytes);
3668
3669                i = osst_write_frame(STp, &SRpnt, 0);
3670                if (i < 0) {
3671                        retval = (-EIO);
3672                        goto out;
3673                }
3674                SRpnt = NULL;                   /* Prevent releasing this request! */
3675        }
3676        STps->at_sm &= (total == 0);
3677        if (total > 0)
3678                STps->eof = ST_NOEOF;
3679
3680        retval = total;
3681
3682out:
3683        if (SRpnt != NULL) osst_release_request(SRpnt);
3684
3685        mutex_unlock(&STp->lock);
3686
3687        return retval;
3688}
3689
3690
3691/* Read command */
3692static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, loff_t *ppos)
3693{
3694        ssize_t               total, retval = 0;
3695        ssize_t               i, transfer;
3696        int                   special;
3697        struct st_modedef   * STm;
3698        struct st_partstat  * STps;
3699        struct osst_request * SRpnt = NULL;
3700        struct osst_tape    * STp   = filp->private_data;
3701        char                * name  = tape_name(STp);
3702
3703
3704        if (mutex_lock_interruptible(&STp->lock))
3705                return (-ERESTARTSYS);
3706
3707        /*
3708         * If we are in the middle of error recovery, don't let anyone
3709         * else try and use this device.  Also, if error recovery fails, it
3710         * may try and take the device offline, in which case all further
3711         * access to the device is prohibited.
3712         */
3713        if( !scsi_block_when_processing_errors(STp->device) ) {
3714                retval = (-ENXIO);
3715                goto out;
3716        }
3717        
3718        if (STp->ready != ST_READY) {
3719                if (STp->ready == ST_NO_TAPE)
3720                        retval = (-ENOMEDIUM);
3721                else
3722                        retval = (-EIO);
3723                goto out;
3724        }
3725        STm = &(STp->modes[STp->current_mode]);
3726        if (!STm->defined) {
3727                retval = (-ENXIO);
3728                goto out;
3729        }
3730#if DEBUG
3731        if (!STp->in_use) {
3732                printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3733                retval = (-EIO);
3734                goto out;
3735        }
3736#endif
3737        /* Must have initialized medium */
3738        if (!STp->header_ok) {
3739                retval = (-EIO);
3740                goto out;
3741        }
3742
3743        if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3744                STp->door_locked = ST_LOCKED_AUTO;
3745
3746        STps = &(STp->ps[STp->partition]);
3747        if (STps->rw == ST_WRITING) {
3748                retval = osst_flush_buffer(STp, &SRpnt, 0);
3749                if (retval)
3750                        goto out;
3751                STps->rw = ST_IDLE;
3752                /* FIXME -- this may leave the tape without EOD and up2date headers */
3753        }
3754
3755        if ((count % STp->block_size) != 0) {
3756                printk(KERN_WARNING
3757                    "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name, count,
3758                    STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3759        }
3760
3761#if DEBUG
3762        if (debugging && STps->eof != ST_NOEOF)
3763                printk(OSST_DEB_MSG "%s:D: EOF/EOM flag up (%d). Bytes %d\n", name,
3764                                     STps->eof, (STp->buffer)->buffer_bytes);
3765#endif
3766        if ((STp->buffer)->buffer_bytes == 0 &&
3767             STps->eof >= ST_EOD_1) {
3768                if (STps->eof < ST_EOD) {
3769                        STps->eof += 1;
3770                        retval = 0;
3771                        goto out;
3772                }
3773                retval = (-EIO);  /* EOM or Blank Check */
3774                goto out;
3775        }
3776
3777        /* Check the buffer writability before any tape movement. Don't alter
3778                 buffer data. */
3779        if (copy_from_user(&i, buf, 1)             != 0 ||
3780            copy_to_user  (buf, &i, 1)             != 0 ||
3781            copy_from_user(&i, buf + count - 1, 1) != 0 ||
3782            copy_to_user  (buf + count - 1, &i, 1) != 0) {
3783                retval = (-EFAULT);
3784                goto out;
3785        }
3786
3787        /* Loop until enough data in buffer or a special condition found */
3788        for (total = 0, special = 0; total < count - STp->block_size + 1 && !special; ) {
3789
3790                /* Get new data if the buffer is empty */
3791                if ((STp->buffer)->buffer_bytes == 0) {
3792                        if (STps->eof == ST_FM_HIT)
3793                                break;
3794                        special = osst_get_logical_frame(STp, &SRpnt, STp->frame_seq_number, 0);
3795                        if (special < 0) {                      /* No need to continue read */
3796                                STp->frame_in_buffer = 0;
3797                                retval = special;
3798                                goto out;
3799                        }
3800                }
3801
3802                /* Move the data from driver buffer to user buffer */
3803                if ((STp->buffer)->buffer_bytes > 0) {
3804#if DEBUG
3805                        if (debugging && STps->eof != ST_NOEOF)
3806                            printk(OSST_DEB_MSG "%s:D: EOF up (%d). Left %d, needed %d.\n", name,
3807                                                 STps->eof, (STp->buffer)->buffer_bytes, (int) (count - total));
3808#endif
3809                        /* force multiple of block size, note block_size may have been adjusted */
3810                        transfer = (((STp->buffer)->buffer_bytes < count - total ?
3811                                     (STp->buffer)->buffer_bytes : count - total)/
3812                                        STp->block_size) * STp->block_size;
3813
3814                        if (transfer == 0) {
3815                                printk(KERN_WARNING
3816                                  "%s:W: Nothing can be transferred, requested %Zd, tape block size (%d%c).\n",
3817                                        name, count, STp->block_size < 1024?
3818                                        STp->block_size:STp->block_size/1024,
3819                                        STp->block_size<1024?'b':'k');
3820                                break;
3821                        }
3822                        i = from_buffer(STp->buffer, buf, transfer);
3823                        if (i)  {
3824                                retval = i;
3825                                goto out;
3826                        }
3827                        STp->logical_blk_num += transfer / STp->block_size;
3828                        STps->drv_block      += transfer / STp->block_size;
3829                        *ppos          += transfer;
3830                        buf                  += transfer;
3831                        total                += transfer;
3832                }
3833 
3834                if ((STp->buffer)->buffer_bytes == 0) {
3835#if DEBUG
3836                        if (debugging)
3837                                printk(OSST_DEB_MSG "%s:D: Finished with frame %d\n",
3838                                                name, STp->frame_seq_number);
3839#endif
3840                        STp->frame_in_buffer = 0;
3841                        STp->frame_seq_number++;              /* frame to look for next time */
3842                }
3843        } /* for (total = 0, special = 0; total < count && !special; ) */
3844
3845        /* Change the eof state if no data from tape or buffer */
3846        if (total == 0) {
3847                if (STps->eof == ST_FM_HIT) {
3848                        STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD_2:ST_FM;
3849                        STps->drv_block = 0;
3850                        if (STps->drv_file >= 0)
3851                                STps->drv_file++;
3852                }
3853                else if (STps->eof == ST_EOD_1) {
3854                        STps->eof = ST_EOD_2;
3855                        if (STps->drv_block > 0 && STps->drv_file >= 0)
3856                                STps->drv_file++;
3857                        STps->drv_block = 0;
3858                }
3859                else if (STps->eof == ST_EOD_2)
3860                        STps->eof = ST_EOD;
3861        }
3862        else if (STps->eof == ST_FM)
3863                STps->eof = ST_NOEOF;
3864
3865        retval = total;
3866
3867out:
3868        if (SRpnt != NULL) osst_release_request(SRpnt);
3869
3870        mutex_unlock(&STp->lock);
3871
3872        return retval;
3873}
3874
3875
3876/* Set the driver options */
3877static void osst_log_options(struct osst_tape *STp, struct st_modedef *STm, char *name)
3878{
3879  printk(KERN_INFO
3880"%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3881         name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
3882         STm->do_read_ahead);
3883  printk(KERN_INFO
3884"%s:I:    can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3885         name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
3886  printk(KERN_INFO
3887"%s:I:    defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3888         name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
3889         STp->scsi2_logical);
3890  printk(KERN_INFO
3891"%s:I:    sysv: %d\n", name, STm->sysv);
3892#if DEBUG
3893  printk(KERN_INFO
3894         "%s:D:    debugging: %d\n",
3895         name, debugging);
3896#endif
3897}
3898
3899
3900static int osst_set_options(struct osst_tape *STp, long options)
3901{
3902        int                 value;
3903        long                code;
3904        struct st_modedef * STm;
3905        char              * name = tape_name(STp);
3906
3907        STm = &(STp->modes[STp->current_mode]);
3908        if (!STm->defined) {
3909                memcpy(STm, &(STp->modes[0]), sizeof(*STm));
3910                modes_defined = 1;
3911#if DEBUG
3912                if (debugging)
3913                        printk(OSST_DEB_MSG "%s:D: Initialized mode %d definition from mode 0\n",
3914                                             name, STp->current_mode);
3915#endif
3916        }
3917
3918        code = options & MT_ST_OPTIONS;
3919        if (code == MT_ST_BOOLEANS) {
3920                STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
3921                STm->do_async_writes  = (options & MT_ST_ASYNC_WRITES) != 0;
3922                STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
3923                STm->do_read_ahead    = (options & MT_ST_READ_AHEAD) != 0;
3924                STp->two_fm           = (options & MT_ST_TWO_FM) != 0;
3925                STp->fast_mteom       = (options & MT_ST_FAST_MTEOM) != 0;
3926                STp->do_auto_lock     = (options & MT_ST_AUTO_LOCK) != 0;
3927                STp->can_bsr          = (options & MT_ST_CAN_BSR) != 0;
3928                STp->omit_blklims     = (options & MT_ST_NO_BLKLIMS) != 0;
3929                if ((STp->device)->scsi_level >= SCSI_2)
3930                        STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
3931                STp->scsi2_logical    = (options & MT_ST_SCSI2LOGICAL) != 0;
3932                STm->sysv             = (options & MT_ST_SYSV) != 0;
3933#if DEBUG
3934                debugging = (options & MT_ST_DEBUGGING) != 0;
3935#endif
3936                osst_log_options(STp, STm, name);
3937        }
3938        else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
3939                value = (code == MT_ST_SETBOOLEANS);
3940                if ((options & MT_ST_BUFFER_WRITES) != 0)
3941                        STm->do_buffer_writes = value;
3942                if ((options & MT_ST_ASYNC_WRITES) != 0)
3943                        STm->do_async_writes = value;
3944                if ((options & MT_ST_DEF_WRITES) != 0)
3945                        STm->defaults_for_writes = value;
3946                if ((options & MT_ST_READ_AHEAD) != 0)
3947                        STm->do_read_ahead = value;
3948                if ((options & MT_ST_TWO_FM) != 0)
3949                        STp->two_fm = value;
3950                if ((options & MT_ST_FAST_MTEOM) != 0)
3951                        STp->fast_mteom = value;
3952                if ((options & MT_ST_AUTO_LOCK) != 0)
3953                        STp->do_auto_lock = value;
3954                if ((options & MT_ST_CAN_BSR) != 0)
3955                        STp->can_bsr = value;
3956                if ((options & MT_ST_NO_BLKLIMS) != 0)
3957                        STp->omit_blklims = value;
3958                if ((STp->device)->scsi_level >= SCSI_2 &&
3959                    (options & MT_ST_CAN_PARTITIONS) != 0)
3960                        STp->can_partitions = value;
3961                if ((options & MT_ST_SCSI2LOGICAL) != 0)
3962                        STp->scsi2_logical = value;
3963                if ((options & MT_ST_SYSV) != 0)
3964                        STm->sysv = value;
3965#if DEBUG
3966                if ((options & MT_ST_DEBUGGING) != 0)
3967                        debugging = value;
3968#endif
3969                osst_log_options(STp, STm, name);
3970        }
3971        else if (code == MT_ST_WRITE_THRESHOLD) {
3972                value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
3973                if (value < 1 || value > osst_buffer_size) {
3974                        printk(KERN_WARNING "%s:W: Write threshold %d too small or too large.\n",
3975                                             name, value);
3976                        return (-EIO);
3977                }
3978                STp->write_threshold = value;
3979                printk(KERN_INFO "%s:I: Write threshold set to %d bytes.\n",
3980                                  name, value);
3981        }
3982        else if (code == MT_ST_DEF_BLKSIZE) {
3983                value = (options & ~MT_ST_OPTIONS);
3984                if (value == ~MT_ST_OPTIONS) {
3985                        STm->default_blksize = (-1);
3986                        printk(KERN_INFO "%s:I: Default block size disabled.\n", name);
3987                }
3988                else {
3989                        if (value < 512 || value > OS_DATA_SIZE || OS_DATA_SIZE % value) {
3990                                printk(KERN_WARNING "%s:W: Default block size cannot be set to %d.\n",
3991                                                         name, value);
3992                                return (-EINVAL);
3993                        }
3994                        STm->default_blksize = value;
3995                        printk(KERN_INFO "%s:I: Default block size set to %d bytes.\n",
3996                                          name, STm->default_blksize);
3997                }
3998        }
3999        else if (code == MT_ST_TIMEOUTS) {
4000                value = (options & ~MT_ST_OPTIONS);
4001                if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
4002                        STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
4003                        printk(KERN_INFO "%s:I: Long timeout set to %d seconds.\n", name,
4004                                             (value & ~MT_ST_SET_LONG_TIMEOUT));
4005                }
4006                else {
4007                        STp->timeout = value * HZ;
4008                        printk(KERN_INFO "%s:I: Normal timeout set to %d seconds.\n", name, value);
4009                }
4010        }
4011        else if (code == MT_ST_DEF_OPTIONS) {
4012                code = (options & ~MT_ST_CLEAR_DEFAULT);
4013                value = (options & MT_ST_CLEAR_DEFAULT);
4014                if (code == MT_ST_DEF_DENSITY) {
4015                        if (value == MT_ST_CLEAR_DEFAULT) {
4016                                STm->default_density = (-1);
4017                                printk(KERN_INFO "%s:I: Density default disabled.\n", name);
4018                        }
4019                        else {
4020                                STm->default_density = value & 0xff;
4021                                printk(KERN_INFO "%s:I: Density default set to %x\n",
4022                                                  name, STm->default_density);
4023                        }
4024                }
4025                else if (code == MT_ST_DEF_DRVBUFFER) {
4026                        if (value == MT_ST_CLEAR_DEFAULT) {
4027                                STp->default_drvbuffer = 0xff;
4028                                printk(KERN_INFO "%s:I: Drive buffer default disabled.\n", name);
4029                        }
4030                        else {
4031                                STp->default_drvbuffer = value & 7;
4032                                printk(KERN_INFO "%s:I: Drive buffer default set to %x\n",
4033                                                  name, STp->default_drvbuffer);
4034                        }
4035                }
4036                else if (code == MT_ST_DEF_COMPRESSION) {
4037                        if (value == MT_ST_CLEAR_DEFAULT) {
4038                                STm->default_compression = ST_DONT_TOUCH;
4039                                printk(KERN_INFO "%s:I: Compression default disabled.\n", name);
4040                        }
4041                        else {
4042                                STm->default_compression = (value & 1 ? ST_YES : ST_NO);
4043                                printk(KERN_INFO "%s:I: Compression default set to %x\n",
4044                                                  name, (value & 1));
4045                        }
4046                }
4047        }
4048        else
4049                return (-EIO);
4050
4051        return 0;
4052}
4053
4054
4055/* Internal ioctl function */
4056static int osst_int_ioctl(struct osst_tape * STp, struct osst_request ** aSRpnt,
4057                             unsigned int cmd_in, unsigned long arg)
4058{
4059        int                     timeout;
4060        long                    ltmp;
4061        int                     i, ioctl_result;
4062        int                     chg_eof = 1;
4063        unsigned char           cmd[MAX_COMMAND_SIZE];
4064        struct osst_request   * SRpnt = * aSRpnt;
4065        struct st_partstat    * STps;
4066        int                     fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
4067        int                     datalen = 0, direction = DMA_NONE;
4068        char                  * name = tape_name(STp);
4069
4070        if (STp->ready != ST_READY && cmd_in != MTLOAD) {
4071                if (STp->ready == ST_NO_TAPE)
4072                        return (-ENOMEDIUM);
4073                else
4074                        return (-EIO);
4075        }
4076        timeout = STp->long_timeout;
4077        STps = &(STp->ps[STp->partition]);
4078        fileno = STps->drv_file;
4079        blkno = STps->drv_block;
4080        at_sm = STps->at_sm;
4081        frame_seq_numbr = STp->frame_seq_number;
4082        logical_blk_num = STp->logical_blk_num;
4083
4084        memset(cmd, 0, MAX_COMMAND_SIZE);
4085        switch (cmd_in) {
4086         case MTFSFM:
4087                chg_eof = 0; /* Changed from the FSF after this */
4088         case MTFSF:
4089                if (STp->raw)
4090                   return (-EIO);
4091                if (STp->linux_media)
4092                   ioctl_result = osst_space_over_filemarks_forward_fast(STp, &SRpnt, cmd_in, arg);
4093                else
4094                   ioctl_result = osst_space_over_filemarks_forward_slow(STp, &SRpnt, cmd_in, arg);
4095                if (fileno >= 0)
4096                   fileno += arg;
4097                blkno = 0;
4098                at_sm &= (arg == 0);
4099                goto os_bypass;
4100
4101         case MTBSF:
4102                chg_eof = 0; /* Changed from the FSF after this */
4103         case MTBSFM:
4104                if (STp->raw)
4105                   return (-EIO);
4106                ioctl_result = osst_space_over_filemarks_backward(STp, &SRpnt, cmd_in, arg);
4107                if (fileno >= 0)
4108                   fileno -= arg;
4109                blkno = (-1);  /* We can't know the block number */
4110                at_sm &= (arg == 0);
4111                goto os_bypass;
4112
4113         case MTFSR:
4114         case MTBSR:
4115#if DEBUG
4116                if (debugging)
4117                   printk(OSST_DEB_MSG "%s:D: Skipping %lu blocks %s from logical block %d\n",
4118                                name, arg, cmd_in==MTFSR?"forward":"backward", logical_blk_num);
4119#endif
4120                if (cmd_in == MTFSR) {
4121                   logical_blk_num += arg;
4122                   if (blkno >= 0) blkno += arg;
4123                }
4124                else {
4125                   logical_blk_num -= arg;
4126                   if (blkno >= 0) blkno -= arg;
4127                }
4128                ioctl_result = osst_seek_logical_blk(STp, &SRpnt, logical_blk_num);
4129                fileno = STps->drv_file;
4130                blkno  = STps->drv_block;
4131                at_sm &= (arg == 0);
4132                goto os_bypass;
4133
4134         case MTFSS:
4135                cmd[0] = SPACE;
4136                cmd[1] = 0x04; /* Space Setmarks */   /* FIXME -- OS can't do this? */
4137                cmd[2] = (arg >> 16);
4138                cmd[3] = (arg >> 8);
4139                cmd[4] = arg;
4140#if DEBUG
4141                if (debugging)
4142                        printk(OSST_DEB_MSG "%s:D: Spacing tape forward %d setmarks.\n", name,
4143                cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4144#endif
4145                if (arg != 0) {
4146                        blkno = fileno = (-1);
4147                        at_sm = 1;
4148                }
4149                break;
4150         case MTBSS:
4151                cmd[0] = SPACE;
4152                cmd[1] = 0x04; /* Space Setmarks */   /* FIXME -- OS can't do this? */
4153                ltmp = (-arg);
4154                cmd[2] = (ltmp >> 16);
4155                cmd[3] = (ltmp >> 8);
4156                cmd[4] = ltmp;
4157#if DEBUG
4158                if (debugging) {
4159                        if (cmd[2] & 0x80)
4160                           ltmp = 0xff000000;
4161                        ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
4162                        printk(OSST_DEB_MSG "%s:D: Spacing tape backward %ld setmarks.\n",
4163                                                name, (-ltmp));
4164                 }
4165#endif
4166                 if (arg != 0) {
4167                        blkno = fileno = (-1);
4168                        at_sm = 1;
4169                 }
4170                 break;
4171         case MTWEOF:
4172                 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4173                        STp->write_type = OS_WRITE_DATA;
4174                        ioctl_result = osst_flush_write_buffer(STp, &SRpnt);
4175                 } else
4176                        ioctl_result = 0;
4177#if DEBUG
4178                 if (debugging) 
4179                           printk(OSST_DEB_MSG "%s:D: Writing %ld filemark(s).\n", name, arg);
4180#endif
4181                 for (i=0; i<arg; i++)
4182                        ioctl_result |= osst_write_filemark(STp, &SRpnt);
4183                 if (fileno >= 0) fileno += arg;
4184                 if (blkno  >= 0) blkno   = 0;
4185                 goto os_bypass;
4186
4187         case MTWSM:
4188                 if (STp->write_prot)
4189                        return (-EACCES);
4190                 if (!STp->raw)
4191                        return 0;
4192                 cmd[0] = WRITE_FILEMARKS;   /* FIXME -- need OS version */
4193                 if (cmd_in == MTWSM)
4194                         cmd[1] = 2;
4195                 cmd[2] = (arg >> 16);
4196                 cmd[3] = (arg >> 8);
4197                 cmd[4] = arg;
4198                 timeout = STp->timeout;
4199#if DEBUG
4200                 if (debugging) 
4201                           printk(OSST_DEB_MSG "%s:D: Writing %d setmark(s).\n", name,
4202                                  cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4203#endif
4204                 if (fileno >= 0)
4205                        fileno += arg;
4206                 blkno = 0;
4207                 at_sm = (cmd_in == MTWSM);
4208                 break;
4209         case MTOFFL:
4210         case MTLOAD:
4211         case MTUNLOAD:
4212         case MTRETEN:
4213                 cmd[0] = START_STOP;
4214                 cmd[1] = 1;                    /* Don't wait for completion */
4215                 if (cmd_in == MTLOAD) {
4216                     if (STp->ready == ST_NO_TAPE)
4217                         cmd[4] = 4;            /* open tray */
4218                      else
4219                         cmd[4] = 1;            /* load */
4220                 }
4221                 if (cmd_in == MTRETEN)
4222                         cmd[4] = 3;            /* retension then mount */
4223                 if (cmd_in == MTOFFL)
4224                         cmd[4] = 4;            /* rewind then eject */
4225                 timeout = STp->timeout;
4226#if DEBUG
4227                 if (debugging) {
4228                         switch (cmd_in) {
4229                                 case MTUNLOAD:
4230                                         printk(OSST_DEB_MSG "%s:D: Unloading tape.\n", name);
4231                                         break;
4232                                 case MTLOAD:
4233                                         printk(OSST_DEB_MSG "%s:D: Loading tape.\n", name);
4234                                         break;
4235                                 case MTRETEN:
4236                                         printk(OSST_DEB_MSG "%s:D: Retensioning tape.\n", name);
4237                                         break;
4238                                 case MTOFFL:
4239                                         printk(OSST_DEB_MSG "%s:D: Ejecting tape.\n", name);
4240                                         break;
4241                         }
4242                 }
4243#endif
4244       fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4245                 break;
4246         case MTNOP:
4247#if DEBUG
4248                 if (debugging)
4249                         printk(OSST_DEB_MSG "%s:D: No-op on tape.\n", name);
4250#endif
4251                 return 0;  /* Should do something ? */
4252                 break;
4253         case MTEOM:
4254#if DEBUG
4255                if (debugging)
4256                   printk(OSST_DEB_MSG "%s:D: Spacing to end of recorded medium.\n", name);
4257#endif
4258                if ((osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0) ||
4259                            (osst_get_logical_frame(STp, &SRpnt, -1, 0)               < 0)) {
4260                   ioctl_result = -EIO;
4261                   goto os_bypass;
4262                }
4263                if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_EOD) {
4264#if DEBUG
4265                   printk(OSST_DEB_MSG "%s:D: No EOD frame found where expected.\n", name);
4266#endif
4267                   ioctl_result = -EIO;
4268                   goto os_bypass;
4269                }
4270                ioctl_result = osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0);
4271                fileno = STp->filemark_cnt;
4272                blkno  = at_sm = 0;
4273                goto os_bypass;
4274
4275         case MTERASE:
4276                if (STp->write_prot)
4277                   return (-EACCES);
4278                ioctl_result = osst_reset_header(STp, &SRpnt);
4279                i = osst_write_eod(STp, &SRpnt);
4280                if (i < ioctl_result) ioctl_result = i;
4281                i = osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos);
4282                if (i < ioctl_result) ioctl_result = i;
4283                fileno = blkno = at_sm = 0 ;
4284                goto os_bypass;
4285
4286         case MTREW:
4287                cmd[0] = REZERO_UNIT; /* rewind */
4288                cmd[1] = 1;
4289#if DEBUG
4290                if (debugging)
4291                   printk(OSST_DEB_MSG "%s:D: Rewinding tape, Immed=%d.\n", name, cmd[1]);
4292#endif
4293                fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4294                break;
4295
4296         case MTSETBLK:           /* Set block length */
4297                 if ((STps->drv_block == 0 )                      &&
4298                     !STp->dirty                                  &&
4299                     ((STp->buffer)->buffer_bytes == 0)           &&
4300                     ((arg & MT_ST_BLKSIZE_MASK) >= 512 )         && 
4301                     ((arg & MT_ST_BLKSIZE_MASK) <= OS_DATA_SIZE) &&
4302                     !(OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))  ) {
4303                         /*
4304                          * Only allowed to change the block size if you opened the
4305                          * device at the beginning of a file before writing anything.
4306                          * Note, that when reading, changing block_size is futile,
4307                          * as the size used when writing overrides it.
4308                          */
4309                         STp->block_size = (arg & MT_ST_BLKSIZE_MASK);
4310                         printk(KERN_INFO "%s:I: Block size set to %d bytes.\n",
4311                                           name, STp->block_size);
4312                         return 0;
4313                 }
4314         case MTSETDENSITY:       /* Set tape density */
4315         case MTSETDRVBUFFER:     /* Set drive buffering */
4316         case SET_DENS_AND_BLK:   /* Set density and block size */
4317                 chg_eof = 0;
4318                 if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
4319                         return (-EIO);       /* Not allowed if data in buffer */
4320                 if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
4321                     (arg & MT_ST_BLKSIZE_MASK) != 0                    &&
4322                     (arg & MT_ST_BLKSIZE_MASK) != STp->block_size       ) {
4323                         printk(KERN_WARNING "%s:W: Illegal to set block size to %d%s.\n",
4324                                                name, (int)(arg & MT_ST_BLKSIZE_MASK),
4325                                                (OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))?"":" now");
4326                         return (-EINVAL);
4327                 }
4328                 return 0;  /* FIXME silently ignore if block size didn't change */
4329
4330         default:
4331                return (-ENOSYS);
4332        }
4333
4334        SRpnt = osst_do_scsi(SRpnt, STp, cmd, datalen, direction, timeout, MAX_RETRIES, 1);
4335
4336        ioctl_result = (STp->buffer)->syscall_result;
4337
4338        if (!SRpnt) {
4339#if DEBUG
4340                printk(OSST_DEB_MSG "%s:D: Couldn't exec scsi cmd for IOCTL\n", name);
4341#endif
4342                return ioctl_result;
4343        }
4344
4345        if (!ioctl_result) {  /* SCSI command successful */
4346                STp->frame_seq_number = frame_seq_numbr;
4347                STp->logical_blk_num  = logical_blk_num;
4348        }
4349
4350os_bypass:
4351#if DEBUG
4352        if (debugging)
4353                printk(OSST_DEB_MSG "%s:D: IOCTL (%d) Result=%d\n", name, cmd_in, ioctl_result);
4354#endif
4355
4356        if (!ioctl_result) {                            /* success */
4357
4358                if (cmd_in == MTFSFM) {
4359                         fileno--;
4360                         blkno--;
4361                }
4362                if (cmd_in == MTBSFM) {
4363                         fileno++;
4364                         blkno++;
4365                }
4366                STps->drv_block = blkno;
4367                STps->drv_file = fileno;
4368                STps->at_sm = at_sm;
4369
4370                if (cmd_in == MTEOM)
4371                        STps->eof = ST_EOD;
4372                else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) {
4373                        ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num-1);
4374                        STps->drv_block++;
4375                        STp->logical_blk_num++;
4376                        STp->frame_seq_number++;
4377                        STp->frame_in_buffer = 0;
4378                        STp->buffer->read_pointer = 0;
4379                }
4380                else if (cmd_in == MTFSF)
4381                        STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
4382                else if (chg_eof)
4383                        STps->eof = ST_NOEOF;
4384
4385                if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
4386                        STp->rew_at_close = 0;
4387                else if (cmd_in == MTLOAD) {
4388                        for (i=0; i < ST_NBR_PARTITIONS; i++) {
4389                            STp->ps[i].rw = ST_IDLE;
4390                            STp->ps[i].last_block_valid = 0;/* FIXME - where else is this field maintained? */
4391                        }
4392                        STp->partition = 0;
4393                }
4394
4395                if (cmd_in == MTREW) {
4396                        ioctl_result = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos); 
4397                        if (ioctl_result > 0)
4398                                ioctl_result = 0;
4399                }
4400
4401        } else if (cmd_in == MTBSF || cmd_in == MTBSFM ) {
4402                if (osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos) < 0)
4403                        STps->drv_file = STps->drv_block = -1;
4404                else
4405                        STps->drv_file = STps->drv_block = 0;
4406                STps->eof = ST_NOEOF;
4407        } else if (cmd_in == MTFSF || cmd_in == MTFSFM) {
4408                if (osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0)
4409                        STps->drv_file = STps->drv_block = -1;
4410                else {
4411                        STps->drv_file  = STp->filemark_cnt;
4412                        STps->drv_block = 0;
4413                }
4414                STps->eof = ST_EOD;
4415        } else if (cmd_in == MTBSR || cmd_in == MTFSR || cmd_in == MTWEOF || cmd_in == MTEOM) {
4416                STps->drv_file = STps->drv_block = (-1);
4417                STps->eof = ST_NOEOF;
4418                STp->header_ok = 0;
4419        } else if (cmd_in == MTERASE) {
4420                STp->header_ok = 0;
4421        } else if (SRpnt) {  /* SCSI command was not completely successful. */
4422                if (SRpnt->sense[2] & 0x40) {
4423                        STps->eof = ST_EOM_OK;
4424                        STps->drv_block = 0;
4425                }
4426                if (chg_eof)
4427                        STps->eof = ST_NOEOF;
4428
4429                if ((SRpnt->sense[2] & 0x0f) == BLANK_CHECK)
4430                        STps->eof = ST_EOD;
4431
4432                if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60))
4433                        ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
4434        }
4435        *aSRpnt = SRpnt;
4436
4437        return ioctl_result;
4438}
4439
4440
4441/* Open the device */
4442static int __os_scsi_tape_open(struct inode * inode, struct file * filp)
4443{
4444        unsigned short        flags;
4445        int                   i, b_size, new_session = 0, retval = 0;
4446        unsigned char         cmd[MAX_COMMAND_SIZE];
4447        struct osst_request * SRpnt = NULL;
4448        struct osst_tape    * STp;
4449        struct st_modedef   * STm;
4450        struct st_partstat  * STps;
4451        char                * name;
4452        int                   dev  = TAPE_NR(inode);
4453        int                   mode = TAPE_MODE(inode);
4454
4455        /*
4456         * We really want to do nonseekable_open(inode, filp); here, but some
4457         * versions of tar incorrectly call lseek on tapes and bail out if that
4458         * fails.  So we disallow pread() and pwrite(), but permit lseeks.
4459         */
4460        filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
4461
4462        write_lock(&os_scsi_tapes_lock);
4463        if (dev >= osst_max_dev || os_scsi_tapes == NULL ||
4464            (STp = os_scsi_tapes[dev]) == NULL || !STp->device) {
4465                write_unlock(&os_scsi_tapes_lock);
4466                return (-ENXIO);
4467        }
4468
4469        name = tape_name(STp);
4470
4471        if (STp->in_use) {
4472                write_unlock(&os_scsi_tapes_lock);
4473#if DEBUG
4474                printk(OSST_DEB_MSG "%s:D: Device already in use.\n", name);
4475#endif
4476                return (-EBUSY);
4477        }
4478        if (scsi_device_get(STp->device)) {
4479                write_unlock(&os_scsi_tapes_lock);
4480#if DEBUG
4481                printk(OSST_DEB_MSG "%s:D: Failed scsi_device_get.\n", name);
4482#endif
4483                return (-ENXIO);
4484        }
4485        filp->private_data = STp;
4486        STp->in_use = 1;
4487        write_unlock(&os_scsi_tapes_lock);
4488        STp->rew_at_close = TAPE_REWIND(inode);
4489
4490        if( !scsi_block_when_processing_errors(STp->device) ) {
4491                return -ENXIO;
4492        }
4493
4494        if (mode != STp->current_mode) {
4495#if DEBUG
4496                if (debugging)
4497                        printk(OSST_DEB_MSG "%s:D: Mode change from %d to %d.\n",
4498                                               name, STp->current_mode, mode);
4499#endif
4500                new_session = 1;
4501                STp->current_mode = mode;
4502        }
4503        STm = &(STp->modes[STp->current_mode]);
4504
4505        flags = filp->f_flags;
4506        STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
4507
4508        STp->raw = TAPE_IS_RAW(inode);
4509        if (STp->raw)
4510                STp->header_ok = 0;
4511
4512        /* Allocate data segments for this device's tape buffer */
4513        if (!enlarge_buffer(STp->buffer, STp->restr_dma)) {
4514                printk(KERN_ERR "%s:E: Unable to allocate memory segments for tape buffer.\n", name);
4515                retval = (-EOVERFLOW);
4516                goto err_out;
4517        }
4518        if (STp->buffer->buffer_size >= OS_FRAME_SIZE) {
4519                for (i = 0, b_size = 0; 
4520                     (i < STp->buffer->sg_segs) && ((b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE); 
4521                     b_size += STp->buffer->sg[i++].length);
4522                STp->buffer->aux = (os_aux_t *) (page_address(sg_page(&STp->buffer->sg[i])) + OS_DATA_SIZE - b_size);
4523#if DEBUG
4524                printk(OSST_DEB_MSG "%s:D: b_data points to %p in segment 0 at %p\n", name,
4525                        STp->buffer->b_data, page_address(STp->buffer->sg[0].page));
4526                printk(OSST_DEB_MSG "%s:D: AUX points to %p in segment %d at %p\n", name,
4527                         STp->buffer->aux, i, page_address(STp->buffer->sg[i].page));
4528#endif
4529        } else {
4530                STp->buffer->aux = NULL; /* this had better never happen! */
4531                printk(KERN_NOTICE "%s:A: Framesize %d too large for buffer.\n", name, OS_FRAME_SIZE);
4532                retval = (-EIO);
4533                goto err_out;
4534        }
4535        STp->buffer->writing = 0;
4536        STp->buffer->syscall_result = 0;
4537        STp->dirty = 0;
4538        for (i=0; i < ST_NBR_PARTITIONS; i++) {
4539                STps = &(STp->ps[i]);
4540                STps->rw = ST_IDLE;
4541        }
4542        STp->ready = ST_READY;
4543#if DEBUG
4544        STp->nbr_waits = STp->nbr_finished = 0;
4545#endif
4546
4547        memset (cmd, 0, MAX_COMMAND_SIZE);
4548        cmd[0] = TEST_UNIT_READY;
4549
4550        SRpnt = osst_do_scsi(NULL, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
4551        if (!SRpnt) {
4552                retval = (STp->buffer)->syscall_result;         /* FIXME - valid? */
4553                goto err_out;
4554        }
4555        if ((SRpnt->sense[0] & 0x70) == 0x70      &&
4556            (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4557             SRpnt->sense[12]        == 4         ) {
4558#if DEBUG
4559                printk(OSST_DEB_MSG "%s:D: Unit not ready, cause %x\n", name, SRpnt->sense[13]);
4560#endif
4561                if (filp->f_flags & O_NONBLOCK) {
4562                        retval = -EAGAIN;
4563                        goto err_out;
4564                }
4565                if (SRpnt->sense[13] == 2) {    /* initialize command required (LOAD) */
4566                        memset (cmd, 0, MAX_COMMAND_SIZE);
4567                        cmd[0] = START_STOP;
4568                        cmd[1] = 1;
4569                        cmd[4] = 1;
4570                        SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4571                                             STp->timeout, MAX_RETRIES, 1);
4572                }
4573                osst_wait_ready(STp, &SRpnt, (SRpnt->sense[13]==1?15:3) * 60, 0);
4574        }
4575        if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4576            (SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
4577#if DEBUG
4578                printk(OSST_DEB_MSG "%s:D: Unit wants attention\n", name);
4579#endif
4580                STp->header_ok = 0;
4581
4582                for (i=0; i < 10; i++) {
4583
4584                        memset (cmd, 0, MAX_COMMAND_SIZE);
4585                        cmd[0] = TEST_UNIT_READY;
4586
4587                        SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4588                                             STp->timeout, MAX_RETRIES, 1);
4589                        if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4590                            (SRpnt->sense[2] & 0x0f) != UNIT_ATTENTION)
4591                                break;
4592                }
4593
4594                STp->pos_unknown = 0;
4595                STp->partition = STp->new_partition = 0;
4596                if (STp->can_partitions)
4597                        STp->nbr_partitions = 1;  /* This guess will be updated later if necessary */
4598                for (i=0; i < ST_NBR_PARTITIONS; i++) {
4599                        STps = &(STp->ps[i]);
4600                        STps->rw = ST_IDLE;             /* FIXME - seems to be redundant... */
4601                        STps->eof = ST_NOEOF;
4602                        STps->at_sm = 0;
4603                        STps->last_block_valid = 0;
4604                        STps->drv_block = 0;
4605                        STps->drv_file = 0 ;
4606                }
4607                new_session = 1;
4608                STp->recover_count = 0;
4609                STp->abort_count = 0;
4610        }
4611        /*
4612         * if we have valid headers from before, and the drive/tape seem untouched,
4613         * open without reconfiguring and re-reading the headers
4614         */
4615        if (!STp->buffer->syscall_result && STp->header_ok &&
4616            !SRpnt->result && SRpnt->sense[0] == 0) {
4617
4618                memset(cmd, 0, MAX_COMMAND_SIZE);
4619                cmd[0] = MODE_SENSE;
4620                cmd[1] = 8;
4621                cmd[2] = VENDOR_IDENT_PAGE;
4622                cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
4623
4624                SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
4625
4626                if (STp->buffer->syscall_result                     ||
4627                    STp->buffer->b_data[MODE_HEADER_LENGTH + 2] != 'L' ||
4628                    STp->buffer->b_data[MODE_HEADER_LENGTH + 3] != 'I' ||
4629                    STp->buffer->b_data[MODE_HEADER_LENGTH + 4] != 'N' ||
4630                    STp->buffer->b_data[MODE_HEADER_LENGTH + 5] != '4'  ) {
4631#if DEBUG
4632                        printk(OSST_DEB_MSG "%s:D: Signature was changed to %c%c%c%c\n", name,
4633                          STp->buffer->b_data[MODE_HEADER_LENGTH + 2],
4634                          STp->buffer->b_data[MODE_HEADER_LENGTH + 3],
4635                          STp->buffer->b_data[MODE_HEADER_LENGTH + 4],
4636                          STp->buffer->b_data[MODE_HEADER_LENGTH + 5]);
4637#endif
4638                        STp->header_ok = 0;
4639                }
4640                i = STp->first_frame_position;
4641                if (STp->header_ok && i == osst_get_frame_position(STp, &SRpnt)) {
4642                        if (STp->door_locked == ST_UNLOCKED) {
4643                                if (do_door_lock(STp, 1))
4644                                        printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4645                                else
4646                                        STp->door_locked = ST_LOCKED_AUTO;
4647                        }
4648                        if (!STp->frame_in_buffer) {
4649                                STp->block_size = (STm->default_blksize > 0) ?
4650                                                        STm->default_blksize : OS_DATA_SIZE;
4651                                STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
4652                        }
4653                        STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size;
4654                        STp->fast_open = 1;
4655                        osst_release_request(SRpnt);
4656                        return 0;
4657                }
4658#if DEBUG
4659                if (i != STp->first_frame_position)
4660                        printk(OSST_DEB_MSG "%s:D: Tape position changed from %d to %d\n",
4661                                                name, i, STp->first_frame_position);
4662#endif
4663                STp->header_ok = 0;
4664        }
4665        STp->fast_open = 0;
4666
4667        if ((STp->buffer)->syscall_result != 0 &&   /* in all error conditions except no medium */ 
4668            (SRpnt->sense[2] != 2 || SRpnt->sense[12] != 0x3A) ) {
4669
4670                memset(cmd, 0, MAX_COMMAND_SIZE);
4671                cmd[0] = MODE_SELECT;
4672                cmd[1] = 0x10;
4673                cmd[4] = 4 + MODE_HEADER_LENGTH;
4674
4675                (STp->buffer)->b_data[0] = cmd[4] - 1;
4676                (STp->buffer)->b_data[1] = 0;                   /* Medium Type - ignoring */
4677                (STp->buffer)->b_data[2] = 0;                   /* Reserved */
4678                (STp->buffer)->b_data[3] = 0;                   /* Block Descriptor Length */
4679                (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = 0x3f;
4680                (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 1;
4681                (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 2;
4682                (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 3;
4683
4684#if DEBUG
4685                printk(OSST_DEB_MSG "%s:D: Applying soft reset\n", name);
4686#endif
4687                SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
4688
4689                STp->header_ok = 0;
4690
4691                for (i=0; i < 10; i++) {
4692
4693                        memset (cmd, 0, MAX_COMMAND_SIZE);
4694                        cmd[0] = TEST_UNIT_READY;
4695
4696                        SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4697                                                    STp->timeout, MAX_RETRIES, 1);
4698                        if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4699                            (SRpnt->sense[2] & 0x0f) == NOT_READY)
4700                        break;
4701
4702                        if ((SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) {
4703                                int j;
4704
4705                                STp->pos_unknown = 0;
4706                                STp->partition = STp->new_partition = 0;
4707                                if (STp->can_partitions)
4708                                        STp->nbr_partitions = 1;  /* This guess will be updated later if necessary */
4709                                for (j = 0; j < ST_NBR_PARTITIONS; j++) {
4710                                        STps = &(STp->ps[j]);
4711                                        STps->rw = ST_IDLE;
4712                                        STps->eof = ST_NOEOF;
4713                                        STps->at_sm = 0;
4714                                        STps->last_block_valid = 0;
4715                                        STps->drv_block = 0;
4716                                        STps->drv_file = 0 ;
4717                                }
4718                                new_session = 1;
4719                        }
4720                }
4721        }
4722
4723        if (osst_wait_ready(STp, &SRpnt, 15 * 60, 0))           /* FIXME - not allowed with NOBLOCK */
4724                 printk(KERN_INFO "%s:I: Device did not become Ready in open\n", name);
4725
4726        if ((STp->buffer)->syscall_result != 0) {
4727                if ((STp->device)->scsi_level >= SCSI_2 &&
4728                    (SRpnt->sense[0] & 0x70) == 0x70 &&
4729                    (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4730                     SRpnt->sense[12] == 0x3a) { /* Check ASC */
4731                        STp->ready = ST_NO_TAPE;
4732                } else
4733                        STp->ready = ST_NOT_READY;
4734                osst_release_request(SRpnt);
4735                SRpnt = NULL;
4736                STp->density = 0;       /* Clear the erroneous "residue" */
4737                STp->write_prot = 0;
4738                STp->block_size = 0;
4739                STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
4740                STp->partition = STp->new_partition = 0;
4741                STp->door_locked = ST_UNLOCKED;
4742                return 0;
4743        }
4744
4745        osst_configure_onstream(STp, &SRpnt);
4746
4747        STp->block_size = STp->raw ? OS_FRAME_SIZE : (
4748                             (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE);
4749        STp->buffer->buffer_blocks = STp->raw ? 1 : OS_DATA_SIZE / STp->block_size;
4750        STp->buffer->buffer_bytes  =
4751        STp->buffer->read_pointer  =
4752        STp->frame_in_buffer       = 0;
4753
4754#if DEBUG
4755        if (debugging)
4756                printk(OSST_DEB_MSG "%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4757                     name, STp->block_size, OS_FRAME_SIZE, (STp->buffer)->buffer_size,
4758                     (STp->buffer)->buffer_blocks);
4759#endif
4760
4761        if (STp->drv_write_prot) {
4762                STp->write_prot = 1;
4763#if DEBUG
4764                if (debugging)
4765                        printk(OSST_DEB_MSG "%s:D: Write protected\n", name);
4766#endif
4767                if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
4768                        retval = (-EROFS);
4769                        goto err_out;
4770                }
4771        }
4772
4773        if (new_session) {  /* Change the drive parameters for the new mode */
4774#if DEBUG
4775                if (debugging)
4776        printk(OSST_DEB_MSG "%s:D: New Session\n", name);
4777#endif
4778                STp->density_changed = STp->blksize_changed = 0;
4779                STp->compression_changed = 0;
4780        }
4781
4782        /*
4783         * properly position the tape and check the ADR headers
4784         */
4785        if (STp->door_locked == ST_UNLOCKED) {
4786                 if (do_door_lock(STp, 1))
4787                        printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4788                 else
4789                        STp->door_locked = ST_LOCKED_AUTO;
4790        }
4791
4792        osst_analyze_headers(STp, &SRpnt);
4793
4794        osst_release_request(SRpnt);
4795        SRpnt = NULL;
4796
4797        return 0;
4798
4799err_out:
4800        if (SRpnt != NULL)
4801                osst_release_request(SRpnt);
4802        normalize_buffer(STp->buffer);
4803        STp->header_ok = 0;
4804        STp->in_use = 0;
4805        scsi_device_put(STp->device);
4806
4807        return retval;
4808}
4809
4810/* BKL pushdown: spaghetti avoidance wrapper */
4811static int os_scsi_tape_open(struct inode * inode, struct file * filp)
4812{
4813        int ret;
4814
4815        mutex_lock(&osst_int_mutex);
4816        ret = __os_scsi_tape_open(inode, filp);
4817        mutex_unlock(&osst_int_mutex);
4818        return ret;
4819}
4820
4821
4822
4823/* Flush the tape buffer before close */
4824static int os_scsi_tape_flush(struct file * filp, fl_owner_t id)
4825{
4826        int                   result = 0, result2;
4827        struct osst_tape    * STp    = filp->private_data;
4828        struct st_modedef   * STm    = &(STp->modes[STp->current_mode]);
4829        struct st_partstat  * STps   = &(STp->ps[STp->partition]);
4830        struct osst_request * SRpnt  = NULL;
4831        char                * name   = tape_name(STp);
4832
4833        if (file_count(filp) > 1)
4834                return 0;
4835
4836        if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4837                STp->write_type = OS_WRITE_DATA;
4838                result = osst_flush_write_buffer(STp, &SRpnt);
4839                if (result != 0 && result != (-ENOSPC))
4840                        goto out;
4841        }
4842        if ( STps->rw >= ST_WRITING && !STp->pos_unknown) {
4843
4844#if DEBUG
4845                if (debugging) {
4846                        printk(OSST_DEB_MSG "%s:D: File length %ld bytes.\n",
4847                                               name, (long)(filp->f_pos));
4848                        printk(OSST_DEB_MSG "%s:D: Async write waits %d, finished %d.\n",
4849                                               name, STp->nbr_waits, STp->nbr_finished);
4850                }
4851#endif
4852                result = osst_write_trailer(STp, &SRpnt, !(STp->rew_at_close));
4853#if DEBUG
4854                if (debugging)
4855                        printk(OSST_DEB_MSG "%s:D: Buffer flushed, %d EOF(s) written\n",
4856                                               name, 1+STp->two_fm);
4857#endif
4858        }
4859        else if (!STp->rew_at_close) {
4860                STps = &(STp->ps[STp->partition]);
4861                if (!STm->sysv || STps->rw != ST_READING) {
4862                        if (STp->can_bsr)
4863                                result = osst_flush_buffer(STp, &SRpnt, 0); /* this is the default path */
4864                        else if (STps->eof == ST_FM_HIT) {
4865                                result = cross_eof(STp, &SRpnt, 0);
4866                                        if (result) {
4867                                                if (STps->drv_file >= 0)
4868                                                        STps->drv_file++;
4869                                                STps->drv_block = 0;
4870                                                STps->eof = ST_FM;
4871                                        }
4872                                        else
4873                                                STps->eof = ST_NOEOF;
4874                        }
4875                }
4876                else if ((STps->eof == ST_NOEOF &&
4877                          !(result = cross_eof(STp, &SRpnt, 1))) ||
4878                         STps->eof == ST_FM_HIT) {
4879                        if (STps->drv_file >= 0)
4880                                STps->drv_file++;
4881                        STps->drv_block = 0;
4882                        STps->eof = ST_FM;
4883                }
4884        }
4885
4886out:
4887        if (STp->rew_at_close) {
4888                result2 = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4889                STps->drv_file = STps->drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
4890                if (result == 0 && result2 < 0)
4891                        result = result2;
4892        }
4893        if (SRpnt) osst_release_request(SRpnt);
4894
4895        if (STp->abort_count || STp->recover_count) {
4896                printk(KERN_INFO "%s:I:", name);
4897                if (STp->abort_count)
4898                        printk(" %d unrecovered errors", STp->abort_count);
4899                if (STp->recover_count)
4900                        printk(" %d recovered errors", STp->recover_count);
4901                if (STp->write_count)
4902                        printk(" in %d frames written", STp->write_count);
4903                if (STp->read_count)
4904                        printk(" in %d frames read", STp->read_count);
4905                printk("\n");
4906                STp->recover_count = 0;
4907                STp->abort_count   = 0;
4908        }
4909        STp->write_count = 0;
4910        STp->read_count  = 0;
4911
4912        return result;
4913}
4914
4915
4916/* Close the device and release it */
4917static int os_scsi_tape_close(struct inode * inode, struct file * filp)
4918{
4919        int                   result = 0;
4920        struct osst_tape    * STp    = filp->private_data;
4921
4922        if (STp->door_locked == ST_LOCKED_AUTO)
4923                do_door_lock(STp, 0);
4924
4925        if (STp->raw)
4926                STp->header_ok = 0;
4927        
4928        normalize_buffer(STp->buffer);
4929        write_lock(&os_scsi_tapes_lock);
4930        STp->in_use = 0;
4931        write_unlock(&os_scsi_tapes_lock);
4932
4933        scsi_device_put(STp->device);
4934
4935        return result;
4936}
4937
4938
4939/* The ioctl command */
4940static long osst_ioctl(struct file * file,
4941         unsigned int cmd_in, unsigned long arg)
4942{
4943        int                   i, cmd_nr, cmd_type, blk, retval = 0;
4944        struct st_modedef   * STm;
4945        struct st_partstat  * STps;
4946        struct osst_request * SRpnt = NULL;
4947        struct osst_tape    * STp   = file->private_data;
4948        char                * name  = tape_name(STp);
4949        void        __user  * p     = (void __user *)arg;
4950
4951        mutex_lock(&osst_int_mutex);
4952        if (mutex_lock_interruptible(&STp->lock)) {
4953                mutex_unlock(&osst_int_mutex);
4954                return -ERESTARTSYS;
4955        }
4956
4957#if DEBUG
4958        if (debugging && !STp->in_use) {
4959                printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
4960                retval = (-EIO);
4961                goto out;
4962        }
4963#endif
4964        STm = &(STp->modes[STp->current_mode]);
4965        STps = &(STp->ps[STp->partition]);
4966
4967        /*
4968         * If we are in the middle of error recovery, don't let anyone
4969         * else try and use this device.  Also, if error recovery fails, it
4970         * may try and take the device offline, in which case all further
4971         * access to the device is prohibited.
4972         */
4973        if( !scsi_block_when_processing_errors(STp->device) ) {
4974                retval = (-ENXIO);
4975                goto out;
4976        }
4977
4978        cmd_type = _IOC_TYPE(cmd_in);
4979        cmd_nr   = _IOC_NR(cmd_in);
4980#if DEBUG
4981        printk(OSST_DEB_MSG "%s:D: Ioctl %d,%d in %s mode\n", name,
4982                            cmd_type, cmd_nr, STp->raw?"raw":"normal");
4983#endif
4984        if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
4985                struct mtop mtc;
4986                int    auto_weof = 0;
4987
4988                if (_IOC_SIZE(cmd_in) != sizeof(mtc)) {
4989                        retval = (-EINVAL);
4990                        goto out;
4991                }
4992
4993                i = copy_from_user((char *) &mtc, p, sizeof(struct mtop));
4994                if (i) {
4995                        retval = (-EFAULT);
4996                        goto out;
4997                }
4998
4999                if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
5000                        printk(KERN_WARNING "%s:W: MTSETDRVBUFFER only allowed for root.\n", name);
5001                        retval = (-EPERM);
5002                        goto out;
5003                }
5004
5005                if (!STm->defined && (mtc.mt_op != MTSETDRVBUFFER && (mtc.mt_count & MT_ST_OPTIONS) == 0)) {
5006                        retval = (-ENXIO);
5007                        goto out;
5008                }
5009
5010                if (!STp->pos_unknown) {
5011
5012                        if (STps->eof == ST_FM_HIT) {
5013                                if (mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM|| mtc.mt_op == MTEOM) {
5014                                        mtc.mt_count -= 1;
5015                                        if (STps->drv_file >= 0)
5016                                                STps->drv_file += 1;
5017                                }
5018                                else if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM) {
5019                                        mtc.mt_count += 1;
5020                                        if (STps->drv_file >= 0)
5021                                                STps->drv_file += 1;
5022                                }
5023                        }
5024
5025                        if (mtc.mt_op == MTSEEK) {
5026                                /* Old position must be restored if partition will be changed */
5027                                i = !STp->can_partitions || (STp->new_partition != STp->partition);
5028                        }
5029                        else {
5030                                i = mtc.mt_op == MTREW   || mtc.mt_op == MTOFFL ||
5031                                    mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM  ||
5032                                    mtc.mt_op == MTLOCK  || mtc.mt_op == MTLOAD ||
5033                                    mtc.mt_op == MTFSF   || mtc.mt_op == MTFSFM ||
5034                                    mtc.mt_op == MTBSF   || mtc.mt_op == MTBSFM ||
5035                                    mtc.mt_op == MTCOMPRESSION;
5036                        }
5037                        i = osst_flush_buffer(STp, &SRpnt, i);
5038                        if (i < 0) {
5039                                retval = i;
5040                                goto out;
5041                        }
5042                }
5043                else {
5044                        /*
5045                         * If there was a bus reset, block further access
5046                         * to this device.  If the user wants to rewind the tape,
5047                         * then reset the flag and allow access again.
5048                         */
5049                        if(mtc.mt_op != MTREW   &&
5050                           mtc.mt_op != MTOFFL  &&
5051                           mtc.mt_op != MTRETEN &&
5052                           mtc.mt_op != MTERASE &&
5053                           mtc.mt_op != MTSEEK  &&
5054                           mtc.mt_op != MTEOM)   {
5055                                retval = (-EIO);
5056                                goto out;
5057                        }
5058                        reset_state(STp);
5059                        /* remove this when the midlevel properly clears was_reset */
5060                        STp->device->was_reset = 0;
5061                }
5062
5063                if (mtc.mt_op != MTCOMPRESSION  && mtc.mt_op != MTLOCK         &&
5064                    mtc.mt_op != MTNOP          && mtc.mt_op != MTSETBLK       &&
5065                    mtc.mt_op != MTSETDENSITY   && mtc.mt_op != MTSETDRVBUFFER && 
5066                    mtc.mt_op != MTMKPART       && mtc.mt_op != MTSETPART      &&
5067                    mtc.mt_op != MTWEOF         && mtc.mt_op != MTWSM           ) {
5068
5069                        /*
5070                         * The user tells us to move to another position on the tape.
5071                         * If we were appending to the tape content, that would leave
5072                         * the tape without proper end, in that case write EOD and
5073                         * update the header to reflect its position.
5074                         */
5075#if DEBUG
5076                        printk(KERN_WARNING "%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name,
5077                                        STps->rw >= ST_WRITING ? "write" : STps->rw == ST_READING ? "read" : "idle",
5078                                        STp->first_frame_position, STp->eod_frame_ppos, STp->frame_seq_number,
5079                                        STp->logical_blk_num, STps->drv_file, STps->drv_block );
5080#endif
5081                        if (STps->rw >= ST_WRITING && STp->first_frame_position >= STp->eod_frame_ppos) {
5082                                auto_weof = ((STp->write_type != OS_WRITE_NEW_MARK) &&
5083                                                        !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
5084                                i = osst_write_trailer(STp, &SRpnt,
5085                                                        !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
5086#if DEBUG
5087                                printk(KERN_WARNING "%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
5088                                                name, auto_weof, STp->first_frame_position, STp->eod_frame_ppos,
5089                                                STp->frame_seq_number, STp->logical_blk_num, STps->drv_file, STps->drv_block );
5090#endif
5091                                if (i < 0) {
5092                                        retval = i;
5093                                        goto out;
5094                                }
5095                        }
5096                        STps->rw = ST_IDLE;
5097                }
5098
5099                if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
5100                        do_door_lock(STp, 0);  /* Ignore result! */
5101
5102                if (mtc.mt_op == MTSETDRVBUFFER &&
5103                   (mtc.mt_count & MT_ST_OPTIONS) != 0) {
5104                        retval = osst_set_options(STp, mtc.mt_count);
5105                        goto out;
5106                }
5107
5108                if (mtc.mt_op == MTSETPART) {
5109                        if (mtc.mt_count >= STp->nbr_partitions)
5110                                retval = -EINVAL;
5111                        else {
5112                                STp->new_partition = mtc.mt_count;
5113                                retval = 0;
5114                        }
5115                        goto out;
5116                }
5117
5118                if (mtc.mt_op == MTMKPART) {
5119                        if (!STp->can_partitions) {
5120                                retval = (-EINVAL);
5121                                goto out;
5122                        }
5123                        if ((i = osst_int_ioctl(STp, &SRpnt, MTREW, 0)) < 0 /*||
5124                            (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
5125                                retval = i;
5126                                goto out;
5127                        }
5128                        for (i=0; i < ST_NBR_PARTITIONS; i++) {
5129                                STp->ps[i].rw = ST_IDLE;
5130                                STp->ps[i].at_sm = 0;
5131                                STp->ps[i].last_block_valid = 0;
5132                        }
5133                        STp->partition = STp->new_partition = 0;
5134                        STp->nbr_partitions = 1;  /* Bad guess ?-) */
5135                        STps->drv_block = STps->drv_file = 0;
5136                        retval = 0;
5137                        goto out;
5138                }
5139
5140                if (mtc.mt_op == MTSEEK) {
5141                        if (STp->raw)
5142                                i = osst_set_frame_position(STp, &SRpnt, mtc.mt_count, 0);
5143                        else
5144                                i = osst_seek_sector(STp, &SRpnt, mtc.mt_count);
5145                        if (!STp->can_partitions)
5146                                STp->ps[0].rw = ST_IDLE;
5147                        retval = i;
5148                        goto out;
5149                }
5150 
5151                if (mtc.mt_op == MTLOCK || mtc.mt_op == MTUNLOCK) {
5152                        retval = do_door_lock(STp, (mtc.mt_op == MTLOCK));
5153                        goto out;
5154                }
5155
5156                if (auto_weof)
5157                        cross_eof(STp, &SRpnt, 0);
5158
5159                if (mtc.mt_op == MTCOMPRESSION)
5160                        retval = -EINVAL;       /* OnStream drives don't have compression hardware */
5161                else
5162                        /* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS
5163                         * MTLOAD MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTWEOF MTWSM */
5164                        retval = osst_int_ioctl(STp, &SRpnt, mtc.mt_op, mtc.mt_count);
5165                goto out;
5166        }
5167
5168        if (!STm->defined) {
5169                retval = (-ENXIO);
5170                goto out;
5171        }
5172
5173        if ((i = osst_flush_buffer(STp, &SRpnt, 0)) < 0) {
5174                retval = i;
5175                goto out;
5176        }
5177
5178        if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
5179                struct mtget mt_status;
5180
5181                if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) {
5182                         retval = (-EINVAL);
5183                         goto out;
5184                }
5185
5186                mt_status.mt_type = MT_ISONSTREAM_SC;
5187                mt_status.mt_erreg = STp->recover_erreg << MT_ST_SOFTERR_SHIFT;
5188                mt_status.mt_dsreg =
5189                        ((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
5190                        ((STp->density    << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
5191                mt_status.mt_blkno = STps->drv_block;
5192                mt_status.mt_fileno = STps->drv_file;
5193                if (STp->block_size != 0) {
5194                        if (STps->rw == ST_WRITING)
5195                                mt_status.mt_blkno += (STp->buffer)->buffer_bytes / STp->block_size;
5196                        else if (STps->rw == ST_READING)
5197                                mt_status.mt_blkno -= ((STp->buffer)->buffer_bytes +
5198                                                        STp->block_size - 1) / STp->block_size;
5199                }
5200
5201                mt_status.mt_gstat = 0;
5202                if (STp->drv_write_prot)
5203                        mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
5204                if (mt_status.mt_blkno == 0) {
5205                        if (mt_status.mt_fileno == 0)
5206                                mt_status.mt_gstat |= GMT_BOT(0xffffffff);
5207                        else
5208                                mt_status.mt_gstat |= GMT_EOF(0xffffffff);
5209                }
5210                mt_status.mt_resid = STp->partition;
5211                if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
5212                        mt_status.mt_gstat |= GMT_EOT(0xffffffff);
5213                else if (STps->eof >= ST_EOM_OK)
5214                        mt_status.mt_gstat |= GMT_EOD(0xffffffff);
5215                if (STp->density == 1)
5216                        mt_status.mt_gstat |= GMT_D_800(0xffffffff);
5217                else if (STp->density == 2)
5218                        mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
5219                else if (STp->density == 3)
5220                        mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
5221                if (STp->ready == ST_READY)
5222                        mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
5223                if (STp->ready == ST_NO_TAPE)
5224                        mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
5225                if (STps->at_sm)
5226                        mt_status.mt_gstat |= GMT_SM(0xffffffff);
5227                if (STm->do_async_writes || (STm->do_buffer_writes && STp->block_size != 0) ||
5228                    STp->drv_buffer != 0)
5229                        mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
5230
5231                i = copy_to_user(p, &mt_status, sizeof(struct mtget));
5232                if (i) {
5233                        retval = (-EFAULT);
5234                        goto out;
5235                }
5236
5237                STp->recover_erreg = 0;  /* Clear after read */
5238                retval = 0;
5239                goto out;
5240        } /* End of MTIOCGET */
5241
5242        if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
5243                struct mtpos mt_pos;
5244
5245                if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) {
5246                        retval = (-EINVAL);
5247                        goto out;
5248                }
5249                if (STp->raw)
5250                        blk = osst_get_frame_position(STp, &SRpnt);
5251                else
5252                        blk = osst_get_sector(STp, &SRpnt);
5253                if (blk < 0) {
5254                        retval = blk;
5255                        goto out;
5256                }
5257                mt_pos.mt_blkno = blk;
5258                i = copy_to_user(p, &mt_pos, sizeof(struct mtpos));
5259                if (i)
5260                        retval = -EFAULT;
5261                goto out;
5262        }
5263        if (SRpnt) osst_release_request(SRpnt);
5264
5265        mutex_unlock(&STp->lock);
5266
5267        retval = scsi_ioctl(STp->device, cmd_in, p);
5268        mutex_unlock(&osst_int_mutex);
5269        return retval;
5270
5271out:
5272        if (SRpnt) osst_release_request(SRpnt);
5273
5274        mutex_unlock(&STp->lock);
5275        mutex_unlock(&osst_int_mutex);
5276
5277        return retval;
5278}
5279
5280#ifdef CONFIG_COMPAT
5281static long osst_compat_ioctl(struct file * file, unsigned int cmd_in, unsigned long arg)
5282{
5283        struct osst_tape *STp = file->private_data;
5284        struct scsi_device *sdev = STp->device;
5285        int ret = -ENOIOCTLCMD;
5286        if (sdev->host->hostt->compat_ioctl) {
5287
5288                ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
5289
5290        }
5291        return ret;
5292}
5293#endif
5294
5295
5296
5297/* Memory handling routines */
5298
5299/* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5300static struct osst_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
5301{
5302        int i;
5303        gfp_t priority;
5304        struct osst_buffer *tb;
5305
5306        if (from_initialization)
5307                priority = GFP_ATOMIC;
5308        else
5309                priority = GFP_KERNEL;
5310
5311        i = sizeof(struct osst_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
5312        tb = kzalloc(i, priority);
5313        if (!tb) {
5314                printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
5315                return NULL;
5316        }
5317
5318        tb->sg_segs = tb->orig_sg_segs = 0;
5319        tb->use_sg = max_sg;
5320        tb->in_use = 1;
5321        tb->dma = need_dma;
5322        tb->buffer_size = 0;
5323#if DEBUG
5324        if (debugging) 
5325                printk(OSST_DEB_MSG
5326                        "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5327                           i, max_sg, need_dma);
5328#endif
5329        return tb;
5330}
5331
5332/* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5333static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
5334{
5335        int segs, nbr, max_segs, b_size, order, got;
5336        gfp_t priority;
5337
5338        if (STbuffer->buffer_size >= OS_FRAME_SIZE)
5339                return 1;
5340
5341        if (STbuffer->sg_segs) {
5342                printk(KERN_WARNING "osst :A: Buffer not previously normalized.\n");
5343                normalize_buffer(STbuffer);
5344        }
5345        /* See how many segments we can use -- need at least two */
5346        nbr = max_segs = STbuffer->use_sg;
5347        if (nbr <= 2)
5348                return 0;
5349
5350        priority = GFP_KERNEL /* | __GFP_NOWARN */;
5351        if (need_dma)
5352                priority |= GFP_DMA;
5353
5354        /* Try to allocate the first segment up to OS_DATA_SIZE and the others
5355           big enough to reach the goal (code assumes no segments in place) */
5356        for (b_size = OS_DATA_SIZE, order = OSST_FIRST_ORDER; b_size >= PAGE_SIZE; order--, b_size /= 2) {
5357                struct page *page = alloc_pages(priority, order);
5358
5359                STbuffer->sg[0].offset = 0;
5360                if (page != NULL) {
5361                    sg_set_page(&STbuffer->sg[0], page, b_size, 0);
5362                    STbuffer->b_data = page_address(page);
5363                    break;
5364                }
5365        }
5366        if (sg_page(&STbuffer->sg[0]) == NULL) {
5367                printk(KERN_NOTICE "osst :I: Can't allocate tape buffer main segment.\n");
5368                return 0;
5369        }
5370        /* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5371        for (segs=STbuffer->sg_segs=1, got=b_size;
5372             segs < max_segs && got < OS_FRAME_SIZE; ) {
5373                struct page *page = alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order);
5374                STbuffer->sg[segs].offset = 0;
5375                if (page == NULL) {
5376                        printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n",
5377                                                OS_FRAME_SIZE);
5378#if DEBUG
5379                        STbuffer->buffer_size = got;
5380#endif
5381                        normalize_buffer(STbuffer);
5382                        return 0;
5383                }
5384                sg_set_page(&STbuffer->sg[segs], page, (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size, 0);
5385                got += STbuffer->sg[segs].length;
5386                STbuffer->buffer_size = got;
5387                STbuffer->sg_segs = ++segs;
5388        }
5389#if DEBUG
5390        if (debugging) {
5391                printk(OSST_DEB_MSG
5392                           "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5393                           got, STbuffer->orig_sg_segs, STbuffer->sg_segs, need_dma, STbuffer->b_data);
5394                printk(OSST_DEB_MSG
5395                           "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5396                           STbuffer->sg[0].length, page_address(STbuffer->sg[0].page),
5397                           STbuffer->sg[segs-1].length, page_address(STbuffer->sg[segs-1].page));
5398        }
5399#endif
5400
5401        return 1;
5402}
5403
5404
5405/* Release the segments */
5406static void normalize_buffer(struct osst_buffer *STbuffer)
5407{
5408  int i, order, b_size;
5409
5410        for (i=0; i < STbuffer->sg_segs; i++) {
5411
5412                for (b_size = PAGE_SIZE, order = 0;
5413                     b_size < STbuffer->sg[i].length;
5414                     b_size *= 2, order++);
5415
5416                __free_pages(sg_page(&STbuffer->sg[i]), order);
5417                STbuffer->buffer_size -= STbuffer->sg[i].length;
5418        }
5419#if DEBUG
5420        if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
5421                printk(OSST_DEB_MSG "osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5422                             STbuffer->b_data, STbuffer->buffer_size, STbuffer->sg_segs);
5423#endif
5424        STbuffer->sg_segs = STbuffer->orig_sg_segs = 0;
5425}
5426
5427
5428/* Move data from the user buffer to the tape buffer. Returns zero (success) or
5429   negative error code. */
5430static int append_to_buffer(const char __user *ubp, struct osst_buffer *st_bp, int do_count)
5431{
5432        int i, cnt, res, offset;
5433
5434        for (i=0, offset=st_bp->buffer_bytes;
5435             i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5436        offset -= st_bp->sg[i].length;
5437        if (i == st_bp->sg_segs) {  /* Should never happen */
5438                printk(KERN_WARNING "osst :A: Append_to_buffer offset overflow.\n");
5439                return (-EIO);
5440        }
5441        for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5442                cnt = st_bp->sg[i].length - offset < do_count ?
5443                      st_bp->sg[i].length - offset : do_count;
5444                res = copy_from_user(page_address(sg_page(&st_bp->sg[i])) + offset, ubp, cnt);
5445                if (res)
5446                        return (-EFAULT);
5447                do_count -= cnt;
5448                st_bp->buffer_bytes += cnt;
5449                ubp += cnt;
5450                offset = 0;
5451        }
5452        if (do_count) {  /* Should never happen */
5453                printk(KERN_WARNING "osst :A: Append_to_buffer overflow (left %d).\n",
5454                       do_count);
5455                return (-EIO);
5456        }
5457        return 0;
5458}
5459
5460
5461/* Move data from the tape buffer to the user buffer. Returns zero (success) or
5462   negative error code. */
5463static int from_buffer(struct osst_buffer *st_bp, char __user *ubp, int do_count)
5464{
5465        int i, cnt, res, offset;
5466
5467        for (i=0, offset=st_bp->read_pointer;
5468             i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5469                offset -= st_bp->sg[i].length;
5470        if (i == st_bp->sg_segs) {  /* Should never happen */
5471                printk(KERN_WARNING "osst :A: From_buffer offset overflow.\n");
5472                return (-EIO);
5473        }
5474        for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5475                cnt = st_bp->sg[i].length - offset < do_count ?
5476                      st_bp->sg[i].length - offset : do_count;
5477                res = copy_to_user(ubp, page_address(sg_page(&st_bp->sg[i])) + offset, cnt);
5478                if (res)
5479                        return (-EFAULT);
5480                do_count -= cnt;
5481                st_bp->buffer_bytes -= cnt;
5482                st_bp->read_pointer += cnt;
5483                ubp += cnt;
5484                offset = 0;
5485        }
5486        if (do_count) {  /* Should never happen */
5487                printk(KERN_WARNING "osst :A: From_buffer overflow (left %d).\n", do_count);
5488                return (-EIO);
5489        }
5490        return 0;
5491}
5492
5493/* Sets the tail of the buffer after fill point to zero.
5494   Returns zero (success) or negative error code.        */
5495static int osst_zero_buffer_tail(struct osst_buffer *st_bp)
5496{
5497        int     i, offset, do_count, cnt;
5498
5499        for (i = 0, offset = st_bp->buffer_bytes;
5500             i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5501                offset -= st_bp->sg[i].length;
5502        if (i == st_bp->sg_segs) {  /* Should never happen */
5503                printk(KERN_WARNING "osst :A: Zero_buffer offset overflow.\n");
5504                return (-EIO);
5505        }
5506        for (do_count = OS_DATA_SIZE - st_bp->buffer_bytes;
5507             i < st_bp->sg_segs && do_count > 0; i++) {
5508                cnt = st_bp->sg[i].length - offset < do_count ?
5509                      st_bp->sg[i].length - offset : do_count ;
5510                memset(page_address(sg_page(&st_bp->sg[i])) + offset, 0, cnt);
5511                do_count -= cnt;
5512                offset = 0;
5513        }
5514        if (do_count) {  /* Should never happen */
5515                printk(KERN_WARNING "osst :A: Zero_buffer overflow (left %d).\n", do_count);
5516                return (-EIO);
5517        }
5518        return 0;
5519}
5520
5521/* Copy a osst 32K chunk of memory into the buffer.
5522   Returns zero (success) or negative error code.  */
5523static int osst_copy_to_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5524{
5525        int     i, cnt, do_count = OS_DATA_SIZE;
5526
5527        for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5528                cnt = st_bp->sg[i].length < do_count ?
5529                      st_bp->sg[i].length : do_count ;
5530                memcpy(page_address(sg_page(&st_bp->sg[i])), ptr, cnt);
5531                do_count -= cnt;
5532                ptr      += cnt;
5533        }
5534        if (do_count || i != st_bp->sg_segs-1) {  /* Should never happen */
5535                printk(KERN_WARNING "osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5536                                         do_count, i);
5537                return (-EIO);
5538        }
5539        return 0;
5540}
5541
5542/* Copy a osst 32K chunk of memory from the buffer.
5543   Returns zero (success) or negative error code.  */
5544static int osst_copy_from_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5545{
5546        int     i, cnt, do_count = OS_DATA_SIZE;
5547
5548        for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5549                cnt = st_bp->sg[i].length < do_count ?
5550                      st_bp->sg[i].length : do_count ;
5551                memcpy(ptr, page_address(sg_page(&st_bp->sg[i])), cnt);
5552                do_count -= cnt;
5553                ptr      += cnt;
5554        }
5555        if (do_count || i != st_bp->sg_segs-1) {  /* Should never happen */
5556                printk(KERN_WARNING "osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5557                                         do_count, i);
5558                return (-EIO);
5559        }
5560        return 0;
5561}
5562
5563
5564/* Module housekeeping */
5565
5566static void validate_options (void)
5567{
5568  if (max_dev > 0)
5569                osst_max_dev = max_dev;  
5570  if (write_threshold_kbs > 0)
5571                osst_write_threshold = write_threshold_kbs * ST_KILOBYTE;
5572  if (osst_write_threshold > osst_buffer_size)
5573                osst_write_threshold = osst_buffer_size;
5574  if (max_sg_segs >= OSST_FIRST_SG)
5575                osst_max_sg_segs = max_sg_segs;
5576#if DEBUG
5577  printk(OSST_DEB_MSG "osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5578                           osst_max_dev, osst_write_threshold, osst_max_sg_segs);
5579#endif
5580}
5581        
5582#ifndef MODULE
5583/* Set the boot options. Syntax: osst=xxx,yyy,...
5584   where xxx is write threshold in 1024 byte blocks,
5585   and   yyy is number of s/g segments to use. */
5586static int __init osst_setup (char *str)
5587{
5588  int i, ints[5];
5589  char *stp;
5590
5591  stp = get_options(str, ARRAY_SIZE(ints), ints);
5592
5593  if (ints[0] > 0) {
5594        for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
5595                  *parms[i].val = ints[i + 1];
5596  } else {
5597        while (stp != NULL) {
5598                for (i = 0; i < ARRAY_SIZE(parms); i++) {
5599                        int len = strlen(parms[i].name);
5600                        if (!strncmp(stp, parms[i].name, len) &&
5601                            (*(stp + len) == ':' || *(stp + len) == '=')) {
5602                                *parms[i].val =
5603                                        simple_strtoul(stp + len + 1, NULL, 0);
5604                                break;
5605                        }
5606                }
5607                if (i >= ARRAY_SIZE(parms))
5608                        printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n",
5609                               stp);
5610                stp = strchr(stp, ',');
5611                if (stp)
5612                        stp++;
5613        }
5614  }
5615
5616  return 1;
5617}
5618
5619__setup("osst=", osst_setup);
5620
5621#endif
5622
5623static const struct file_operations osst_fops = {
5624        .owner =        THIS_MODULE,
5625        .read =         osst_read,
5626        .write =        osst_write,
5627        .unlocked_ioctl = osst_ioctl,
5628#ifdef CONFIG_COMPAT
5629        .compat_ioctl = osst_compat_ioctl,
5630#endif
5631        .open =         os_scsi_tape_open,
5632        .flush =        os_scsi_tape_flush,
5633        .release =      os_scsi_tape_close,
5634        .llseek =       noop_llseek,
5635};
5636
5637static int osst_supports(struct scsi_device * SDp)
5638{
5639        struct  osst_support_data {
5640                char *vendor;
5641                char *model;
5642                char *rev;
5643                char *driver_hint; /* Name of the correct driver, NULL if unknown */
5644        };
5645
5646static  struct  osst_support_data support_list[] = {
5647                /* {"XXX", "Yy-", "", NULL},  example */
5648                SIGS_FROM_OSST,
5649                {NULL, }};
5650
5651        struct  osst_support_data *rp;
5652
5653        /* We are willing to drive OnStream SC-x0 as well as the
5654         *       * IDE, ParPort, FireWire, USB variants, if accessible by
5655         *               * emulation layer (ide-scsi, usb-storage, ...) */
5656
5657        for (rp=&(support_list[0]); rp->vendor != NULL; rp++)
5658                if (!strncmp(rp->vendor, SDp->vendor, strlen(rp->vendor)) &&
5659                    !strncmp(rp->model, SDp->model, strlen(rp->model)) &&
5660                    !strncmp(rp->rev, SDp->rev, strlen(rp->rev))) 
5661                        return 1;
5662        return 0;
5663}
5664
5665/*
5666 * sysfs support for osst driver parameter information
5667 */
5668
5669static ssize_t osst_version_show(struct device_driver *ddd, char *buf)
5670{
5671        return snprintf(buf, PAGE_SIZE, "%s\n", osst_version);
5672}
5673
5674static DRIVER_ATTR(version, S_IRUGO, osst_version_show, NULL);
5675
5676static int osst_create_sysfs_files(struct device_driver *sysfs)
5677{
5678        return driver_create_file(sysfs, &driver_attr_version);
5679}
5680
5681static void osst_remove_sysfs_files(struct device_driver *sysfs)
5682{
5683        driver_remove_file(sysfs, &driver_attr_version);
5684}
5685
5686/*
5687 * sysfs support for accessing ADR header information
5688 */
5689
5690static ssize_t osst_adr_rev_show(struct device *dev,
5691                                 struct device_attribute *attr, char *buf)
5692{
5693        struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5694        ssize_t l = 0;
5695
5696        if (STp && STp->header_ok && STp->linux_media)
5697                l = snprintf(buf, PAGE_SIZE, "%d.%d\n", STp->header_cache->major_rev, STp->header_cache->minor_rev);
5698        return l;
5699}
5700
5701DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
5702
5703static ssize_t osst_linux_media_version_show(struct device *dev,
5704                                             struct device_attribute *attr,
5705                                             char *buf)
5706{
5707        struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5708        ssize_t l = 0;
5709
5710        if (STp && STp->header_ok && STp->linux_media)
5711                l = snprintf(buf, PAGE_SIZE, "LIN%d\n", STp->linux_media_version);
5712        return l;
5713}
5714
5715DEVICE_ATTR(media_version, S_IRUGO, osst_linux_media_version_show, NULL);
5716
5717static ssize_t osst_capacity_show(struct device *dev,
5718                                  struct device_attribute *attr, char *buf)
5719{
5720        struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5721        ssize_t l = 0;
5722
5723        if (STp && STp->header_ok && STp->linux_media)
5724                l = snprintf(buf, PAGE_SIZE, "%d\n", STp->capacity);
5725        return l;
5726}
5727
5728DEVICE_ATTR(capacity, S_IRUGO, osst_capacity_show, NULL);
5729
5730static ssize_t osst_first_data_ppos_show(struct device *dev,
5731                                         struct device_attribute *attr,
5732                                         char *buf)
5733{
5734        struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5735        ssize_t l = 0;
5736
5737        if (STp && STp->header_ok && STp->linux_media)
5738                l = snprintf(buf, PAGE_SIZE, "%d\n", STp->first_data_ppos);
5739        return l;
5740}
5741
5742DEVICE_ATTR(BOT_frame, S_IRUGO, osst_first_data_ppos_show, NULL);
5743
5744static ssize_t osst_eod_frame_ppos_show(struct device *dev,
5745                                        struct device_attribute *attr,
5746                                        char *buf)
5747{
5748        struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5749        ssize_t l = 0;
5750
5751        if (STp && STp->header_ok && STp->linux_media)
5752                l = snprintf(buf, PAGE_SIZE, "%d\n", STp->eod_frame_ppos);
5753        return l;
5754}
5755
5756DEVICE_ATTR(EOD_frame, S_IRUGO, osst_eod_frame_ppos_show, NULL);
5757
5758static ssize_t osst_filemark_cnt_show(struct device *dev,
5759                                      struct device_attribute *attr, char *buf)
5760{
5761        struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5762        ssize_t l = 0;
5763
5764        if (STp && STp->header_ok && STp->linux_media)
5765                l = snprintf(buf, PAGE_SIZE, "%d\n", STp->filemark_cnt);
5766        return l;
5767}
5768
5769DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
5770
5771static struct class *osst_sysfs_class;
5772
5773static int osst_sysfs_init(void)
5774{
5775        osst_sysfs_class = class_create(THIS_MODULE, "onstream_tape");
5776        if (IS_ERR(osst_sysfs_class)) {
5777                printk(KERN_ERR "osst :W: Unable to register sysfs class\n");
5778                return PTR_ERR(osst_sysfs_class);
5779        }
5780
5781        return 0;
5782}
5783
5784static void osst_sysfs_destroy(dev_t dev)
5785{
5786        device_destroy(osst_sysfs_class, dev);
5787}
5788
5789static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * STp, char * name)
5790{
5791        struct device *osst_member;
5792        int err;
5793
5794        osst_member = device_create(osst_sysfs_class, device, dev, STp,
5795                                    "%s", name);
5796        if (IS_ERR(osst_member)) {
5797                printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
5798                return PTR_ERR(osst_member);
5799        }
5800
5801        err = device_create_file(osst_member, &dev_attr_ADR_rev);
5802        if (err)
5803                goto err_out;
5804        err = device_create_file(osst_member, &dev_attr_media_version);
5805        if (err)
5806                goto err_out;
5807        err = device_create_file(osst_member, &dev_attr_capacity);
5808        if (err)
5809                goto err_out;
5810        err = device_create_file(osst_member, &dev_attr_BOT_frame);
5811        if (err)
5812                goto err_out;
5813        err = device_create_file(osst_member, &dev_attr_EOD_frame);
5814        if (err)
5815                goto err_out;
5816        err = device_create_file(osst_member, &dev_attr_file_count);
5817        if (err)
5818                goto err_out;
5819
5820        return 0;
5821
5822err_out:
5823        osst_sysfs_destroy(dev);
5824        return err;
5825}
5826
5827static void osst_sysfs_cleanup(void)
5828{
5829        class_destroy(osst_sysfs_class);
5830}
5831
5832/*
5833 * osst startup / cleanup code
5834 */
5835
5836static int osst_probe(struct device *dev)
5837{
5838        struct scsi_device * SDp = to_scsi_device(dev);
5839        struct osst_tape   * tpnt;
5840        struct st_modedef  * STm;
5841        struct st_partstat * STps;
5842        struct osst_buffer * buffer;
5843        struct gendisk     * drive;
5844        int                  i, dev_num, err = -ENODEV;
5845
5846        if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
5847                return -ENODEV;
5848
5849        drive = alloc_disk(1);
5850        if (!drive) {
5851                printk(KERN_ERR "osst :E: Out of memory. Device not attached.\n");
5852                return -ENODEV;
5853        }
5854
5855        /* if this is the first attach, build the infrastructure */
5856        write_lock(&os_scsi_tapes_lock);
5857        if (os_scsi_tapes == NULL) {
5858                os_scsi_tapes = kmalloc(osst_max_dev * sizeof(struct osst_tape *), GFP_ATOMIC);
5859                if (os_scsi_tapes == NULL) {
5860                        write_unlock(&os_scsi_tapes_lock);
5861                        printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5862                        goto out_put_disk;
5863                }
5864                for (i=0; i < osst_max_dev; ++i) os_scsi_tapes[i] = NULL;
5865        }
5866        
5867        if (osst_nr_dev >= osst_max_dev) {
5868                write_unlock(&os_scsi_tapes_lock);
5869                printk(KERN_ERR "osst :E: Too many tape devices (max. %d).\n", osst_max_dev);
5870                goto out_put_disk;
5871        }
5872
5873        /* find a free minor number */
5874        for (i = 0; i < osst_max_dev && os_scsi_tapes[i]; i++)
5875                ;
5876        if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)");
5877        dev_num = i;
5878
5879        /* allocate a struct osst_tape for this device */
5880        tpnt = kzalloc(sizeof(struct osst_tape), GFP_ATOMIC);
5881        if (!tpnt) {
5882                write_unlock(&os_scsi_tapes_lock);
5883                printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
5884                goto out_put_disk;
5885        }
5886
5887        /* allocate a buffer for this device */
5888        i = SDp->host->sg_tablesize;
5889        if (osst_max_sg_segs < i)
5890                i = osst_max_sg_segs;
5891        buffer = new_tape_buffer(1, SDp->host->unchecked_isa_dma, i);
5892        if (buffer == NULL) {
5893                write_unlock(&os_scsi_tapes_lock);
5894                printk(KERN_ERR "osst :E: Unable to allocate a tape buffer, device not attached.\n");
5895                kfree(tpnt);
5896                goto out_put_disk;
5897        }
5898        os_scsi_tapes[dev_num] = tpnt;
5899        tpnt->buffer = buffer;
5900        tpnt->device = SDp;
5901        drive->private_data = &tpnt->driver;
5902        sprintf(drive->disk_name, "osst%d", dev_num);
5903        tpnt->driver = &osst_template;
5904        tpnt->drive = drive;
5905        tpnt->in_use = 0;
5906        tpnt->capacity = 0xfffff;
5907        tpnt->dirty = 0;
5908        tpnt->drv_buffer = 1;  /* Try buffering if no mode sense */
5909        tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
5910        tpnt->density = 0;
5911        tpnt->do_auto_lock = OSST_AUTO_LOCK;
5912        tpnt->can_bsr = OSST_IN_FILE_POS;
5913        tpnt->can_partitions = 0;
5914        tpnt->two_fm = OSST_TWO_FM;
5915        tpnt->fast_mteom = OSST_FAST_MTEOM;
5916        tpnt->scsi2_logical = OSST_SCSI2LOGICAL; /* FIXME */
5917        tpnt->write_threshold = osst_write_threshold;
5918        tpnt->default_drvbuffer = 0xff; /* No forced buffering */
5919        tpnt->partition = 0;
5920        tpnt->new_partition = 0;
5921        tpnt->nbr_partitions = 0;
5922        tpnt->min_block = 512;
5923        tpnt->max_block = OS_DATA_SIZE;
5924        tpnt->timeout = OSST_TIMEOUT;
5925        tpnt->long_timeout = OSST_LONG_TIMEOUT;
5926
5927        /* Recognize OnStream tapes */
5928        /* We don't need to test for OnStream, as this has been done in detect () */
5929        tpnt->os_fw_rev = osst_parse_firmware_rev (SDp->rev);
5930        tpnt->omit_blklims = 1;
5931
5932        tpnt->poll = (strncmp(SDp->model, "DI-", 3) == 0) || 
5933                     (strncmp(SDp->model, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt->os_fw_rev,SDp);
5934        tpnt->frame_in_buffer = 0;
5935        tpnt->header_ok = 0;
5936        tpnt->linux_media = 0;
5937        tpnt->header_cache = NULL;
5938
5939        for (i=0; i < ST_NBR_MODES; i++) {
5940                STm = &(tpnt->modes[i]);
5941                STm->defined = 0;
5942                STm->sysv = OSST_SYSV;
5943                STm->defaults_for_writes = 0;
5944                STm->do_async_writes = OSST_ASYNC_WRITES;
5945                STm->do_buffer_writes = OSST_BUFFER_WRITES;
5946                STm->do_read_ahead = OSST_READ_AHEAD;
5947                STm->default_compression = ST_DONT_TOUCH;
5948                STm->default_blksize = 512;
5949                STm->default_density = (-1);  /* No forced density */
5950        }
5951
5952        for (i=0; i < ST_NBR_PARTITIONS; i++) {
5953                STps = &(tpnt->ps[i]);
5954                STps->rw = ST_IDLE;
5955                STps->eof = ST_NOEOF;
5956                STps->at_sm = 0;
5957                STps->last_block_valid = 0;
5958                STps->drv_block = (-1);
5959                STps->drv_file = (-1);
5960        }
5961
5962        tpnt->current_mode = 0;
5963        tpnt->modes[0].defined = 1;
5964        tpnt->modes[2].defined = 1;
5965        tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = 0;
5966
5967        mutex_init(&tpnt->lock);
5968        osst_nr_dev++;
5969        write_unlock(&os_scsi_tapes_lock);
5970
5971        {
5972                char name[8];
5973
5974                /*  Rewind entry  */
5975                err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num), dev, tpnt, tape_name(tpnt));
5976                if (err)
5977                        goto out_free_buffer;
5978
5979                /*  No-rewind entry  */
5980                snprintf(name, 8, "%s%s", "n", tape_name(tpnt));
5981                err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num + 128), dev, tpnt, name);
5982                if (err)
5983                        goto out_free_sysfs1;
5984        }
5985
5986        sdev_printk(KERN_INFO, SDp,
5987                "osst :I: Attached OnStream %.5s tape as %s\n",
5988                SDp->model, tape_name(tpnt));
5989
5990        return 0;
5991
5992out_free_sysfs1:
5993        osst_sysfs_destroy(MKDEV(OSST_MAJOR, dev_num));
5994out_free_buffer:
5995        kfree(buffer);
5996out_put_disk:
5997        put_disk(drive);
5998        return err;
5999};
6000
6001static int osst_remove(struct device *dev)
6002{
6003        struct scsi_device * SDp = to_scsi_device(dev);
6004        struct osst_tape * tpnt;
6005        int i;
6006
6007        if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
6008                return 0;
6009
6010        write_lock(&os_scsi_tapes_lock);
6011        for(i=0; i < osst_max_dev; i++) {
6012                if((tpnt = os_scsi_tapes[i]) && (tpnt->device == SDp)) {
6013                        osst_sysfs_destroy(MKDEV(OSST_MAJOR, i));
6014                        osst_sysfs_destroy(MKDEV(OSST_MAJOR, i+128));
6015                        tpnt->device = NULL;
6016                        put_disk(tpnt->drive);
6017                        os_scsi_tapes[i] = NULL;
6018                        osst_nr_dev--;
6019                        write_unlock(&os_scsi_tapes_lock);
6020                        vfree(tpnt->header_cache);
6021                        if (tpnt->buffer) {
6022                                normalize_buffer(tpnt->buffer);
6023                                kfree(tpnt->buffer);
6024                        }
6025                        kfree(tpnt);
6026                        return 0;
6027                }
6028        }
6029        write_unlock(&os_scsi_tapes_lock);
6030        return 0;
6031}
6032
6033static int __init init_osst(void) 
6034{
6035        int err;
6036
6037        printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
6038
6039        validate_options();
6040
6041        err = osst_sysfs_init();
6042        if (err)
6043                return err;
6044
6045        err = register_chrdev(OSST_MAJOR, "osst", &osst_fops);
6046        if (err < 0) {
6047                printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
6048                goto err_out;
6049        }
6050
6051        err = scsi_register_driver(&osst_template.gendrv);
6052        if (err)
6053                goto err_out_chrdev;
6054
6055        err = osst_create_sysfs_files(&osst_template.gendrv);
6056        if (err)
6057                goto err_out_scsidrv;
6058
6059        return 0;
6060
6061err_out_scsidrv:
6062        scsi_unregister_driver(&osst_template.gendrv);
6063err_out_chrdev:
6064        unregister_chrdev(OSST_MAJOR, "osst");
6065err_out:
6066        osst_sysfs_cleanup();
6067        return err;
6068}
6069
6070static void __exit exit_osst (void)
6071{
6072        int i;
6073        struct osst_tape * STp;
6074
6075        osst_remove_sysfs_files(&osst_template.gendrv);
6076        scsi_unregister_driver(&osst_template.gendrv);
6077        unregister_chrdev(OSST_MAJOR, "osst");
6078        osst_sysfs_cleanup();
6079
6080        if (os_scsi_tapes) {
6081                for (i=0; i < osst_max_dev; ++i) {
6082                        if (!(STp = os_scsi_tapes[i])) continue;
6083                        /* This is defensive, supposed to happen during detach */
6084                        vfree(STp->header_cache);
6085                        if (STp->buffer) {
6086                                normalize_buffer(STp->buffer);
6087                                kfree(STp->buffer);
6088                        }
6089                        put_disk(STp->drive);
6090                        kfree(STp);
6091                }
6092                kfree(os_scsi_tapes);
6093        }
6094        printk(KERN_INFO "osst :I: Unloaded.\n");
6095}
6096
6097module_init(init_osst);
6098module_exit(exit_osst);
6099