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