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