root/drivers/scsi/st.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. st_chk_result
  2. st_sleep_done
  3. write_behind_check
  4. back_over_eof
  5. flush_write_buffer
  6. flush_buffer
  7. scsi_tape_open
  8. scsi_tape_close
  9. st_write
  10. st_read
  11. st_set_options
  12. st_int_ioctl
  13. st_ioctl
  14. st_setup
  15. st_attach
  16. st_init1
  17. st_init

   1 /*
   2   SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying
   3   file README.st for more information.
   4 
   5   History:
   6   Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
   7   Contribution and ideas from several people including (in alphabetical
   8   order) Klaus Ehrenfried, Wolfgang Denk, J"org Weule, and
   9   Eric Youngdale.
  10 
  11   Copyright 1992, 1993, 1994 Kai Makisara
  12                  email makisara@vtinsx.ins.vtt.fi or Kai.Makisara@vtt.fi
  13 
  14   Last modified: Wed Jun 22 23:37:10 1994 by root@kai.home
  15 */
  16 
  17 #include <linux/fs.h>
  18 #include <linux/kernel.h>
  19 #include <linux/sched.h>
  20 #include <linux/string.h>
  21 #include <linux/errno.h>
  22 #include <linux/mtio.h>
  23 #include <linux/ioctl.h>
  24 #include <linux/fcntl.h>
  25 #include <asm/segment.h>
  26 #include <asm/system.h>
  27 
  28 #define MAJOR_NR SCSI_TAPE_MAJOR
  29 #include "../block/blk.h"
  30 #include "scsi.h"
  31 #include "scsi_ioctl.h"
  32 #include "st.h"
  33 #include "constants.h"
  34 
  35 /* #define DEBUG */
  36 
  37 /* #define ST_NOWAIT */
  38 
  39 /* #define ST_IN_FILE_POS */
  40 
  41 /* #define ST_RECOVERED_WRITE_FATAL */
  42 
  43 #define ST_TWO_FM 0
  44 
  45 #define ST_BUFFER_WRITES 1
  46 
  47 #define ST_ASYNC_WRITES 1
  48 
  49 #define ST_READ_AHEAD 1
  50 
  51 #define ST_BLOCK_SIZE 1024
  52 
  53 #define ST_MAX_BUFFERS 2
  54 
  55 #define ST_BUFFER_BLOCKS 32
  56 
  57 #define ST_WRITE_THRESHOLD_BLOCKS 30
  58 
  59 #define ST_BUFFER_SIZE (ST_BUFFER_BLOCKS * ST_BLOCK_SIZE)
  60 #define ST_WRITE_THRESHOLD (ST_WRITE_THRESHOLD_BLOCKS * ST_BLOCK_SIZE)
  61 
  62 /* The buffer size should fit into the 24 bits for length in the
  63    6-byte SCSI read and write commands. */
  64 #if ST_BUFFER_SIZE >= (2 << 24 - 1)
  65 #error "Buffer size should not exceed (2 << 24 - 1) bytes!"
  66 #endif
  67 
  68 #ifdef DEBUG
  69 static int debugging = 1;
  70 #endif
  71 
  72 #define MAX_RETRIES 0
  73 #define MAX_READY_RETRIES 5
  74 #define NO_TAPE  NOT_READY
  75 
  76 #define ST_TIMEOUT 27000
  77 #define ST_LONG_TIMEOUT 200000
  78 
  79 static int st_nbr_buffers;
  80 static ST_buffer **st_buffers;
  81 static int st_buffer_size = ST_BUFFER_SIZE;
  82 static int st_write_threshold = ST_WRITE_THRESHOLD;
  83 static int st_max_buffers = ST_MAX_BUFFERS;
  84 
  85 static Scsi_Tape * scsi_tapes;
  86 int NR_ST=0;
  87 int MAX_ST=0;
  88 
  89 static int st_int_ioctl(struct inode * inode,struct file * file,
  90              unsigned int cmd_in, unsigned long arg);
  91 
  92 
  93 
  94 
  95 /* Convert the result to success code */
  96         static int
  97 st_chk_result(Scsi_Cmnd * SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
  98 {
  99   int dev = SCpnt->request.dev;
 100   int result = SCpnt->result;
 101   unsigned char * sense = SCpnt->sense_buffer;
 102   char *stp;
 103 
 104   if (!result && SCpnt->sense_buffer[0] == 0)
 105     return 0;
 106 #ifdef DEBUG
 107   if (debugging) {
 108     printk("st%d: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n", dev, result,
 109            SCpnt->cmnd[0], SCpnt->cmnd[1], SCpnt->cmnd[2],
 110            SCpnt->cmnd[3], SCpnt->cmnd[4], SCpnt->cmnd[5],
 111            SCpnt->request_bufflen);
 112     if (driver_byte(result) & DRIVER_SENSE)
 113       print_sense("st", SCpnt);
 114   }
 115 #endif
 116 /*  if ((sense[0] & 0x70) == 0x70 &&
 117        ((sense[2] & 0x80) ))
 118     return 0; */
 119   if ((sense[0] & 0x70) == 0x70 &&
 120       sense[2] == RECOVERED_ERROR
 121 #ifdef ST_RECOVERED_WRITE_FATAL
 122       && SCpnt->cmnd[0] != WRITE_6
 123       && SCpnt->cmnd[0] != WRITE_FILEMARKS
 124 #endif
 125       ) {
 126     scsi_tapes[dev].recover_count++;
 127     scsi_tapes[dev].mt_status->mt_erreg += (1 << MT_ST_SOFTERR_SHIFT);
 128     if (SCpnt->cmnd[0] == READ_6)
 129       stp = "read";
 130     else if (SCpnt->cmnd[0] == WRITE_6)
 131       stp = "write";
 132     else
 133       stp = "ioctl";
 134     printk("st%d: Recovered %s error (%d).\n", dev, stp,
 135            scsi_tapes[dev].recover_count);
 136     return 0;
 137   }
 138   return (-EIO);
 139 }
 140 
 141 
 142 /* Wakeup from interrupt */
 143         static void
 144 st_sleep_done (Scsi_Cmnd * SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
 145 {
 146   int st_nbr, remainder;
 147   Scsi_Tape * STp;
 148 
 149   if ((st_nbr = SCpnt->request.dev) < NR_ST && st_nbr >= 0) {
 150     STp = &(scsi_tapes[st_nbr]);
 151     if ((STp->buffer)->writing &&
 152         (SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
 153         (SCpnt->sense_buffer[2] & 0x40)) {
 154       /* EOM at write-behind, has all been written? */
 155       if ((SCpnt->sense_buffer[0] & 0x80) != 0)
 156         remainder = (SCpnt->sense_buffer[3] << 24) |
 157               (SCpnt->sense_buffer[4] << 16) |
 158                 (SCpnt->sense_buffer[5] << 8) | SCpnt->sense_buffer[6];
 159       else
 160         remainder = 0;
 161       if ((SCpnt->sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW ||
 162           remainder > 0)
 163         (STp->buffer)->last_result = SCpnt->result; /* Error */
 164       else
 165         (STp->buffer)->last_result = INT_MAX; /* OK */
 166     }
 167     else
 168       (STp->buffer)->last_result = SCpnt->result;
 169     (STp->buffer)->last_result_fatal = st_chk_result(SCpnt);
 170     if ((STp->buffer)->writing)
 171       SCpnt->request.dev = -1;
 172     else
 173       SCpnt->request.dev = 0xffff;
 174     if ((STp->buffer)->writing <= 0)
 175       wake_up( &(STp->waiting) );
 176   }
 177 #ifdef DEBUG
 178   else if (debugging)
 179     printk("st?: Illegal interrupt device %x\n", st_nbr);
 180 #endif
 181 }
 182 
 183 
 184 /* Handle the write-behind checking */
 185         static void
 186 write_behind_check(int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 187 {
 188   Scsi_Tape * STp;
 189   ST_buffer * STbuffer;
 190 
 191   STp = &(scsi_tapes[dev]);
 192   STbuffer = STp->buffer;
 193 
 194   cli();
 195   if (STbuffer->last_result < 0) {
 196     STbuffer->writing = (- STbuffer->writing);
 197     sleep_on( &(STp->waiting) );
 198     STbuffer->writing = (- STbuffer->writing);
 199   }
 200   sti();
 201 
 202   if (STbuffer->writing < STbuffer->buffer_bytes)
 203     memcpy(STbuffer->b_data,
 204            STbuffer->b_data + STbuffer->writing,
 205            STbuffer->buffer_bytes - STbuffer->writing);
 206   STbuffer->buffer_bytes -= STbuffer->writing;
 207   if (STp->drv_block >= 0) {
 208     if (STp->block_size == 0)
 209       STp->drv_block++;
 210     else
 211       STp->drv_block += STbuffer->writing / STp->block_size;
 212   }
 213   STbuffer->writing = 0;
 214 
 215   return;
 216 }
 217 
 218 
 219 /* Back over EOF if it has been inadvertently crossed (ioctl not used because
 220    it messes up the block number). */
 221         static int
 222 back_over_eof(int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 223 {
 224   Scsi_Cmnd *SCpnt;
 225   Scsi_Tape *STp = &(scsi_tapes[dev]);
 226   unsigned char cmd[10];
 227 
 228   cmd[0] = SPACE;
 229   cmd[1] = 0x01; /* Space FileMarks */
 230   cmd[2] = cmd[3] = cmd[4] = 0xff;  /* -1 filemarks */
 231   cmd[5] = 0;
 232 
 233   SCpnt = allocate_device(NULL, STp->device, 1);
 234   SCpnt->sense_buffer[0] = 0;
 235   SCpnt->request.dev = dev;
 236   scsi_do_cmd(SCpnt,
 237               (void *) cmd, (void *) (STp->buffer)->b_data, 0,
 238               st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
 239 
 240   if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
 241   SCpnt->request.dev = -1;
 242   if ((STp->buffer)->last_result != 0) {
 243     printk("st%d: Backing over filemark failed.\n", dev);
 244     (STp->mt_status)->mt_fileno += 1;
 245     (STp->mt_status)->mt_blkno = 0;
 246   }
 247 
 248   return (STp->buffer)->last_result_fatal;
 249 }
 250 
 251 
 252 /* Flush the write buffer (never need to write if variable blocksize). */
 253         static int
 254 flush_write_buffer(int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 255 {
 256   int offset, transfer, blks;
 257   int result;
 258   unsigned char cmd[10];
 259   Scsi_Cmnd *SCpnt;
 260   Scsi_Tape *STp = &(scsi_tapes[dev]);
 261 
 262   if ((STp->buffer)->writing) {
 263     write_behind_check(dev);
 264     if ((STp->buffer)->last_result_fatal) {
 265 #ifdef DEBUG
 266       if (debugging)
 267         printk("st%d: Async write error (flush) %x.\n", dev,
 268                (STp->buffer)->last_result);
 269 #endif
 270       if ((STp->buffer)->last_result == INT_MAX)
 271         return (-ENOSPC);
 272       return (-EIO);
 273     }
 274   }
 275 
 276   result = 0;
 277   if (STp->dirty == 1) {
 278     SCpnt = allocate_device(NULL, STp->device, 1);
 279 
 280     offset = (STp->buffer)->buffer_bytes;
 281     transfer = ((offset + STp->block_size - 1) /
 282                 STp->block_size) * STp->block_size;
 283 #ifdef DEBUG
 284     if (debugging)
 285       printk("st%d: Flushing %d bytes.\n", dev, transfer);
 286 #endif
 287     memset((STp->buffer)->b_data + offset, 0, transfer - offset);
 288 
 289     SCpnt->sense_buffer[0] = 0;
 290     memset(cmd, 0, 10);
 291     cmd[0] = WRITE_6;
 292     cmd[1] = 1;
 293     blks = transfer / STp->block_size;
 294     cmd[2] = blks >> 16;
 295     cmd[3] = blks >> 8;
 296     cmd[4] = blks;
 297     SCpnt->request.dev = dev;
 298     scsi_do_cmd (SCpnt,
 299                  (void *) cmd, (STp->buffer)->b_data, transfer,
 300                  st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
 301 
 302     if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
 303 
 304     if ((STp->buffer)->last_result_fatal != 0) {
 305       printk("st%d: Error on flush.\n", dev);
 306       if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
 307           (SCpnt->sense_buffer[2] & 0x40) &&
 308           (SCpnt->sense_buffer[2] & 0x0f) != VOLUME_OVERFLOW) {
 309         STp->dirty = 0;
 310         (STp->buffer)->buffer_bytes = 0;
 311         result = (-ENOSPC);
 312       }
 313       else
 314         result = (-EIO);
 315       STp->drv_block = (-1);
 316     }
 317     else {
 318       if (STp->drv_block >= 0)
 319         STp->drv_block += blks;
 320       STp->dirty = 0;
 321       (STp->buffer)->buffer_bytes = 0;
 322     }
 323     SCpnt->request.dev = -1;  /* Mark as not busy */
 324   }
 325   return result;
 326 }
 327 
 328 
 329 /* Flush the tape buffer. The tape will be positioned correctly unless
 330    seek_next is true. */
 331         static int
 332 flush_buffer(struct inode * inode, struct file * filp, int seek_next)
     /* [previous][next][first][last][top][bottom][index][help] */
 333 {
 334   int dev;
 335   int backspace, result;
 336   Scsi_Tape * STp;
 337   ST_buffer * STbuffer;
 338 
 339   dev = MINOR(inode->i_rdev) & 127;
 340   STp = &(scsi_tapes[dev]);
 341   STbuffer = STp->buffer;
 342 
 343   if (STp->rw == ST_WRITING)  /* Writing */
 344     return flush_write_buffer(dev);
 345 
 346   if (STp->block_size == 0)
 347     return 0;
 348 
 349   backspace = ((STp->buffer)->buffer_bytes +
 350     (STp->buffer)->read_pointer) / STp->block_size -
 351       ((STp->buffer)->read_pointer + STp->block_size - 1) /
 352         STp->block_size;
 353   (STp->buffer)->buffer_bytes = 0;
 354   (STp->buffer)->read_pointer = 0;
 355   result = 0;
 356   if (!seek_next) {
 357     if ((STp->eof == ST_FM) && !STp->eof_hit) {
 358       result = back_over_eof(dev); /* Back over the EOF hit */
 359       if (!result) {
 360         STp->eof = ST_NOEOF;
 361         STp->eof_hit = 0;
 362       }
 363     }
 364     if (!result && backspace > 0)
 365       result = st_int_ioctl(inode, filp, MTBSR, backspace);
 366   }
 367   return result;
 368 
 369 }
 370 
 371 
 372 /* Open the device */
 373         static int
 374 scsi_tape_open(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 375 {
 376     int dev;
 377     unsigned short flags;
 378     int i;
 379     unsigned char cmd[10];
 380     Scsi_Cmnd * SCpnt;
 381     Scsi_Tape * STp;
 382 
 383     dev = MINOR(inode->i_rdev) & 127;
 384     if (dev >= NR_ST)
 385       return (-ENXIO);
 386     STp = &(scsi_tapes[dev]);
 387     if (STp->in_use) {
 388       printk("st%d: Device already in use.\n", dev);
 389       return (-EBUSY);
 390     }
 391 
 392     /* Allocate buffer for this user */
 393     for (i=0; i < st_nbr_buffers; i++)
 394       if (!st_buffers[i]->in_use)
 395         break;
 396     if (i >= st_nbr_buffers) {
 397       printk("st%d: No free buffers.\n", dev);
 398       return (-EBUSY);
 399     }
 400     STp->buffer = st_buffers[i];
 401     (STp->buffer)->in_use = 1;
 402     (STp->buffer)->writing = 0;
 403     STp->in_use = 1;
 404 
 405     flags = filp->f_flags;
 406     STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
 407 
 408     STp->dirty = 0;
 409     STp->rw = ST_IDLE;
 410     STp->eof = ST_NOEOF;
 411     STp->eof_hit = 0;
 412     STp->recover_count = 0;
 413 
 414     SCpnt = allocate_device(NULL, STp->device, 1);
 415     if (!SCpnt) {
 416       printk("st%d: Tape request not allocated", dev);
 417       return (-EBUSY);
 418     }
 419 
 420     SCpnt->sense_buffer[0]=0;
 421     memset ((void *) &cmd[0], 0, 10);
 422     cmd[0] = TEST_UNIT_READY;
 423     SCpnt->request.dev = dev;
 424     scsi_do_cmd(SCpnt,
 425                 (void *) cmd, (void *) (STp->buffer)->b_data,
 426                 0, st_sleep_done, ST_LONG_TIMEOUT,
 427                 MAX_READY_RETRIES);
 428 
 429     if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
 430 
 431     if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
 432         (SCpnt->sense_buffer[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
 433       (STp->mt_status)->mt_fileno = 0 ;
 434       SCpnt->sense_buffer[0]=0;
 435       memset ((void *) &cmd[0], 0, 10);
 436       cmd[0] = TEST_UNIT_READY;
 437       SCpnt->request.dev = dev;
 438       scsi_do_cmd(SCpnt,
 439                   (void *) cmd, (void *) (STp->buffer)->b_data,
 440                   0, st_sleep_done, ST_LONG_TIMEOUT,
 441                   MAX_READY_RETRIES);
 442 
 443       if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
 444       (STp->mt_status)->mt_fileno = STp->drv_block = 0;
 445     }
 446 
 447     if ((STp->buffer)->last_result_fatal != 0) {
 448       if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
 449           (SCpnt->sense_buffer[2] & 0x0f) == NO_TAPE) {
 450         (STp->mt_status)->mt_fileno = STp->drv_block = 0 ;
 451         printk("st%d: No tape.\n", dev);
 452       } else {
 453         printk("st%d: Error %x.\n", dev, SCpnt->result);
 454         (STp->mt_status)->mt_fileno = STp->drv_block = (-1);
 455       }
 456       (STp->buffer)->in_use = 0;
 457       STp->in_use = 0;
 458       SCpnt->request.dev = -1;  /* Mark as not busy */
 459       return (-EIO);
 460     }
 461 
 462     SCpnt->sense_buffer[0]=0;
 463     memset ((void *) &cmd[0], 0, 10);
 464     cmd[0] = READ_BLOCK_LIMITS;
 465     SCpnt->request.dev = dev;
 466     scsi_do_cmd(SCpnt,
 467                 (void *) cmd, (void *) (STp->buffer)->b_data,
 468                 6, st_sleep_done, ST_TIMEOUT, MAX_READY_RETRIES);
 469 
 470     if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
 471 
 472     if (!SCpnt->result && !SCpnt->sense_buffer[0]) {
 473       STp->max_block = ((STp->buffer)->b_data[1] << 16) |
 474         ((STp->buffer)->b_data[2] << 8) | (STp->buffer)->b_data[3];
 475       STp->min_block = ((STp->buffer)->b_data[4] << 8) |
 476         (STp->buffer)->b_data[5];
 477 #ifdef DEBUG
 478       if (debugging)
 479         printk("st%d: Block limits %d - %d bytes.\n", dev, STp->min_block,
 480                STp->max_block);
 481 #endif
 482     }
 483     else {
 484       STp->min_block = STp->max_block = (-1);
 485 #ifdef DEBUG
 486       if (debugging)
 487         printk("st%d: Can't read block limits.\n", dev);
 488 #endif
 489     }
 490 
 491     SCpnt->sense_buffer[0]=0;
 492     memset ((void *) &cmd[0], 0, 10);
 493     cmd[0] = MODE_SENSE;
 494     cmd[4] = 12;
 495     SCpnt->request.dev = dev;
 496     scsi_do_cmd(SCpnt,
 497                 (void *) cmd, (void *) (STp->buffer)->b_data,
 498                 12, st_sleep_done, ST_TIMEOUT, MAX_READY_RETRIES);
 499 
 500     if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
 501 
 502     if ((STp->buffer)->last_result_fatal != 0) {
 503 #ifdef DEBUG
 504       if (debugging)
 505         printk("st%d: No Mode Sense.\n", dev);
 506 #endif
 507       (STp->buffer)->b_data[2] =
 508       (STp->buffer)->b_data[3] = 0;
 509     }
 510     SCpnt->request.dev = -1;  /* Mark as not busy */
 511 
 512 #ifdef DEBUG
 513     if (debugging)
 514       printk("st%d: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n", dev,
 515              (STp->buffer)->b_data[0], (STp->buffer)->b_data[1],
 516              (STp->buffer)->b_data[2], (STp->buffer)->b_data[3]);
 517 #endif
 518 
 519     if ((STp->buffer)->b_data[3] >= 8) {
 520       STp->drv_buffer = ((STp->buffer)->b_data[2] >> 4) & 7;
 521       STp->density = (STp->buffer)->b_data[4];
 522       STp->block_size = (STp->buffer)->b_data[9] * 65536 +
 523         (STp->buffer)->b_data[10] * 256 + (STp->buffer)->b_data[11];
 524 #ifdef DEBUG
 525       if (debugging)
 526         printk("st%d: Density %x, tape length: %x, blocksize: %d, drv buffer: %d\n",
 527                dev, STp->density, (STp->buffer)->b_data[5] * 65536 +
 528                (STp->buffer)->b_data[6] * 256 + (STp->buffer)->b_data[7],
 529                STp->block_size, STp->drv_buffer);
 530 #endif
 531       if (STp->block_size > st_buffer_size) {
 532         printk("st%d: Blocksize %d too large for buffer.\n", dev,
 533                STp->block_size);
 534         (STp->buffer)->in_use = 0;
 535         STp->in_use = 0;
 536         return (-EIO);
 537       }
 538 
 539     }
 540     else
 541       STp->block_size = 512;  /* "Educated Guess" (?) */
 542 
 543     if (STp->block_size > 0) {
 544       (STp->buffer)->buffer_blocks = st_buffer_size / STp->block_size;
 545       (STp->buffer)->buffer_size =
 546         (STp->buffer)->buffer_blocks * STp->block_size;
 547     }
 548     else {
 549       (STp->buffer)->buffer_blocks = 1;
 550       (STp->buffer)->buffer_size = st_buffer_size;
 551     }
 552     (STp->buffer)->buffer_bytes = (STp->buffer)->read_pointer = 0;
 553 
 554 #ifdef DEBUG
 555     if (debugging)
 556       printk("st%d: Block size: %d, buffer size: %d (%d blocks).\n", dev,
 557              STp->block_size, (STp->buffer)->buffer_size,
 558              (STp->buffer)->buffer_blocks);
 559 #endif
 560 
 561     STp->drv_write_prot = ((STp->buffer)->b_data[2] & 0x80) != 0;
 562     if (STp->drv_write_prot) {
 563       STp->write_prot = 1;
 564 #ifdef DEBUG
 565       if (debugging)
 566         printk( "st%d: Write protected\n", dev);
 567 #endif
 568     }
 569 
 570     return 0;
 571 }
 572 
 573 
 574 /* Close the device*/
 575         static void
 576 scsi_tape_close(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 577 {
 578     int dev;
 579     int result;
 580     int rewind;
 581     static unsigned char cmd[10];
 582     Scsi_Cmnd * SCpnt;
 583     Scsi_Tape * STp;
 584    
 585     dev = MINOR(inode->i_rdev);
 586     rewind = (dev & 0x80) == 0;
 587     dev = dev & 127;
 588     STp = &(scsi_tapes[dev]);
 589 
 590     if ( STp->rw == ST_WRITING) {
 591 
 592       result = flush_write_buffer(dev);
 593 
 594 #ifdef DEBUG
 595       if (debugging)
 596         printk("st%d: File length %ld bytes.\n", dev, filp->f_pos);
 597 #endif
 598 
 599       if (result == 0 || result == (-ENOSPC)) {
 600         SCpnt = allocate_device(NULL, STp->device, 1);
 601 
 602         SCpnt->sense_buffer[0] = 0;
 603         memset(cmd, 0, 10);
 604         cmd[0] = WRITE_FILEMARKS;
 605         cmd[4] = 1 + STp->two_fm;
 606         SCpnt->request.dev = dev;
 607         scsi_do_cmd( SCpnt,
 608                     (void *) cmd, (void *) (STp->buffer)->b_data,
 609                     0, st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
 610 
 611         if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
 612 
 613         if ((STp->buffer)->last_result_fatal != 0) {
 614           SCpnt->request.dev = -1;  /* Mark as not busy */
 615           printk("st%d: Error on write filemark.\n", dev);
 616         }
 617         else {
 618           SCpnt->request.dev = -1;  /* Mark as not busy */
 619           (STp->mt_status)->mt_fileno++ ;
 620           STp->drv_block = 0;
 621           if (STp->two_fm)
 622             back_over_eof(dev);
 623         }
 624 
 625       }
 626 
 627 #ifdef DEBUG
 628       if (debugging)
 629         printk("st%d: Buffer flushed, %d EOF(s) written\n", dev, cmd[4]);
 630 #endif
 631     }
 632     else if (!rewind) {
 633 #ifndef ST_IN_FILE_POS
 634       if ((STp->eof == ST_FM) && !STp->eof_hit)
 635         back_over_eof(dev);
 636 #else
 637       flush_buffer(inode, filp, 0);
 638 #endif
 639     }
 640 
 641     if (rewind)
 642       st_int_ioctl(inode, filp, MTREW, 1);
 643 
 644     (STp->buffer)->in_use = 0;
 645     STp->in_use = 0;
 646 
 647     return;
 648 }
 649 
 650 
 651 /* Write command */
 652         static int
 653 st_write(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 654 {
 655     int dev;
 656     int total, do_count, blks, retval, transfer;
 657     int write_threshold;
 658     static unsigned char cmd[10];
 659     char *b_point;
 660     Scsi_Cmnd * SCpnt;
 661     Scsi_Tape * STp;
 662 
 663     dev = MINOR(inode->i_rdev) & 127;
 664     STp = &(scsi_tapes[dev]);
 665 #ifdef DEBUG
 666     if (!STp->in_use) {
 667       printk("st%d: Incorrect device.\n", dev);
 668       return (-EIO);
 669     }
 670 #endif
 671 
 672     if (STp->write_prot)
 673       return (-EACCES);
 674 
 675     if (STp->block_size == 0 && count > st_buffer_size)
 676       return (-EOVERFLOW);
 677 
 678     if (STp->rw == ST_READING) {
 679       retval = flush_buffer(inode, filp, 0);
 680       if (retval)
 681         return retval;
 682       STp->rw = ST_WRITING;
 683     }
 684 
 685     if (STp->moves_after_eof < 255)
 686       STp->moves_after_eof++;
 687 
 688     if ((STp->buffer)->writing) {
 689       write_behind_check(dev);
 690       if ((STp->buffer)->last_result_fatal) {
 691 #ifdef DEBUG
 692         if (debugging)
 693           printk("st%d: Async write error (write) %x.\n", dev,
 694                  (STp->buffer)->last_result);
 695 #endif
 696         if ((STp->buffer)->last_result == INT_MAX) {
 697           retval = (-ENOSPC);  /* All has been written */
 698           STp->eof = ST_EOM_OK;
 699         }
 700         else
 701           retval = (-EIO);
 702         return retval;
 703       }
 704     }
 705 
 706     if (STp->eof == ST_EOM_OK)
 707       return (-ENOSPC);
 708     else if (STp->eof == ST_EOM_ERROR)
 709       return (-EIO);
 710 
 711     if (!STp->do_buffer_writes) {
 712       if (STp->block_size != 0 && (count % STp->block_size) != 0)
 713         return (-EIO);   /* Write must be integral number of blocks */
 714       write_threshold = 1;
 715     }
 716     else
 717       write_threshold = (STp->buffer)->buffer_size;
 718     if (!STp->do_async_writes)
 719       write_threshold--;
 720 
 721     SCpnt = allocate_device(NULL, STp->device, 1);
 722 
 723     total = count;
 724 
 725     memset(cmd, 0, 10);
 726     cmd[0] = WRITE_6;
 727     cmd[1] = (STp->block_size != 0);
 728 
 729     STp->rw = ST_WRITING;
 730 
 731     b_point = buf;
 732     while((STp->block_size == 0 && !STp->do_async_writes && count > 0) ||
 733           (STp->block_size != 0 &&
 734            (STp->buffer)->buffer_bytes + count > write_threshold))
 735     {
 736       if (STp->block_size == 0)
 737         do_count = count;
 738       else {
 739         do_count = (STp->buffer)->buffer_size - (STp->buffer)->buffer_bytes;
 740         if (do_count > count)
 741           do_count = count;
 742       }
 743       memcpy_fromfs((STp->buffer)->b_data +
 744                     (STp->buffer)->buffer_bytes, b_point, do_count);
 745 
 746       if (STp->block_size == 0)
 747         blks = transfer = do_count;
 748       else {
 749         blks = ((STp->buffer)->buffer_bytes + do_count) /
 750           STp->block_size;
 751         transfer = blks * STp->block_size;
 752       }
 753       cmd[2] = blks >> 16;
 754       cmd[3] = blks >> 8;
 755       cmd[4] = blks;
 756       SCpnt->sense_buffer[0] = 0;
 757       SCpnt->request.dev = dev;
 758       scsi_do_cmd (SCpnt,
 759                    (void *) cmd, (STp->buffer)->b_data, transfer,
 760                    st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
 761 
 762       if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
 763 
 764       if ((STp->buffer)->last_result_fatal != 0) {
 765 #ifdef DEBUG
 766         if (debugging)
 767           printk("st%d: Error on write:\n", dev);
 768 #endif
 769         if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
 770             (SCpnt->sense_buffer[2] & 0x40)) {
 771           if (STp->block_size != 0 && (SCpnt->sense_buffer[0] & 0x80) != 0)
 772             transfer = (SCpnt->sense_buffer[3] << 24) |
 773               (SCpnt->sense_buffer[4] << 16) |
 774                 (SCpnt->sense_buffer[5] << 8) | SCpnt->sense_buffer[6];
 775           else if (STp->block_size == 0 &&
 776                    (SCpnt->sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW)
 777             transfer = do_count;
 778           else
 779             transfer = 0;
 780           if (STp->block_size != 0)
 781             transfer *= STp->block_size;
 782           if (transfer <= do_count) {
 783             filp->f_pos += do_count - transfer;
 784             count -= do_count - transfer;
 785             if (STp->drv_block >= 0) {
 786               if (STp->block_size == 0 && transfer < do_count)
 787                 STp->drv_block++;
 788               else if (STp->block_size != 0)
 789                 STp->drv_block += (do_count - transfer) / STp->block_size;
 790             }
 791             STp->eof = ST_EOM_OK;
 792             retval = (-ENOSPC); /* EOM within current request */
 793 #ifdef DEBUG
 794             if (debugging)
 795               printk("st%d: EOM with %d bytes unwritten.\n",
 796                      dev, transfer);
 797 #endif
 798           }
 799           else {
 800             STp->eof = ST_EOM_ERROR;
 801             STp->drv_block = (-1);    /* Too cautious? */
 802             retval = (-EIO); /* EOM for old data */
 803 #ifdef DEBUG
 804             if (debugging)
 805               printk("st%d: EOM with lost data.\n", dev);
 806 #endif
 807           }
 808         }
 809         else {
 810           STp->drv_block = (-1);    /* Too cautious? */
 811           retval = (-EIO);
 812         }
 813 
 814         SCpnt->request.dev = -1;  /* Mark as not busy */
 815         (STp->buffer)->buffer_bytes = 0;
 816         STp->dirty = 0;
 817         if (count < total)
 818           return total - count;
 819         else
 820           return retval;
 821       }
 822       filp->f_pos += do_count;
 823       b_point += do_count;
 824       count -= do_count;
 825       if (STp->drv_block >= 0) {
 826         if (STp->block_size == 0)
 827           STp->drv_block++;
 828         else
 829           STp->drv_block += blks;
 830       }
 831       (STp->buffer)->buffer_bytes = 0;
 832       STp->dirty = 0;
 833     }
 834     if (count != 0) {
 835       STp->dirty = 1;
 836       memcpy_fromfs((STp->buffer)->b_data +
 837                     (STp->buffer)->buffer_bytes,b_point,count);
 838       filp->f_pos += count;
 839       (STp->buffer)->buffer_bytes += count;
 840       count = 0;
 841     }
 842 
 843     if ((STp->buffer)->last_result_fatal != 0) {
 844       SCpnt->request.dev = -1;
 845       return (STp->buffer)->last_result_fatal;
 846     }
 847 
 848     if (STp->do_async_writes &&
 849         ((STp->buffer)->buffer_bytes >= STp->write_threshold ||
 850          STp->block_size == 0) ) {
 851       /* Schedule an asynchronous write */
 852       if (STp->block_size == 0)
 853         (STp->buffer)->writing = (STp->buffer)->buffer_bytes;
 854       else
 855         (STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
 856           STp->block_size) * STp->block_size;
 857       STp->dirty = 0;
 858 
 859       if (STp->block_size == 0)
 860         blks = (STp->buffer)->writing;
 861       else
 862         blks = (STp->buffer)->writing / STp->block_size;
 863       cmd[2] = blks >> 16;
 864       cmd[3] = blks >> 8;
 865       cmd[4] = blks;
 866       SCpnt->result = (STp->buffer)->last_result = -1;
 867       SCpnt->sense_buffer[0] = 0;
 868       SCpnt->request.dev = dev;
 869       scsi_do_cmd (SCpnt,
 870                    (void *) cmd, (STp->buffer)->b_data,
 871                    (STp->buffer)->writing,
 872                    st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
 873     }
 874     else
 875       SCpnt->request.dev = -1;  /* Mark as not busy */
 876 
 877     return( total);
 878 }   
 879 
 880 
 881 /* Read command */
 882         static int
 883 st_read(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 884 {
 885     int dev;
 886     int total;
 887     int transfer, blks, bytes;
 888     static unsigned char cmd[10];
 889     Scsi_Cmnd * SCpnt;
 890     Scsi_Tape * STp;
 891 
 892     dev = MINOR(inode->i_rdev) & 127;
 893     STp = &(scsi_tapes[dev]);
 894 #ifdef DEBUG
 895     if (!STp->in_use) {
 896       printk("st%d: Incorrect device.\n", dev);
 897       return (-EIO);
 898     }
 899 #endif
 900 
 901     if (STp->block_size == 0 && count > st_buffer_size)
 902       return (-EOVERFLOW);
 903 
 904     if (!(STp->do_read_ahead) && STp->block_size != 0 &&
 905         (count % STp->block_size) != 0)
 906       return (-EIO);    /* Read must be integral number of blocks */
 907 
 908     if (STp->rw == ST_WRITING) {
 909       transfer = flush_buffer(inode, filp, 0);
 910       if (transfer)
 911         return transfer;
 912       STp->rw = ST_READING;
 913     }
 914     if (STp->moves_after_eof < 255)
 915       STp->moves_after_eof++;
 916 
 917 #ifdef DEBUG
 918     if (debugging && STp->eof != ST_NOEOF)
 919       printk("st%d: EOF flag up. Bytes %d\n", dev,
 920              (STp->buffer)->buffer_bytes);
 921 #endif
 922     if (((STp->buffer)->buffer_bytes == 0) &&
 923         STp->eof == ST_EOM_OK)  /* EOM or Blank Check */
 924       return (-EIO);
 925 
 926     STp->rw = ST_READING;
 927 
 928     SCpnt = allocate_device(NULL, STp->device, 1);
 929 
 930     for (total = 0; total < count; ) {
 931 
 932       if ((STp->buffer)->buffer_bytes == 0 &&
 933           STp->eof == ST_NOEOF) {
 934 
 935         memset(cmd, 0, 10);
 936         cmd[0] = READ_6;
 937         cmd[1] = (STp->block_size != 0);
 938         if (STp->block_size == 0)
 939           blks = bytes = count;
 940         else {
 941           if (STp->do_read_ahead) {
 942             blks = (STp->buffer)->buffer_blocks;
 943             bytes = blks * STp->block_size;
 944           }
 945           else {
 946             bytes = count;
 947             if (bytes > st_buffer_size)
 948               bytes = st_buffer_size;
 949             blks = bytes / STp->block_size;
 950             bytes = blks * STp->block_size;
 951           }
 952         }
 953         cmd[2] = blks >> 16;
 954         cmd[3] = blks >> 8;
 955         cmd[4] = blks;
 956 
 957         SCpnt->sense_buffer[0] = 0;
 958         SCpnt->request.dev = dev;
 959         scsi_do_cmd (SCpnt,
 960                      (void *) cmd, (STp->buffer)->b_data,
 961                      (STp->buffer)->buffer_size,
 962                      st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
 963 
 964         if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
 965 
 966         (STp->buffer)->read_pointer = 0;
 967         STp->eof_hit = 0;
 968 
 969         if ((STp->buffer)->last_result_fatal) {
 970 #ifdef DEBUG
 971           if (debugging)
 972             printk("st%d: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n", dev,
 973                    SCpnt->sense_buffer[0], SCpnt->sense_buffer[1],
 974                    SCpnt->sense_buffer[2], SCpnt->sense_buffer[3],
 975                    SCpnt->sense_buffer[4], SCpnt->sense_buffer[5],
 976                    SCpnt->sense_buffer[6], SCpnt->sense_buffer[7]);
 977 #endif
 978           if ((SCpnt->sense_buffer[0] & 0x70) == 0x70) { /* extended sense */
 979 
 980             if ((SCpnt->sense_buffer[2] & 0xe0) != 0) { /* EOF, EOM, or ILI */
 981 
 982               if ((SCpnt->sense_buffer[0] & 0x80) != 0)
 983                 transfer = (SCpnt->sense_buffer[3] << 24) |
 984                   (SCpnt->sense_buffer[4] << 16) |
 985                     (SCpnt->sense_buffer[5] << 8) | SCpnt->sense_buffer[6];
 986               else
 987                 transfer = 0;
 988               if (STp->block_size == 0 &&
 989                   (SCpnt->sense_buffer[2] & 0x0f) == MEDIUM_ERROR)
 990                 transfer = bytes;
 991 
 992               if (SCpnt->sense_buffer[2] & 0x20) {
 993                 if (STp->block_size == 0) {
 994                   if (transfer <= 0)
 995                     transfer = 0;
 996                   (STp->buffer)->buffer_bytes = bytes - transfer;
 997                 }
 998                 else {
 999                   printk("st%d: Incorrect block size.\n", dev);
1000                   SCpnt->request.dev = -1;  /* Mark as not busy */
1001                   return (-EIO);
1002                 }
1003               }
1004               else if (SCpnt->sense_buffer[2] & 0x40) {
1005                 STp->eof = ST_EOM_OK;
1006                 if (STp->block_size == 0)
1007                   (STp->buffer)->buffer_bytes = bytes - transfer;
1008                 else
1009                   (STp->buffer)->buffer_bytes =
1010                     bytes - transfer * STp->block_size;
1011 #ifdef DEBUG
1012                 if (debugging)
1013                   printk("st%d: EOM detected (%d bytes read).\n", dev,
1014                          (STp->buffer)->buffer_bytes);
1015 #endif
1016               }
1017               else if (SCpnt->sense_buffer[2] & 0x80) {
1018                 STp->eof = ST_FM;
1019                 if (STp->block_size == 0)
1020                   (STp->buffer)->buffer_bytes = 0;
1021                 else
1022                   (STp->buffer)->buffer_bytes =
1023                     bytes - transfer * STp->block_size;
1024 #ifdef DEBUG
1025                 if (debugging)
1026                   printk(
1027                     "st%d: EOF detected (%d bytes read, transferred %d bytes).\n",
1028                          dev, (STp->buffer)->buffer_bytes, total);
1029 #endif
1030               }
1031             } /* end of EOF, EOM, ILI test */
1032             else { /* nonzero sense key */
1033 #ifdef DEBUG
1034               if (debugging)
1035                 printk("st%d: Tape error while reading.\n", dev);
1036 #endif
1037               SCpnt->request.dev = -1;
1038               STp->drv_block = (-1);
1039               if (total)
1040                 return total;
1041               else if (STp->moves_after_eof == 1 &&
1042                        (SCpnt->sense_buffer[2] & 0x0f) == BLANK_CHECK) {
1043 #ifdef DEBUG
1044                 if (debugging)
1045                   printk("st%d: Zero returned for first BLANK CHECK after EOF.\n",
1046                          dev);
1047 #endif
1048                 return 0; /* First BLANK_CHECK after EOF */
1049               }
1050               else
1051                 return -EIO;
1052             }
1053           } /* End of extended sense test */
1054           else {
1055             transfer = (STp->buffer)->last_result_fatal;
1056             SCpnt->request.dev = -1;  /* Mark as not busy */
1057             return transfer;
1058           }
1059         } /* End of error handling */
1060         else /* Read successful */
1061           (STp->buffer)->buffer_bytes = bytes;
1062 
1063         if (STp->drv_block >= 0) {
1064           if (STp->block_size == 0)
1065             STp->drv_block++;
1066           else
1067             STp->drv_block += (STp->buffer)->buffer_bytes / STp->block_size;
1068         }
1069 
1070       } /* if ((STp->buffer)->buffer_bytes == 0 &&
1071            STp->eof == ST_NOEOF) */
1072 
1073       if ((STp->buffer)->buffer_bytes > 0) {
1074 #ifdef DEBUG
1075         if (debugging && STp->eof != ST_NOEOF)
1076           printk("st%d: EOF up. Left %d, needed %d.\n", dev,
1077                  (STp->buffer)->buffer_bytes, count - total);
1078 #endif
1079         transfer = (STp->buffer)->buffer_bytes < count - total ?
1080           (STp->buffer)->buffer_bytes : count - total;
1081         memcpy_tofs(buf, (STp->buffer)->b_data +
1082                     (STp->buffer)->read_pointer,transfer);
1083         filp->f_pos += transfer;
1084         buf += transfer;
1085         total += transfer;
1086         (STp->buffer)->buffer_bytes -= transfer;
1087         (STp->buffer)->read_pointer += transfer;
1088       }
1089       else if (STp->eof != ST_NOEOF) {
1090         STp->eof_hit = 1;
1091         SCpnt->request.dev = -1;  /* Mark as not busy */
1092         if (total == 0 && STp->eof == ST_FM) {
1093           STp->eof = 0;
1094           STp->drv_block = 0;
1095           if (STp->moves_after_eof > 1)
1096             STp->moves_after_eof = 0;
1097           (STp->mt_status)->mt_fileno++;
1098         }
1099         if (total == 0 && STp->eof == ST_EOM_OK)
1100           return (-EIO);  /* ST_EOM_ERROR not used in read */
1101         return total;
1102       }
1103 
1104       if (STp->block_size == 0)
1105         count = total;  /* Read only one variable length block */
1106 
1107     } /* for (total = 0; total < count; ) */
1108 
1109     SCpnt->request.dev = -1;  /* Mark as not busy */
1110 
1111     return total;
1112 }
1113 
1114 
1115 
1116 /* Set the driver options */
1117         static int
1118 st_set_options(struct inode * inode, long options)
     /* [previous][next][first][last][top][bottom][index][help] */
1119 {
1120   int dev, value;
1121   Scsi_Tape *STp;
1122 
1123   dev = MINOR(inode->i_rdev) & 127;
1124   STp = &(scsi_tapes[dev]);
1125   if ((options & MT_ST_OPTIONS) == MT_ST_BOOLEANS) {
1126     STp->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
1127     STp->do_async_writes  = (options & MT_ST_ASYNC_WRITES) != 0;
1128     STp->do_read_ahead    = (options & MT_ST_READ_AHEAD) != 0;
1129     STp->two_fm           = (options & MT_ST_TWO_FM) != 0;
1130 #ifdef DEBUG
1131     debugging = (options & MT_ST_DEBUGGING) != 0;
1132     printk(
1133 "st%d: options: buffer writes: %d, async writes: %d, read ahead: %d\n",
1134            dev, STp->do_buffer_writes, STp->do_async_writes,
1135            STp->do_read_ahead);
1136     printk("              two FMs: %d, debugging: %d\n", STp->two_fm,
1137            debugging);
1138 #endif
1139   }
1140   else if ((options & MT_ST_OPTIONS) == MT_ST_WRITE_THRESHOLD) {
1141     value = (options & ~MT_ST_OPTIONS) * ST_BLOCK_SIZE;
1142     if (value < 1 || value > st_buffer_size) {
1143       printk("st: Write threshold %d too small or too large.\n",
1144              value);
1145       return (-EIO);
1146     }
1147     STp->write_threshold = value;
1148 #ifdef DEBUG
1149     printk("st%d: Write threshold set to %d bytes.\n", dev,
1150            STp->write_threshold);
1151 #endif
1152   }
1153   else
1154     return (-EIO);
1155 
1156   return 0;
1157 }
1158 
1159 
1160 /* Internal ioctl function */
1161         static int
1162 st_int_ioctl(struct inode * inode,struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
1163              unsigned int cmd_in, unsigned long arg)
1164 {
1165    int dev = MINOR(inode->i_rdev);
1166    int timeout = ST_LONG_TIMEOUT;
1167    long ltmp;
1168    int ioctl_result;
1169    unsigned char cmd[10];
1170    Scsi_Cmnd * SCpnt;
1171    Scsi_Tape * STp;
1172    int fileno, blkno, undone, datalen;
1173 
1174    dev = dev & 127;
1175    STp = &(scsi_tapes[dev]);
1176    fileno = (STp->mt_status)->mt_fileno ;
1177    blkno = STp->drv_block;
1178 
1179    memset(cmd, 0, 10);
1180    datalen = 0;
1181    switch (cmd_in) {
1182      case MTFSF:
1183      case MTFSFM:
1184        cmd[0] = SPACE;
1185        cmd[1] = 0x01; /* Space FileMarks */
1186        cmd[2] = (arg >> 16);
1187        cmd[3] = (arg >> 8);
1188        cmd[4] = arg;
1189 #ifdef DEBUG
1190        if (debugging)
1191          printk("st%d: Spacing tape forward over %d filemarks.\n", dev,
1192                 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
1193 #endif
1194        fileno += arg;
1195        blkno = 0;
1196        break; 
1197      case MTBSF:
1198      case MTBSFM:
1199        cmd[0] = SPACE;
1200        cmd[1] = 0x01; /* Space FileMarks */
1201        ltmp = (-arg);
1202        cmd[2] = (ltmp >> 16);
1203        cmd[3] = (ltmp >> 8);
1204        cmd[4] = ltmp;
1205 #ifdef DEBUG
1206        if (debugging) {
1207          if (cmd[2] & 0x80)
1208            ltmp = 0xff000000;
1209          ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
1210          printk("st%d: Spacing tape backward over %ld filemarks.\n", dev, (-ltmp));
1211        }
1212 #endif
1213        fileno -= arg;
1214        blkno = (-1);  /* We can't know the block number */
1215        break; 
1216       case MTFSR:
1217        cmd[0] = SPACE;
1218        cmd[1] = 0x00; /* Space Blocks */
1219        cmd[2] = (arg >> 16);
1220        cmd[3] = (arg >> 8);
1221        cmd[4] = arg;
1222 #ifdef DEBUG
1223        if (debugging)
1224          printk("st%d: Spacing tape forward %d blocks.\n", dev,
1225                 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
1226 #endif
1227        if (blkno >= 0)
1228          blkno += arg;
1229        break; 
1230      case MTBSR:
1231        cmd[0] = SPACE;
1232        cmd[1] = 0x00; /* Space Blocks */
1233        ltmp = (-arg);
1234        cmd[2] = (ltmp >> 16);
1235        cmd[3] = (ltmp >> 8);
1236        cmd[4] = ltmp;
1237 #ifdef DEBUG
1238        if (debugging) {
1239          if (cmd[2] & 0x80)
1240            ltmp = 0xff000000;
1241          ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
1242          printk("st%d: Spacing tape backward %ld blocks.\n", dev, (-ltmp));
1243        }
1244 #endif
1245        if (blkno >= 0)
1246          blkno -= arg;
1247        break; 
1248      case MTWEOF:
1249        if (STp->write_prot)
1250          return (-EACCES);
1251        cmd[0] = WRITE_FILEMARKS;
1252        cmd[2] = (arg >> 16);
1253        cmd[3] = (arg >> 8);
1254        cmd[4] = arg;
1255        timeout = ST_TIMEOUT;
1256 #ifdef DEBUG
1257        if (debugging)
1258          printk("st%d: Writing %d filemarks.\n", dev,
1259                 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
1260 #endif
1261        fileno += arg;
1262        blkno = 0;
1263        break; 
1264      case MTREW:
1265        cmd[0] = REZERO_UNIT;
1266 #ifdef ST_NOWAIT
1267        cmd[1] = 1;  /* Don't wait for completion */
1268        timeout = ST_TIMEOUT;
1269 #endif
1270 #ifdef DEBUG
1271        if (debugging)
1272          printk("st%d: Rewinding tape.\n", dev);
1273 #endif
1274        fileno = blkno = 0 ;
1275        break; 
1276      case MTOFFL:
1277        cmd[0] = START_STOP;
1278 #ifdef ST_NOWAIT
1279        cmd[1] = 1;  /* Don't wait for completion */
1280        timeout = ST_TIMEOUT;
1281 #endif
1282 #ifdef DEBUG
1283        if (debugging)
1284          printk("st%d: Unloading tape.\n", dev);
1285 #endif
1286        fileno = blkno = 0 ;
1287        break; 
1288      case MTNOP:
1289 #ifdef DEBUG
1290        if (debugging)
1291          printk("st%d: No op on tape.\n", dev);
1292 #endif
1293        return 0;  /* Should do something ? */
1294        break;
1295      case MTRETEN:
1296        cmd[0] = START_STOP;
1297 #ifdef ST_NOWAIT
1298        cmd[1] = 1;  /* Don't wait for completion */
1299        timeout = ST_TIMEOUT;
1300 #endif
1301        cmd[4] = 3;
1302 #ifdef DEBUG
1303        if (debugging)
1304          printk("st%d: Retensioning tape.\n", dev);
1305 #endif
1306        fileno = blkno = 0 ;
1307        break; 
1308      case MTEOM:
1309        /* space to the end of tape */
1310        ioctl_result = st_int_ioctl(inode, file, MTFSF, 0x3fff);
1311        fileno = (STp->mt_status)->mt_fileno ;
1312        /* The next lines would hide the number of spaced FileMarks
1313           That's why I inserted the previous lines. I had no luck
1314           with detecting EOM with FSF, so we go now to EOM.
1315           Joerg Weule */
1316        cmd[0] = SPACE;
1317        cmd[1] = 3;
1318 #ifdef DEBUG
1319        if (debugging)
1320          printk("st%d: Spacing to end of recorded medium.\n", dev);
1321 #endif
1322        blkno = (-1);
1323        break; 
1324      case MTERASE:
1325        if (STp->write_prot)
1326          return (-EACCES);
1327        cmd[0] = ERASE;
1328        cmd[1] = 1;  /* To the end of tape */
1329 #ifdef DEBUG
1330        if (debugging)
1331          printk("st%d: Erasing tape.\n", dev);
1332 #endif
1333        fileno = blkno = 0 ;
1334        break;
1335      case MTSEEK:
1336        if ((STp->device)->scsi_level < SCSI_2) {
1337          cmd[0] = QFA_SEEK_BLOCK;
1338          cmd[2] = (arg >> 16);
1339          cmd[3] = (arg >> 8);
1340          cmd[4] = arg;
1341          cmd[5] = 0;
1342        }
1343        else {
1344          cmd[0] = SEEK_10;
1345          cmd[1] = 4;
1346          cmd[3] = (arg >> 24);
1347          cmd[4] = (arg >> 16);
1348          cmd[5] = (arg >> 8);
1349          cmd[6] = arg;
1350        }
1351 #ifdef ST_NOWAIT
1352        cmd[1] |= 1;  /* Don't wait for completion */
1353        timeout = ST_TIMEOUT;
1354 #endif
1355 #ifdef DEBUG
1356        if (debugging)
1357          printk("st%d: Seeking tape to block %ld.\n", dev, arg);
1358 #endif
1359        fileno = blkno = (-1);
1360        break;
1361      case MTSETBLK:  /* Set block length */
1362      case MTSETDENSITY: /* Set tape density */
1363      case MTSETDRVBUFFER: /* Set drive buffering */
1364        if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
1365          return (-EIO);   /* Not allowed if data in buffer */
1366        if (cmd_in == MTSETBLK &&
1367            arg != 0 &&
1368            (arg < STp->min_block || arg > STp->max_block ||
1369             arg > st_buffer_size)) {
1370          printk("st%d: Illegal block size.\n", dev);
1371          return (-EINVAL);
1372        }
1373        cmd[0] = MODE_SELECT;
1374        cmd[4] = datalen = 12;
1375 
1376        memset((STp->buffer)->b_data, 0, 12);
1377        if (cmd_in == MTSETDRVBUFFER)
1378          (STp->buffer)->b_data[2] = (arg & 7) << 4;
1379        else
1380          (STp->buffer)->b_data[2] = 
1381            STp->drv_buffer << 4;
1382        (STp->buffer)->b_data[3] = 8;     /* block descriptor length */
1383        if (cmd_in == MTSETDENSITY)
1384          (STp->buffer)->b_data[4] = arg;
1385        else
1386          (STp->buffer)->b_data[4] = STp->density;
1387        if (cmd_in == MTSETBLK)
1388          ltmp = arg;
1389        else
1390          ltmp = STp->block_size;
1391        (STp->buffer)->b_data[9] = (ltmp >> 16);
1392        (STp->buffer)->b_data[10] = (ltmp >> 8);
1393        (STp->buffer)->b_data[11] = ltmp;
1394        timeout = ST_TIMEOUT;
1395 #ifdef DEBUG
1396        if (debugging) {
1397          if (cmd_in == MTSETBLK)
1398            printk("st%d: Setting block size to %d bytes.\n", dev,
1399                   (STp->buffer)->b_data[9] * 65536 +
1400                   (STp->buffer)->b_data[10] * 256 +
1401                   (STp->buffer)->b_data[11]);
1402          else if (cmd_in == MTSETDENSITY)
1403            printk("st%d: Setting density code to %x.\n", dev,
1404                   (STp->buffer)->b_data[4]);
1405          else
1406            printk("st%d: Setting drive buffer code to %d.\n", dev,
1407                   ((STp->buffer)->b_data[2] >> 4) & 7);
1408        }
1409 #endif
1410        break;
1411      default:
1412        printk("st%d: Unknown st_ioctl command %x.\n", dev, cmd_in);
1413        return (-ENOSYS);
1414      }
1415 
1416    SCpnt = allocate_device(NULL, STp->device, 1);
1417    SCpnt->sense_buffer[0] = 0;
1418    SCpnt->request.dev = dev;
1419    scsi_do_cmd(SCpnt,
1420                (void *) cmd, (void *) (STp->buffer)->b_data, datalen,
1421                st_sleep_done, timeout, MAX_RETRIES);
1422 
1423    if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
1424 
1425    ioctl_result = (STp->buffer)->last_result_fatal;
1426 
1427    SCpnt->request.dev = -1;  /* Mark as not busy */
1428 
1429    if (!ioctl_result) {
1430      if (cmd_in != MTSEEK) {
1431        STp->drv_block = blkno;
1432        (STp->mt_status)->mt_fileno = fileno;
1433      }
1434      else
1435        STp->drv_block = (STp->mt_status)->mt_fileno = (-1);
1436      if (cmd_in == MTFSF)
1437        STp->moves_after_eof = 0;
1438      else
1439        STp->moves_after_eof = 1;
1440      if (cmd_in == MTBSFM)
1441        ioctl_result = st_int_ioctl(inode, file, MTFSF, 1);
1442      else if (cmd_in == MTFSFM)
1443        ioctl_result = st_int_ioctl(inode, file, MTBSF, 1);
1444      else if (cmd_in == MTSETBLK) {
1445        STp->block_size = arg;
1446        if (arg != 0) {
1447          (STp->buffer)->buffer_blocks =
1448            st_buffer_size / STp->block_size;
1449          (STp->buffer)->buffer_size =
1450            (STp->buffer)->buffer_blocks * STp->block_size;
1451        }
1452        else {
1453          (STp->buffer)->buffer_blocks = 1;
1454          (STp->buffer)->buffer_size = st_buffer_size;
1455        }
1456        (STp->buffer)->buffer_bytes =
1457          (STp->buffer)->read_pointer = 0;
1458      }
1459      else if (cmd_in == MTSETDRVBUFFER)
1460        STp->drv_buffer = (arg & 7);
1461      else if (cmd_in == MTSETDENSITY)
1462        STp->density = arg;
1463      else if (cmd_in == MTEOM) {
1464        STp->eof = ST_EOM_OK;
1465        STp->eof_hit = 0;
1466      }
1467      else if (cmd_in != MTSETBLK && cmd_in != MTNOP) {
1468        STp->eof = ST_NOEOF;
1469        STp->eof_hit = 0;
1470      }
1471    } else {
1472      if (SCpnt->sense_buffer[2] & 0x40) {
1473        STp->eof = ST_EOM_OK;
1474        STp->eof_hit = 0;
1475        STp->drv_block = 0;
1476      }
1477      undone = (
1478           (SCpnt->sense_buffer[3] << 24) +
1479           (SCpnt->sense_buffer[4] << 16) +
1480           (SCpnt->sense_buffer[5] << 8) +
1481           SCpnt->sense_buffer[6] );
1482      if ( (cmd_in == MTFSF) || (cmd_in == MTFSFM) )
1483        (STp->mt_status)->mt_fileno = fileno - undone ;
1484      else if ( (cmd_in == MTBSF) || (cmd_in == MTBSFM) )
1485        (STp->mt_status)->mt_fileno = fileno + undone ;
1486      else if (cmd_in == MTFSR) {
1487        if (blkno >= undone)
1488          STp->drv_block = blkno - undone;
1489        else
1490          STp->drv_block = (-1);
1491      }
1492      else if (cmd_in == MTBSR && blkno >= 0) {
1493        if (blkno >= 0)
1494          STp->drv_block = blkno + undone;
1495        else
1496          STp->drv_block = (-1);
1497      }
1498    }
1499 
1500    return ioctl_result ;
1501 }
1502 
1503 
1504 
1505 /* The ioctl command */
1506         static int
1507 st_ioctl(struct inode * inode,struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
1508          unsigned int cmd_in, unsigned long arg)
1509 {
1510    int dev = MINOR(inode->i_rdev);
1511    int i, cmd, result;
1512    struct mtop mtc;
1513    struct mtpos mt_pos;
1514    unsigned char scmd[10];
1515    Scsi_Cmnd *SCpnt;
1516    Scsi_Tape *STp;
1517 
1518    dev = dev & 127;
1519    STp = &(scsi_tapes[dev]);
1520 #ifdef DEBUG
1521    if (debugging && !STp->in_use) {
1522      printk("st%d: Incorrect device.\n", dev);
1523      return (-EIO);
1524    }
1525 #endif
1526 
1527    cmd = cmd_in & IOCCMD_MASK;
1528    if (cmd == (MTIOCTOP & IOCCMD_MASK)) {
1529 
1530      if (((cmd_in & IOCSIZE_MASK) >> IOCSIZE_SHIFT) != sizeof(mtc))
1531        return (-EINVAL);
1532 
1533      i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(mtc));
1534      if (i)
1535         return i;
1536 
1537      memcpy_fromfs((char *) &mtc, (char *)arg, sizeof(struct mtop));
1538 
1539      i = flush_buffer(inode, file, mtc.mt_op == MTNOP || mtc.mt_op == MTSEEK ||
1540                       mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
1541                       mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM);
1542      if (i < 0)
1543        return i;
1544 
1545      if (mtc.mt_op == MTSETDRVBUFFER &&
1546          (mtc.mt_count & MT_ST_OPTIONS) != 0)
1547        return st_set_options(inode, mtc.mt_count);
1548      else
1549        return st_int_ioctl(inode, file, mtc.mt_op, mtc.mt_count);
1550    }
1551    else if (cmd == (MTIOCGET & IOCCMD_MASK)) {
1552 
1553      if (((cmd_in & IOCSIZE_MASK) >> IOCSIZE_SHIFT) != sizeof(struct mtget))
1554        return (-EINVAL);
1555      i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct mtget));
1556      if (i)
1557        return i;
1558 
1559      (STp->mt_status)->mt_dsreg =
1560        ((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
1561        ((STp->density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
1562      (STp->mt_status)->mt_blkno = STp->drv_block;
1563      if (STp->block_size != 0) {
1564        if (STp->rw == ST_WRITING)
1565          (STp->mt_status)->mt_blkno +=
1566            (STp->buffer)->buffer_bytes / STp->block_size;
1567        else if (STp->rw == ST_READING)
1568          (STp->mt_status)->mt_blkno -= ((STp->buffer)->buffer_bytes +
1569            STp->block_size - 1) / STp->block_size;
1570      }
1571      (STp->mt_status)->mt_gstat = 0;
1572      if (STp->drv_write_prot)
1573        (STp->mt_status)->mt_gstat |= GMT_WR_PROT(0xffffffff);
1574 
1575      memcpy_tofs((char *)arg, (char *)(STp->mt_status),
1576                  sizeof(struct mtget));
1577 
1578      (STp->mt_status)->mt_erreg = 0;  /* Clear after read */
1579      return 0;
1580    }
1581    else if (cmd == (MTIOCPOS & IOCCMD_MASK)) {
1582 #ifdef DEBUG
1583      if (debugging)
1584        printk("st%d: get tape position.\n", dev);
1585 #endif
1586      if (((cmd_in & IOCSIZE_MASK) >> IOCSIZE_SHIFT) != sizeof(struct mtpos))
1587        return (-EINVAL);
1588 
1589      i = flush_buffer(inode, file, 0);
1590      if (i < 0)
1591        return i;
1592 
1593      i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct mtpos));
1594      if (i)
1595        return i;
1596 
1597      SCpnt = allocate_device(NULL, STp->device, 1);
1598 
1599      SCpnt->sense_buffer[0]=0;
1600      memset (scmd, 0, 10);
1601      if ((STp->device)->scsi_level < SCSI_2) {
1602        scmd[0] = QFA_REQUEST_BLOCK;
1603        scmd[4] = 3;
1604      }
1605      else {
1606        scmd[0] = READ_POSITION;
1607        scmd[1] = 1;
1608      }
1609      SCpnt->request.dev = dev;
1610      SCpnt->sense_buffer[0] = 0;
1611      scsi_do_cmd(SCpnt,
1612                  (void *) scmd, (void *) (STp->buffer)->b_data,
1613                  20, st_sleep_done, ST_TIMEOUT, MAX_READY_RETRIES);
1614 
1615      if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
1616      
1617      if ((STp->buffer)->last_result_fatal != 0) {
1618        mt_pos.mt_blkno = (-1);
1619 #ifdef DEBUG
1620        if (debugging)
1621          printk("st%d: Can't read tape position.\n", dev);
1622 #endif
1623        result = (-EIO);
1624      }
1625      else {
1626        result = 0;
1627        if ((STp->device)->scsi_level < SCSI_2)
1628          mt_pos.mt_blkno = ((STp->buffer)->b_data[0] << 16) 
1629            + ((STp->buffer)->b_data[1] << 8) 
1630              + (STp->buffer)->b_data[2];
1631        else
1632          mt_pos.mt_blkno = ((STp->buffer)->b_data[4] << 24)
1633            + ((STp->buffer)->b_data[5] << 16) 
1634              + ((STp->buffer)->b_data[6] << 8) 
1635                + (STp->buffer)->b_data[7];
1636 
1637      }
1638 
1639      SCpnt->request.dev = -1;  /* Mark as not busy */
1640 
1641      memcpy_tofs((char *)arg, (char *) (&mt_pos), sizeof(struct mtpos));
1642      return result;
1643    }
1644    else
1645      return scsi_ioctl(STp->device, cmd_in, (void *) arg);
1646 }
1647 
1648 
1649 /* Set the boot options. Syntax: st=xxx,yyy
1650    where xxx is buffer size in 512 byte blocks and yyy is write threshold
1651    in 512 byte blocks. */
1652         void
1653 st_setup(char *str, int *ints)
     /* [previous][next][first][last][top][bottom][index][help] */
1654 {
1655   if (ints[0] > 0 && ints[1] > 0)
1656     st_buffer_size = ints[1] * ST_BLOCK_SIZE;
1657   if (ints[0] > 1 && ints[2] > 0) {
1658     st_write_threshold = ints[2] * ST_BLOCK_SIZE;
1659     if (st_write_threshold > st_buffer_size)
1660       st_write_threshold = st_buffer_size;
1661   }
1662   if (ints[0] > 2 && ints[3] > 0)
1663     st_max_buffers = ints[3];
1664 }
1665 
1666 
1667 static struct file_operations st_fops = {
1668    NULL,            /* lseek - default */
1669    st_read,         /* read - general block-dev read */
1670    st_write,        /* write - general block-dev write */
1671    NULL,            /* readdir - bad */
1672    NULL,            /* select */
1673    st_ioctl,        /* ioctl */
1674    NULL,            /* mmap */
1675    scsi_tape_open,  /* open */
1676    scsi_tape_close, /* release */
1677    NULL             /* fsync */
1678 };
1679 
1680 void st_attach(Scsi_Device * SDp){
     /* [previous][next][first][last][top][bottom][index][help] */
1681   scsi_tapes[NR_ST++].device = SDp;
1682   if(NR_ST > MAX_ST) panic ("scsi_devices corrupt (st)");
1683 };
1684 
1685 void st_init1(){
     /* [previous][next][first][last][top][bottom][index][help] */
1686   scsi_tapes = (Scsi_Tape *) scsi_init_malloc(MAX_ST * sizeof(Scsi_Tape));
1687 };
1688 
1689 /* Driver initialization */
1690 unsigned long st_init(unsigned long mem_start, unsigned long mem_end)
     /* [previous][next][first][last][top][bottom][index][help] */
1691 {
1692   int i;
1693   Scsi_Tape * STp;
1694   Scsi_Device * SDp;
1695 
1696   if (register_chrdev(MAJOR_NR,"st",&st_fops)) {
1697     printk("Unable to get major %d for SCSI tapes\n",MAJOR_NR);
1698     return mem_start;
1699   }
1700   if (NR_ST == 0) return mem_start;
1701 
1702 #ifdef DEBUG
1703   printk("st: Buffer size %d bytes, write threshold %d bytes.\n",
1704          st_buffer_size, st_write_threshold);
1705 #endif
1706 
1707   for (i=0, SDp = scsi_devices; i < NR_ST; ++i) {
1708     STp = &(scsi_tapes[i]);
1709     STp->capacity = 0xfffff;
1710     STp->dirty = 0;
1711     STp->rw = ST_IDLE;
1712     STp->eof = ST_NOEOF;
1713     STp->waiting = NULL;
1714     STp->in_use = 0;
1715     STp->drv_buffer = 1;  /* Try buffering if no mode sense */
1716     STp->density = 0;
1717     STp->do_buffer_writes = ST_BUFFER_WRITES;
1718     STp->do_async_writes = ST_ASYNC_WRITES;
1719     STp->do_read_ahead = ST_READ_AHEAD;
1720     STp->two_fm = ST_TWO_FM;
1721     STp->write_threshold = st_write_threshold;
1722     STp->drv_block = 0;
1723     STp->moves_after_eof = 1;
1724     STp->mt_status = (struct mtget *) mem_start;
1725     mem_start += sizeof(struct mtget);
1726     /* Initialize status */
1727     memset((void *) scsi_tapes[i].mt_status, 0, sizeof(struct mtget));
1728     for (; SDp; SDp = SDp->next)
1729       if (SDp->type == TYPE_TAPE)
1730         break;
1731     if (!SDp)
1732       printk("st%d: ERROR: Not found in scsi chain.\n", i);
1733     else {
1734       if (SDp->scsi_level <= 2)
1735         STp->mt_status->mt_type = MT_ISSCSI1;
1736       else
1737         STp->mt_status->mt_type = MT_ISSCSI2;
1738     }
1739     SDp = SDp->next;
1740   }
1741 
1742   /* Allocate the buffers */
1743   st_nbr_buffers = NR_ST;
1744   if (st_nbr_buffers > st_max_buffers)
1745     st_nbr_buffers = st_max_buffers;
1746   st_buffers = (ST_buffer **)mem_start;
1747   mem_start += st_nbr_buffers * sizeof(ST_buffer *);
1748   for (i=0; i < st_nbr_buffers; i++) {
1749     st_buffers[i] = (ST_buffer *) mem_start;
1750 #ifdef DEBUG
1751 /*    printk("st: Buffer address: %p\n", st_buffers[i]); */
1752 #endif
1753     mem_start += sizeof(ST_buffer) - 1 + st_buffer_size;
1754     st_buffers[i]->in_use = 0;
1755     st_buffers[i]->writing = 0;
1756   }
1757 
1758   return mem_start;
1759 }

/* [previous][next][first][last][top][bottom][index][help] */