root/kernel/blk_drv/scsi/st.c

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

DEFINITIONS

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

   1 /*
   2   SCSI Tape Driver for Linux
   3 
   4   Version 0.02 for Linux 0.98.4 and Eric Youngdale's new scsi driver
   5 
   6   History:
   7   Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
   8 
   9   Features:
  10   - support for different block sizes and internal buffering
  11   - *nix-style ioctl with codes from mtio.h from the QIC-02 driver by
  12     Hennus Bergman (command MTSETBLK added)
  13   - character device
  14   - rewind and non-rewind devices
  15   - capability to handle several tape drives simultaneously
  16   - one buffer if one drive, two buffers if more than one drive (limits the
  17     number of simultaneously open drives to two)
  18   - write behind
  19   - seek and tell (Tandberg compatible and SCSI-2)
  20 
  21   Devices:
  22   Autorewind devices have minor numbers equal to the tape numbers (0 > ).
  23   Nonrewind device has the minor number equal to tape number + 128.
  24 
  25   Problems:
  26   The end of media detection may not work correctly because of the buffering.
  27   If you want to do multiple tape backups relying on end of tape detection,
  28   you should disable write behind and in addition to that check that the
  29   tapes are readable.
  30 
  31   Kai Makisara, Nov 9, 1992  email makisara@vtinsx.ins.vtt.fi or
  32                                     Kai.Makisara@vtt.fi
  33   Last changes Jan 3, 1993.
  34 */
  35 
  36 #include <linux/fs.h>
  37 #include <linux/kernel.h>
  38 #include <linux/sched.h>
  39 #include <linux/string.h>
  40 #include <linux/errno.h>
  41 #include <linux/mtio.h>
  42 #include <linux/ioctl.h>
  43 #include <linux/fcntl.h>
  44 #include <asm/segment.h>
  45 #include <asm/system.h>
  46 
  47 #define MAJOR_NR 9
  48 #include "../blk.h"
  49 #include "scsi.h"
  50 #include "st.h"
  51 
  52 #define MAX_RETRIES 5
  53 #define NO_TAPE  NOT_READY
  54 
  55 /* Uncomment the following if you want the rewind, etc. commands return
  56    before command completion. */
  57 /* #define ST_NOWAIT */
  58 
  59 /* Uncomment the following if you want the tape to be positioned correctly
  60    within file after close (the tape is positioned correctly with respect
  61    to the filemarks even wihout ST_IN_FILE_POS defined */
  62 /* #define ST_IN_FILE_POS */
  63 
  64 /* #define DEBUG */
  65 
  66 #define ST_TIMEOUT 6000
  67 #define ST_LONG_TIMEOUT 200000
  68 
  69 /* Number of ST_BLOCK_SIZE blocks in the buffers */
  70 #define ST_BUFFER_BLOCKS 64
  71 /* Write-behind can be disabled by setting ST_WRITE_THRESHOLD_BLOCKS equal to or
  72    larger than ST_BUFFER_BLOCKS */
  73 #define ST_WRITE_THRESHOLD_BLOCKS 60
  74 #define ST_BLOCK_SIZE 512
  75 #define ST_BUFFER_SIZE (ST_BUFFER_BLOCKS * ST_BLOCK_SIZE)
  76 #define ST_WRITE_THRESHOLD (ST_WRITE_THRESHOLD_BLOCKS * ST_BLOCK_SIZE)
  77 
  78 static int st_nbr_buffers;
  79 static ST_buffer *st_buffers[2];
  80 
  81 static Scsi_Tape * scsi_tapes;
  82 int NR_ST=0;
  83 int MAX_ST=0;
  84 
  85 static int st_int_ioctl(struct inode * inode,struct file * file,
  86              unsigned int cmd_in, unsigned long arg);
  87 
  88 
  89 
  90 
  91 /* Wakeup from interrupt */
  92 static void st_sleep_done (Scsi_Cmnd * SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
  93 {
  94   int st_nbr;
  95 
  96   if ((st_nbr = SCpnt->request.dev) < NR_ST && st_nbr >= 0) {
  97     if (scsi_tapes[st_nbr].buffer->writing &&
  98         (SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
  99         (SCpnt->sense_buffer[2] & 0x40))
 100       scsi_tapes[st_nbr].buffer->last_result = 0x7fffffff;
 101     else
 102       scsi_tapes[st_nbr].buffer->last_result = SCpnt->result;
 103     if (scsi_tapes[st_nbr].buffer->writing)
 104       SCpnt->request.dev = -1;
 105     else
 106       SCpnt->request.dev = 0xffff;
 107     if (scsi_tapes[st_nbr].buffer->writing <= 0)
 108       wake_up( &scsi_tapes[st_nbr].waiting );
 109   }
 110 #ifdef DEBUG
 111   else
 112     printk("st?: Illegal interrupt device %x\n", st_nbr);
 113 #endif
 114 }
 115 
 116 
 117 
 118 #ifdef DEBUG
 119 /* Print sense information */
 120 static void decode_sns(int dev, char *sense_buffer)
     /* [previous][next][first][last][top][bottom][index][help] */
 121 {
 122    static char *snstext[] = {
 123    "None","Recovered Error","Not Ready","Medium Error","Hardware Error",
 124    "Illegal Request","Unit Attention","Data Protect","Blank Check",
 125    "Key=E","Key=F","Filemark","End-Of-Medium","Incorrect Block Length",
 126    "14","15"};
 127 
 128    if (sense_buffer[0]!=0) {
 129       if ((sense_buffer[0] & 0x70) == 0x70) {
 130          if (sense_buffer[2] & 0x80) printk( "FMK ");
 131          if (sense_buffer[2] & 0x40) printk( "EOM ");
 132          if (sense_buffer[2] & 0x20) printk( "ILI ");
 133         printk( "st%d: sense key %s\n", dev, snstext[sense_buffer[2] & 0x0f]);
 134       } else {
 135       if (sense_buffer[0] < 15)
 136         printk("st%d: old sense key %s\n", dev, snstext[sense_buffer[0] & 0x0f]);
 137       else
 138         printk("st%d: sns = %2x %2x\n", dev, sense_buffer[0], sense_buffer[2]);
 139       }
 140    }
 141    return;
 142 }
 143 #endif
 144 
 145 
 146 /* Convert the result to success code */
 147 static int st_chk_result(int dev, int result, char *sense)
     /* [previous][next][first][last][top][bottom][index][help] */
 148 {
 149   if (!result)
 150     return 0;
 151 #ifdef DEBUG
 152   printk("st%d: Error: %x\n", dev, result);
 153   decode_sns(dev, sense);
 154 #endif
 155   if ((sense[0] & 0x70) == 0x70 &&
 156        ((sense[2] & 0x80) /* || ((sense[2] & 0x0f) == 8) */ ))
 157     return 0;
 158   return (-EIO);
 159 }
 160 
 161 
 162 #if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS
 163 /* Handle the write-behind checking */
 164 static void write_behind_check(int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 165 {
 166   cli();
 167   if (scsi_tapes[dev].buffer->last_result < 0) {
 168     scsi_tapes[dev].buffer->writing = (- scsi_tapes[dev].buffer->writing);
 169     sleep_on( &scsi_tapes[dev].waiting );
 170     scsi_tapes[dev].buffer->writing = (- scsi_tapes[dev].buffer->writing);
 171   }
 172   sti();
 173 
 174   if (scsi_tapes[dev].buffer->writing < scsi_tapes[dev].buffer->buffer_bytes)
 175     memcpy(scsi_tapes[dev].buffer->b_data,
 176            scsi_tapes[dev].buffer->b_data + scsi_tapes[dev].buffer->writing,
 177            scsi_tapes[dev].buffer->buffer_bytes -
 178            scsi_tapes[dev].buffer->writing);
 179   scsi_tapes[dev].buffer->buffer_bytes -= scsi_tapes[dev].buffer->writing;
 180   scsi_tapes[dev].buffer->writing = 0;
 181 
 182   return;
 183 }
 184 #endif
 185 
 186 
 187 /* Flush the write buffer */
 188 static int flush_write_buffer(int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 189 {
 190   int offset, transfer, blks;
 191   int result;
 192   unsigned char cmd[10];
 193   Scsi_Cmnd *SCpnt;
 194 
 195 #if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS
 196   if (scsi_tapes[dev].buffer->writing) {
 197     write_behind_check(dev);
 198     if (scsi_tapes[dev].buffer->last_result) {
 199 #ifdef DEBUG
 200       printk("st%d: Async write error %x.\n", dev,
 201              scsi_tapes[dev].buffer->last_result);
 202 #endif
 203       return (-EIO);
 204     }
 205   }
 206 #endif
 207 
 208   result = 0;
 209   if (scsi_tapes[dev].dirty==1) {
 210     SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1);
 211 
 212     offset = scsi_tapes[dev].buffer->buffer_bytes;
 213     transfer = ((offset + scsi_tapes[dev].block_size - 1) /
 214                 scsi_tapes[dev].block_size) * scsi_tapes[dev].block_size;
 215 #ifdef DEBUG
 216     printk("st%d: Flushing %d bytes.\n", dev, transfer);
 217 #endif
 218     memset(scsi_tapes[dev].buffer->b_data + offset, 0, transfer - offset);
 219 
 220     SCpnt->sense_buffer[0] = 0;
 221     memset(cmd, 0, 10);
 222     cmd[0] = WRITE_6;
 223     cmd[1] = 1;
 224     blks = transfer / scsi_tapes[dev].block_size;
 225     cmd[2] = blks >> 16;
 226     cmd[3] = blks >> 8;
 227     cmd[4] = blks;
 228     SCpnt->request.dev = dev;
 229     scsi_do_cmd (SCpnt,
 230                  (void *) cmd, scsi_tapes[dev].buffer->b_data, transfer,
 231                  st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
 232 
 233     if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
 234 
 235     if (SCpnt->result != 0) {
 236       printk("st%d: Error on flush:\n", dev);
 237 #ifdef DEBUG
 238       st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);
 239 #endif
 240       result = (-EIO);
 241     }
 242     else {
 243       scsi_tapes[dev].dirty = 0;
 244       scsi_tapes[dev].buffer->buffer_bytes = 0;
 245     }
 246     SCpnt->request.dev = -1;  /* Mark as not busy */
 247   }
 248   return result;
 249 }
 250 
 251 
 252 /* Flush the tape buffer. The tape will be positioned correctly unless
 253    seek_next is true. */
 254 static int flush_buffer(struct inode * inode, struct file * filp,
     /* [previous][next][first][last][top][bottom][index][help] */
 255                         int seek_next)
 256 {
 257   int dev;
 258   int backspace, result;
 259 
 260   dev = inode->i_rdev & 127;
 261 
 262   if (scsi_tapes[dev].rw == 2)  /* Writing */
 263     return flush_write_buffer(dev);
 264 
 265   backspace = (scsi_tapes[dev].buffer->buffer_bytes +
 266     scsi_tapes[dev].buffer->read_pointer) / scsi_tapes[dev].block_size -
 267       (scsi_tapes[dev].buffer->read_pointer + scsi_tapes[dev].block_size - 1) /
 268         scsi_tapes[dev].block_size;
 269   scsi_tapes[dev].buffer->buffer_bytes = 0;
 270   scsi_tapes[dev].buffer->read_pointer = 0;
 271   result = 0;
 272   if (!seek_next && backspace > 0) {
 273     result = st_int_ioctl(inode, filp, MTBSR, backspace);
 274     if (!result) {
 275       scsi_tapes[dev].eof = 0;
 276       scsi_tapes[dev].eof_hit = 0;
 277     }
 278   }
 279   return result;
 280 
 281 }
 282 
 283 
 284 /* Open the device */
 285 static int scsi_tape_open(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 286 {
 287     int dev;
 288     unsigned short flags;
 289     int i;
 290     unsigned char cmd[10];
 291     Scsi_Cmnd * SCpnt;
 292 
 293     dev = inode->i_rdev & 127;
 294     if (dev >= NR_ST)
 295       return (-ENODEV);
 296     if (scsi_tapes[dev].in_use) {
 297       printk("st%d: Device already in use.\n", dev);
 298       return (-EBUSY);
 299     }
 300 
 301     /* Allocate buffer for this user */
 302     for (i=0; i < st_nbr_buffers; i++)
 303       if (!st_buffers[i]->in_use)
 304         break;
 305     if (i >= st_nbr_buffers) {
 306       printk("st%d: No free buffers.\n", dev);
 307       return (-EBUSY);
 308     }
 309     st_buffers[i]->in_use = 1;
 310     st_buffers[i]->writing = 0;
 311     scsi_tapes[dev].buffer = st_buffers[i];
 312     scsi_tapes[dev].in_use = 1;
 313 
 314     flags = filp->f_flags;
 315     scsi_tapes[dev].write_prot = ((flags & O_ACCMODE) == O_RDONLY);
 316 
 317     scsi_tapes[dev].dirty = 0;
 318     scsi_tapes[dev].rw = 0;
 319     scsi_tapes[dev].eof = 0;
 320     scsi_tapes[dev].eof_hit = 0;
 321 
 322     SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1);
 323     if (!SCpnt) {
 324       printk("st%d: Tape request not allocated", dev);
 325       return (-EBUSY);
 326     }
 327 
 328     SCpnt->sense_buffer[0]=0;
 329     memset ((void *) &cmd[0], 0, 10);
 330     cmd[0] = TEST_UNIT_READY;
 331     SCpnt->request.dev = dev;
 332     scsi_do_cmd(SCpnt,
 333                 (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data,
 334                 ST_BLOCK_SIZE, st_sleep_done, ST_LONG_TIMEOUT, MAX_RETRIES);
 335 
 336     if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
 337 
 338     if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
 339         (SCpnt->sense_buffer[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
 340 #ifdef DEBUG
 341       decode_sns(dev, SCpnt->sense_buffer);
 342 #endif
 343       SCpnt->sense_buffer[0]=0;
 344       memset ((void *) &cmd[0], 0, 10);
 345       cmd[0] = TEST_UNIT_READY;
 346       SCpnt->request.dev = dev;
 347       scsi_do_cmd(SCpnt,
 348                   (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data,
 349                   ST_BLOCK_SIZE, st_sleep_done, ST_LONG_TIMEOUT, MAX_RETRIES);
 350 
 351       if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
 352     }
 353 
 354     if (SCpnt->result != 0) {
 355 #ifdef DEBUG
 356       decode_sns(dev, SCpnt->sense_buffer);
 357 #endif
 358       if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
 359           (SCpnt->sense_buffer[2] & 0x0f) == NO_TAPE)
 360         printk("st%d: No tape.\n", dev);
 361       else
 362         printk("st%d: Error %x.\n", dev, SCpnt->result);
 363       scsi_tapes[dev].buffer->in_use = 0;
 364       scsi_tapes[dev].in_use = 0;
 365       SCpnt->request.dev = -1;  /* Mark as not busy */
 366       return (-EIO);
 367     }
 368 
 369     SCpnt->sense_buffer[0]=0;
 370     memset ((void *) &cmd[0], 0, 10);
 371     cmd[0] = READ_BLOCK_LIMITS;
 372     SCpnt->request.dev = dev;
 373     scsi_do_cmd(SCpnt,
 374                 (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data,
 375                 ST_BLOCK_SIZE, st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
 376 
 377     if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
 378 
 379     if (!SCpnt->result && !SCpnt->sense_buffer[0]) {
 380       scsi_tapes[dev].max_block = (scsi_tapes[dev].buffer->b_data[1] << 16) |
 381         (scsi_tapes[dev].buffer->b_data[2] << 8) | scsi_tapes[dev].buffer->b_data[3];
 382       scsi_tapes[dev].min_block = (scsi_tapes[dev].buffer->b_data[4] << 8) |
 383         scsi_tapes[dev].buffer->b_data[5];
 384 #ifdef DEBUG
 385       printk("st%d: Block limits %d - %d bytes.\n", dev, scsi_tapes[dev].min_block,
 386              scsi_tapes[dev].max_block);
 387 #endif
 388     }
 389     else {
 390       scsi_tapes[dev].min_block = scsi_tapes[dev].max_block = (-1);
 391 #ifdef DEBUG
 392       printk("st%d: Can't read block limits.\n", dev);
 393 #endif
 394     }
 395 
 396     SCpnt->sense_buffer[0]=0;
 397     memset ((void *) &cmd[0], 0, 10);
 398     cmd[0] = MODE_SENSE;
 399     cmd[4] = 12;
 400     SCpnt->request.dev = dev;
 401     scsi_do_cmd(SCpnt,
 402                 (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data,
 403                 ST_BLOCK_SIZE, st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
 404 
 405     if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
 406 
 407     i = st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);
 408     if (i) {
 409 #ifdef DEBUG
 410       printk("st%d: No Mode Sense.\n", dev);
 411 #endif
 412       scsi_tapes[dev].buffer->b_data[2] =
 413       scsi_tapes[dev].buffer->b_data[3] = 0;
 414     }
 415     SCpnt->request.dev = -1;  /* Mark as not busy */
 416 
 417 #ifdef DEBUG
 418     printk("st%d: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n", dev,
 419            scsi_tapes[dev].buffer->b_data[0], scsi_tapes[dev].buffer->b_data[1],
 420            scsi_tapes[dev].buffer->b_data[2], scsi_tapes[dev].buffer->b_data[3]);
 421 #endif
 422 
 423     if (scsi_tapes[dev].buffer->b_data[3] >= 8) {
 424       scsi_tapes[dev].block_size = scsi_tapes[dev].buffer->b_data[9] * 65536 +
 425         scsi_tapes[dev].buffer->b_data[10] * 256 + scsi_tapes[dev].buffer->b_data[11];
 426 #ifdef DEBUG
 427       printk("st%d: Density %x, tape length: %x, blocksize: %d\n", dev,
 428              scsi_tapes[dev].buffer->b_data[4], scsi_tapes[dev].buffer->b_data[5] *
 429              65536 + scsi_tapes[dev].buffer->b_data[6] * 256 +
 430              scsi_tapes[dev].buffer->b_data[7], scsi_tapes[dev].buffer->b_data[9] *
 431              65536 + scsi_tapes[dev].buffer->b_data[10] * 256 +
 432              scsi_tapes[dev].buffer->b_data[11]);
 433 #endif
 434       if (scsi_tapes[dev].block_size > ST_BUFFER_SIZE) {
 435         printk("st%d: Blocksize %d too large for buffer.\n", dev,
 436                scsi_tapes[dev].block_size);
 437         scsi_tapes[dev].buffer->in_use = 0;
 438         scsi_tapes[dev].in_use = 0;
 439         return (-EIO);
 440       }
 441 
 442       if (scsi_tapes[dev].block_size == 0) {
 443         printk("st%d: Fixing block size to 512 bytes.\n", dev);
 444         if (st_int_ioctl(inode, filp, MTSETBLK, ST_BLOCK_SIZE)) {
 445           printk("st%d: Can't set fixed block size.\n", dev);
 446           scsi_tapes[dev].buffer->in_use = 0;
 447           scsi_tapes[dev].in_use = 0;
 448           return (-EIO);
 449         }
 450         scsi_tapes[dev].block_size = ST_BLOCK_SIZE;
 451       }
 452     }
 453     else
 454       scsi_tapes[dev].block_size = ST_BLOCK_SIZE;
 455 
 456     scsi_tapes[dev].buffer->buffer_blocks =
 457       ST_BUFFER_SIZE / scsi_tapes[dev].block_size;
 458     scsi_tapes[dev].buffer->buffer_size =
 459       scsi_tapes[dev].buffer->buffer_blocks * scsi_tapes[dev].block_size;
 460     scsi_tapes[dev].buffer->buffer_bytes = scsi_tapes[dev].buffer->read_pointer = 0;
 461 
 462 #ifdef DEBUG
 463     printk("st%d: Block size: %d, buffer size: %d (%d blocks).\n", dev,
 464            scsi_tapes[dev].block_size, scsi_tapes[dev].buffer->buffer_size,
 465            scsi_tapes[dev].buffer->buffer_blocks);
 466 #endif
 467 
 468     if (scsi_tapes[dev].buffer->b_data[2] & 0x80) {
 469       scsi_tapes[dev].write_prot = 1;
 470 #ifdef DEBUG
 471       printk( "st%d: Write protected\n", dev);
 472 #endif
 473     }
 474 
 475     return 0;
 476 }
 477 
 478 
 479 /* Close the device*/
 480 static void scsi_tape_close(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 481 {
 482     int dev;
 483     int result;
 484     int rewind;
 485     static unsigned char cmd[10];
 486     Scsi_Cmnd * SCpnt;
 487    
 488     dev = inode->i_rdev;
 489     rewind = (dev & 0x80) == 0;
 490     dev = dev & 127;
 491 
 492     if ( scsi_tapes[dev].rw == 2) {
 493 
 494       result = flush_write_buffer(dev);
 495 
 496 #ifdef DEBUG
 497       printk("st%d: File length %d bytes.\n", dev, filp->f_pos);
 498 #endif
 499 
 500       if (!result) {
 501         SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1);
 502 
 503         SCpnt->sense_buffer[0] = 0;
 504         memset(cmd, 0, 10);
 505         cmd[0] = WRITE_FILEMARKS;
 506         cmd[4] = 1;
 507         SCpnt->request.dev = dev;
 508         scsi_do_cmd( SCpnt,
 509                     (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data,
 510                     ST_BLOCK_SIZE, st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
 511 
 512         if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
 513 
 514         if (SCpnt->result) {
 515           printk("st%d: Error on write filemark:\n", dev);
 516 #ifdef DEBUG
 517           st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);
 518 #endif
 519         }
 520         SCpnt->request.dev = -1;  /* Mark as not busy */
 521       }
 522 
 523 #ifdef DEBUG
 524       printk("st%d: Buffer flushed, EOF written\n", dev);
 525 #endif
 526     }
 527     else if (!rewind) {
 528       if ((scsi_tapes[dev].eof == 1) && !scsi_tapes[dev].eof_hit)
 529         st_int_ioctl(inode, filp, MTBSF, 1); /* Back over the EOF hit */
 530 #ifdef ST_IN_FILE_POS
 531       flush_buffer(inode, filp, 0);
 532 #endif
 533     }
 534 
 535     if (rewind)
 536       st_int_ioctl(inode, filp, MTREW, 1);
 537 
 538     scsi_tapes[dev].buffer->in_use = 0;
 539     scsi_tapes[dev].in_use = 0;
 540 
 541     return;
 542 }
 543 
 544 
 545 /* Write command */
 546 int st_write(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 547 {
 548     int dev;
 549     int total, do_count, blks, retval;
 550     static unsigned char cmd[10];
 551     char *b_point;
 552     Scsi_Cmnd * SCpnt;
 553 
 554     dev = inode->i_rdev & 127;
 555 #ifdef DEBUG
 556     if (!scsi_tapes[dev].in_use) {
 557       printk("st%d: Incorrect device.\n", dev);
 558       return (-EIO);
 559     }
 560 #endif
 561 
 562     if (scsi_tapes[dev].write_prot)
 563       return (-EACCES);
 564 
 565     if (scsi_tapes[dev].rw == 1) {
 566       retval = flush_buffer(inode, filp, 0);
 567       if (retval)
 568         return retval;
 569       scsi_tapes[dev].rw = 2;
 570     }
 571 
 572 #if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS
 573     if (scsi_tapes[dev].buffer->writing) {
 574       write_behind_check(dev);
 575       if (scsi_tapes[dev].buffer->last_result) {
 576 #ifdef DEBUG
 577         printk("st%d: Async write error %x.\n", dev,
 578                scsi_tapes[dev].buffer->last_result);
 579 #endif
 580         /*if (scsi_tapes[dev].buffer->last_result = 0x7fffffff)
 581           retval = (-ENOSPC);
 582         else */
 583           retval = (-EIO);
 584         return retval;
 585       }
 586     }
 587 #endif
 588 
 589     SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1);
 590 
 591     total = count;
 592 
 593     memset(cmd, 0, 10);
 594     cmd[0] = WRITE_6;
 595     cmd[1] = 1;
 596 
 597     scsi_tapes[dev].rw = 2;
 598 
 599     b_point = buf;
 600     while((scsi_tapes[dev].buffer->buffer_bytes + count) >=
 601           scsi_tapes[dev].buffer->buffer_size) {
 602       do_count = scsi_tapes[dev].buffer->buffer_size -
 603         scsi_tapes[dev].buffer->buffer_bytes;
 604       memcpy_fromfs(scsi_tapes[dev].buffer->b_data +
 605                     scsi_tapes[dev].buffer->buffer_bytes,b_point,do_count);
 606 
 607       blks = scsi_tapes[dev].buffer->buffer_blocks;
 608       cmd[2] = blks >> 16;
 609       cmd[3] = blks >> 8;
 610       cmd[4] = blks;
 611       SCpnt->sense_buffer[0] = 0;
 612       SCpnt->request.dev = dev;
 613       scsi_do_cmd (SCpnt,
 614                    (void *) cmd, scsi_tapes[dev].buffer->b_data,
 615                    scsi_tapes[dev].buffer->buffer_size,
 616                    st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
 617 
 618       if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
 619 
 620       if (SCpnt->result || SCpnt->sense_buffer[0] != 0) {
 621 #ifdef DEBUG
 622         printk("st%d: Error on write:\n", dev);
 623         st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);
 624 #endif
 625         if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
 626             (SCpnt->sense_buffer[2] & 0x40))
 627           retval = (-ENOSPC); /* EOM */
 628         else
 629           retval = (-EIO);
 630         SCpnt->request.dev = -1;  /* Mark as not busy */
 631         if (count < total)
 632           return total - count;
 633         else
 634           return retval;
 635       }
 636       filp->f_pos += do_count;
 637       b_point += do_count;
 638       count -= do_count;
 639       scsi_tapes[dev].buffer->buffer_bytes = 0;
 640       scsi_tapes[dev].dirty = 0;
 641     }
 642     if (count != 0) {
 643       scsi_tapes[dev].dirty = 1;
 644       memcpy_fromfs(scsi_tapes[dev].buffer->b_data +
 645                     scsi_tapes[dev].buffer->buffer_bytes,b_point,count);
 646       filp->f_pos += count;
 647       scsi_tapes[dev].buffer->buffer_bytes += count;
 648       count = 0;
 649     }
 650 
 651     do_count = st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);
 652     if (do_count) {
 653       SCpnt->request.dev = -1;
 654       return do_count;
 655     }
 656 
 657 #if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS
 658     if (scsi_tapes[dev].buffer->buffer_bytes >= ST_WRITE_THRESHOLD) {
 659       /* Schedule an asynchronous write */
 660       scsi_tapes[dev].buffer->writing = (scsi_tapes[dev].buffer->buffer_bytes /
 661         scsi_tapes[dev].block_size) * scsi_tapes[dev].block_size;
 662       scsi_tapes[dev].dirty = 0;
 663 
 664       blks = scsi_tapes[dev].buffer->writing / scsi_tapes[dev].block_size;
 665       cmd[2] = blks >> 16;
 666       cmd[3] = blks >> 8;
 667       cmd[4] = blks;
 668       SCpnt->result = scsi_tapes[dev].buffer->last_result = -1;
 669       SCpnt->sense_buffer[0] = 0;
 670       SCpnt->request.dev = dev;
 671       scsi_do_cmd (SCpnt,
 672                    (void *) cmd, scsi_tapes[dev].buffer->b_data,
 673                    scsi_tapes[dev].buffer->writing,
 674                    st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
 675     }
 676     else
 677 #endif
 678       SCpnt->request.dev = -1;  /* Mark as not busy */
 679 
 680     return( total);
 681 }   
 682 
 683 
 684 /* Read command */
 685 int st_read(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 686 {
 687     int dev;
 688     int total;
 689     int transfer, blks;
 690     static unsigned char cmd[10];
 691     Scsi_Cmnd * SCpnt;
 692 
 693     dev = inode->i_rdev & 127;
 694 #ifdef DEBUG
 695     if (!scsi_tapes[dev].in_use) {
 696       printk("st%d: Incorrect device.\n", dev);
 697       return (-EIO);
 698     }
 699 #endif
 700 
 701     if (scsi_tapes[dev].rw == 2) {
 702       transfer = flush_buffer(inode, filp, 0);
 703       if (transfer)
 704         return transfer;
 705       scsi_tapes[dev].rw = 1;
 706     }
 707 
 708 #ifdef DEBUG
 709     if (scsi_tapes[dev].eof)
 710       printk("st%d: EOF flag up. Bytes %d\n", dev,
 711              scsi_tapes[dev].buffer->buffer_bytes);
 712 #endif
 713     if ((scsi_tapes[dev].buffer->buffer_bytes == 0) &&
 714         scsi_tapes[dev].eof == 2)  /* EOM or Blank Check */
 715       return (-EIO);
 716 
 717     scsi_tapes[dev].rw = 1;
 718 
 719     SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1);
 720 
 721     for (total = 0; total < count; ) {
 722 
 723       if (scsi_tapes[dev].buffer->buffer_bytes == 0 &&
 724           scsi_tapes[dev].eof == 0) {
 725 
 726         memset(cmd, 0, 10);
 727         cmd[0] = READ_6;
 728         cmd[1] = 1;
 729         blks = scsi_tapes[dev].buffer->buffer_blocks;
 730         cmd[2] = blks >> 16;
 731         cmd[3] = blks >> 8;
 732         cmd[4] = blks;
 733 
 734         SCpnt->sense_buffer[0] = 0;
 735         SCpnt->request.dev = dev;
 736         scsi_do_cmd (SCpnt,
 737                      (void *) cmd, scsi_tapes[dev].buffer->b_data,
 738                      scsi_tapes[dev].buffer->buffer_size,
 739                      st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
 740 
 741         if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
 742 
 743         scsi_tapes[dev].buffer->read_pointer = 0;
 744         scsi_tapes[dev].eof_hit = 0;
 745 
 746         if (SCpnt->result != 0 || SCpnt->sense_buffer[0] != 0) {
 747 #ifdef DEBUG
 748           printk("st%d: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n", dev,
 749                  SCpnt->sense_buffer[0], SCpnt->sense_buffer[1],
 750                  SCpnt->sense_buffer[2], SCpnt->sense_buffer[3],
 751                  SCpnt->sense_buffer[4], SCpnt->sense_buffer[5],
 752                  SCpnt->sense_buffer[6], SCpnt->sense_buffer[7]);
 753 #endif
 754           if ((SCpnt->sense_buffer[0] & 0x70) == 0x70) { /* extended sense */
 755 
 756             if ((SCpnt->sense_buffer[2] & 0xe0) != 0) { /* EOF, EOM, or ILI */
 757               transfer = (SCpnt->sense_buffer[3] << 24) |
 758                 (SCpnt->sense_buffer[4] << 16) |
 759                   (SCpnt->sense_buffer[5] << 8) | SCpnt->sense_buffer[6];
 760 
 761               if (SCpnt->sense_buffer[2] & 0x20) {
 762                 printk("st%d: Incorrect block size.\n", dev);
 763                 SCpnt->request.dev = -1;  /* Mark as not busy */
 764                 return (-EIO);
 765               }
 766               else if (SCpnt->sense_buffer[2] & 0x40) {
 767                 scsi_tapes[dev].eof = 2; /* What should be done at EOM ? */
 768                 scsi_tapes[dev].buffer->buffer_bytes =
 769                   (scsi_tapes[dev].buffer->buffer_blocks - transfer) *
 770                     scsi_tapes[dev].block_size;
 771 #ifdef DEBUG
 772                 printk("st%d: EOM detected (%d blocks read).\n", dev,
 773                        scsi_tapes[dev].buffer->buffer_blocks - transfer);
 774 #endif
 775               }
 776               else if (SCpnt->sense_buffer[2] & 0x80) {
 777                 scsi_tapes[dev].eof = 1;
 778                 scsi_tapes[dev].buffer->buffer_bytes =
 779                   (scsi_tapes[dev].buffer->buffer_blocks - transfer) *
 780                     scsi_tapes[dev].block_size;
 781 #ifdef DEBUG
 782                 printk("st%d: EOF detected (%d blocks read, transferred %d bytes).\n",
 783                        dev, scsi_tapes[dev].buffer->buffer_blocks - transfer, total);
 784 #endif
 785               } /* end of EOF, EOM, ILI test */
 786             }
 787             else { /* nonzero sense key */
 788 #ifdef DEBUG
 789               printk("st%d: Tape error. Sense key %x\n", dev,
 790                      SCpnt->sense_buffer[2] & 0x0f);
 791               decode_sns(dev, SCpnt->sense_buffer);
 792 #endif
 793               SCpnt->request.dev = -1;
 794               if (total)
 795                 return total;
 796               else
 797                 return -EIO;
 798             }
 799           }
 800           else {
 801             transfer = st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);
 802             SCpnt->request.dev = -1;  /* Mark as not busy */
 803             return transfer;
 804           }
 805         }
 806         else
 807           scsi_tapes[dev].buffer->buffer_bytes =
 808             scsi_tapes[dev].buffer->buffer_size;
 809       } /* if (scsi_tapes[dev].buffer->buffer_bytes == 0 &&
 810            scsi_tapes[dev].eof == 0) */
 811 
 812       if (scsi_tapes[dev].buffer->buffer_bytes > 0) {
 813 #ifdef DEBUG
 814         if (scsi_tapes[dev].eof)
 815           printk("st%d: EOF up. Left %d, needed %d.\n", dev,
 816                  scsi_tapes[dev].buffer->buffer_bytes, count - total);
 817 #endif
 818         transfer = scsi_tapes[dev].buffer->buffer_bytes < count - total ?
 819           scsi_tapes[dev].buffer->buffer_bytes : count - total;
 820         memcpy_tofs(buf, scsi_tapes[dev].buffer->b_data +
 821                     scsi_tapes[dev].buffer->read_pointer,transfer);
 822         filp->f_pos += transfer;
 823         buf += transfer;
 824         total += transfer;
 825         scsi_tapes[dev].buffer->buffer_bytes -= transfer;
 826         scsi_tapes[dev].buffer->read_pointer += transfer;
 827       }
 828       else if (scsi_tapes[dev].eof) {
 829         scsi_tapes[dev].eof_hit = 1;
 830         SCpnt->request.dev = -1;  /* Mark as not busy */
 831         if (total == 0 && scsi_tapes[dev].eof == 1)
 832           scsi_tapes[dev].eof = 0;
 833         if (total == 0 && scsi_tapes[dev].eof == 2)
 834           return (-EIO);
 835         return total;
 836       }
 837 
 838     } /* for (total = 0; total < count; ) */
 839 
 840     SCpnt->request.dev = -1;  /* Mark as not busy */
 841 
 842     return total;
 843 }
 844 
 845 
 846 /* Internal ioctl function */
 847 static int st_int_ioctl(struct inode * inode,struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 848              unsigned int cmd_in, unsigned long arg)
 849 {
 850    int dev = inode->i_rdev;
 851    int timeout = ST_LONG_TIMEOUT;
 852    long ltmp;
 853    int ioctl_result;
 854    unsigned char cmd[10];
 855    Scsi_Cmnd * SCpnt;
 856 
 857    dev = dev & 127;
 858 
 859    memset(cmd, 0, 10);
 860    switch (cmd_in) {
 861      case MTFSF:
 862      case MTFSFM:
 863        cmd[0] = SPACE;
 864        cmd[1] = 0x01; /* Space FileMarks */
 865        cmd[2] = (arg >> 16);
 866        cmd[3] = (arg >> 8);
 867        cmd[4] = arg;
 868 #ifdef DEBUG
 869        printk("st%d: Spacing tape forward %d files.\n", dev,
 870               cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
 871 #endif
 872        break; 
 873      case MTBSF:
 874      case MTBSFM:
 875        cmd[0] = SPACE;
 876        cmd[1] = 0x01; /* Space FileMarks */
 877        ltmp = (-arg);
 878        cmd[2] = (ltmp >> 16);
 879        cmd[3] = (ltmp >> 8);
 880        cmd[4] = ltmp;
 881 #ifdef DEBUG
 882        if (cmd[2] & 0x80)
 883          ltmp = 0xff000000;
 884        ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
 885        printk("st%d: Spacing tape backward %d files.\n", dev, (-ltmp));
 886 #endif
 887        break; 
 888       case MTFSR:
 889        cmd[0] = SPACE;
 890        cmd[1] = 0x00; /* Space Blocks */
 891        cmd[2] = (arg >> 16);
 892        cmd[3] = (arg >> 8);
 893        cmd[4] = arg;
 894 #ifdef DEBUG
 895        printk("st%d: Spacing tape forward %d blocks.\n", dev,
 896               cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
 897 #endif
 898        break; 
 899      case MTBSR:
 900        cmd[0] = SPACE;
 901        cmd[1] = 0x00; /* Space Blocks */
 902        ltmp = (-arg);
 903        cmd[2] = (ltmp >> 16);
 904        cmd[3] = (ltmp >> 8);
 905        cmd[4] = ltmp;
 906 #ifdef DEBUG
 907        if (cmd[2] & 0x80)
 908          ltmp = 0xff000000;
 909        ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
 910        printk("st%d: Spacing tape backward %d blocks.\n", dev, (-ltmp));
 911 #endif
 912        break; 
 913      case MTWEOF:
 914        if (scsi_tapes[dev].write_prot)
 915          return (-EACCES);
 916        cmd[0] = WRITE_FILEMARKS;
 917        cmd[2] = (arg >> 16);
 918        cmd[3] = (arg >> 8);
 919        cmd[4] = arg;
 920        timeout = ST_TIMEOUT;
 921 #ifdef DEBUG
 922        printk("st%d: Writing %d filemarks.\n", dev,
 923               cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
 924 #endif
 925        break; 
 926      case MTREW:
 927        cmd[0] = REZERO_UNIT;
 928 #ifdef ST_NOWAIT
 929        cmd[1] = 1;  /* Don't wait for completion */
 930        timeout = ST_TIMEOUT;
 931 #endif
 932 #ifdef DEBUG
 933        printk("st%d: Rewinding tape.\n", dev);
 934 #endif
 935        break; 
 936      case MTOFFL:
 937        cmd[0] = START_STOP;
 938 #ifdef ST_NOWAIT
 939        cmd[1] = 1;  /* Don't wait for completion */
 940        timeout = ST_TIMEOUT;
 941 #endif
 942 #ifdef DEBUG
 943        printk("st%d: Unloading tape.\n", dev);
 944 #endif
 945        break; 
 946      case MTNOP:
 947 #ifdef DEBUG
 948        printk("st%d: No op on tape.\n", dev);
 949 #endif
 950        return 0;  /* Should do something ? */
 951        break;
 952      case MTRETEN:
 953        cmd[0] = START_STOP;
 954 #ifdef ST_NOWAIT
 955        cmd[1] = 1;  /* Don't wait for completion */
 956        timeout = ST_TIMEOUT;
 957 #endif
 958        cmd[4] = 3;
 959 #ifdef DEBUG
 960        printk("st%d: Retensioning tape.\n", dev);
 961 #endif
 962        break; 
 963      case MTEOM:
 964        cmd[0] = SPACE;
 965        cmd[1] = 3;
 966 #ifdef DEBUG
 967        printk("st%d: Spacing to end of recorded medium.\n", dev);
 968 #endif
 969        break; 
 970      case MTERASE:
 971        if (scsi_tapes[dev].write_prot)
 972          return (-EACCES);
 973        cmd[0] = ERASE;
 974        cmd[1] = 1;  /* To the end of tape */
 975 #ifdef DEBUG
 976        printk("st%d: Erasing tape.\n", dev);
 977 #endif
 978        break;
 979      case MTSEEK:
 980        if (scsi_tapes[dev].device->scsi_level < SCSI_2) {
 981          cmd[0] = QFA_SEEK_BLOCK;
 982          cmd[2] = (arg >> 16);
 983          cmd[3] = (arg >> 8);
 984          cmd[4] = arg;
 985          cmd[5] = 0;
 986        }
 987        else {
 988          cmd[0] = SEEK_10;
 989          cmd[1] = 4;
 990          cmd[3] = (arg >> 24);
 991          cmd[4] = (arg >> 16);
 992          cmd[5] = (arg >> 8);
 993          cmd[6] = arg;
 994        }
 995 #ifdef ST_NOWAIT
 996        cmd[1] |= 1;  /* Don't wait for completion */
 997        timeout = ST_TIMEOUT;
 998 #endif
 999 #ifdef DEBUG
1000        printk("st%d: Seeking tape to block %d.\n", dev, arg);
1001 #endif
1002        break;
1003      case MTSETBLK:  /* Set block length */
1004      case MTSETDENSITY: /* Set tape density */
1005        if (scsi_tapes[dev].dirty || scsi_tapes[dev].buffer->buffer_bytes != 0)
1006          return (-EIO);   /* Not allowed if data in buffer */
1007        if (cmd_in == MTSETBLK &&
1008            (arg < scsi_tapes[dev].min_block || arg > scsi_tapes[dev].max_block ||
1009             arg > ST_BUFFER_SIZE)) {
1010          printk("st%d: Illegal block size.\n", dev);
1011          return (-EINVAL);
1012        }
1013        cmd[0] = MODE_SELECT;
1014        cmd[4] = 12;
1015 
1016        memset(scsi_tapes[dev].buffer->b_data, 0, 12);
1017        scsi_tapes[dev].buffer->b_data[2] = 0x10;  /* buffered mode */
1018        scsi_tapes[dev].buffer->b_data[3] = 8;     /* block descriptor length */
1019        if (cmd_in == MTSETBLK)
1020          ltmp = arg;
1021        else {
1022          scsi_tapes[dev].buffer->b_data[4] = arg;
1023          ltmp = scsi_tapes[dev].block_size;
1024        }
1025        scsi_tapes[dev].buffer->b_data[9] = (ltmp >> 16);
1026        scsi_tapes[dev].buffer->b_data[10] = (ltmp >> 8);
1027        scsi_tapes[dev].buffer->b_data[11] = ltmp;
1028        timeout = ST_TIMEOUT;
1029 #ifdef DEBUG
1030        if (cmd_in == MTSETBLK)
1031          printk("st%d: Setting block size to %d bytes.\n", dev,
1032                 scsi_tapes[dev].buffer->b_data[9] * 65536 +
1033                 scsi_tapes[dev].buffer->b_data[10] * 256 +
1034                 scsi_tapes[dev].buffer->b_data[11]);
1035        else
1036          printk("st%d: Setting density code to %x.\n", dev,
1037                 scsi_tapes[dev].buffer->b_data[4]);
1038 #endif
1039        break;
1040      default:
1041        printk("st%d: Unknown st_ioctl command %x.\n", dev, cmd_in);
1042        return (-ENOSYS);
1043      }
1044 
1045    SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1);
1046    SCpnt->sense_buffer[0] = 0;
1047    SCpnt->request.dev = dev;
1048    scsi_do_cmd(SCpnt,
1049                (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data, ST_BLOCK_SIZE,
1050                st_sleep_done, timeout, MAX_RETRIES);
1051 
1052    if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
1053 
1054    SCpnt->request.dev = -1;  /* Mark as not busy */
1055 
1056    ioctl_result = st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);
1057 
1058    if (!ioctl_result) {
1059      if (cmd_in == MTBSFM)
1060        ioctl_result = st_int_ioctl(inode, file, MTFSF, 1);
1061      else if (cmd_in == MTFSFM)
1062        ioctl_result = st_int_ioctl(inode, file, MTBSF, 1);
1063      else if (cmd_in == MTSETBLK) {
1064        scsi_tapes[dev].block_size = arg;
1065        scsi_tapes[dev].buffer->buffer_blocks =
1066          ST_BUFFER_SIZE / scsi_tapes[dev].block_size;
1067        scsi_tapes[dev].buffer->buffer_size =
1068          scsi_tapes[dev].buffer->buffer_blocks * scsi_tapes[dev].block_size;
1069        scsi_tapes[dev].buffer->buffer_bytes =
1070          scsi_tapes[dev].buffer->read_pointer = 0;
1071      }
1072      if (cmd_in == MTEOM || cmd_in == MTWEOF) {
1073        scsi_tapes[dev].eof = 2;
1074        scsi_tapes[dev].eof_hit = 0;
1075      }
1076      else if (cmd_in != MTSETBLK && cmd_in != MTNOP) {
1077        scsi_tapes[dev].eof = 0;
1078        scsi_tapes[dev].eof_hit = 0;
1079      }
1080    }
1081 
1082    return ioctl_result ;
1083 }
1084 
1085 
1086 
1087 /* The ioctl command */
1088 static int st_ioctl(struct inode * inode,struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
1089              unsigned int cmd_in, unsigned long arg)
1090 {
1091    int dev = inode->i_rdev;
1092    int i, cmd, result;
1093    struct mtop mtc;
1094    struct mtpos mt_pos;
1095    unsigned char scmd[10];
1096    Scsi_Cmnd *SCpnt;
1097 
1098    dev = dev & 127;
1099 #ifdef DEBUG
1100    if (!scsi_tapes[dev].in_use) {
1101      printk("st%d: Incorrect device.\n", dev);
1102      return (-EIO);
1103    }
1104 #endif
1105 
1106    cmd = cmd_in & IOCCMD_MASK;
1107    if (cmd == (MTIOCTOP & IOCCMD_MASK)) {
1108 
1109      if (((cmd_in & IOCSIZE_MASK) >> IOCSIZE_SHIFT) != sizeof(mtc))
1110        return (-EINVAL);
1111 
1112      i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(mtc));
1113      if (i)
1114         return i;
1115 
1116      memcpy_fromfs((char *) &mtc, (char *)arg, sizeof(struct mtop));
1117 
1118      i = flush_buffer(inode, file, mtc.mt_op == MTSEEK ||
1119                       mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
1120                       mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM);
1121      if (i < 0)
1122        return i;
1123 
1124      return st_int_ioctl(inode, file, mtc.mt_op, mtc.mt_count);
1125    }
1126    else if (cmd == (MTIOCGET & IOCCMD_MASK)) {
1127 
1128      if (((cmd_in & IOCSIZE_MASK) >> IOCSIZE_SHIFT) != sizeof(struct mtget))
1129        return (-EINVAL);
1130      i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct mtget));
1131      if (i)
1132        return i;
1133 
1134      memcpy_tofs((char *)arg, (char *)scsi_tapes[dev].buffer->mt_status,
1135                  sizeof(struct mtget));
1136      return 0;
1137    }
1138    else if (cmd == (MTIOCPOS & IOCCMD_MASK)) {
1139 #ifdef DEBUG
1140      printk("st%d: get tape position.\n", dev);
1141 #endif
1142      if (((cmd_in & IOCSIZE_MASK) >> IOCSIZE_SHIFT) != sizeof(struct mtpos))
1143        return (-EINVAL);
1144 
1145      i = flush_buffer(inode, file, 0);
1146      if (i < 0)
1147        return i;
1148 
1149      i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct mtpos));
1150      if (i)
1151        return i;
1152 
1153      SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1);
1154 
1155      SCpnt->sense_buffer[0]=0;
1156      memset (scmd, 0, 10);
1157      if (scsi_tapes[dev].device->scsi_level < SCSI_2) {
1158        scmd[0] = QFA_REQUEST_BLOCK;
1159        scmd[4] = 3;
1160      }
1161      else {
1162        scmd[0] = READ_POSITION;
1163        scmd[1] = 1;
1164      }
1165      SCpnt->request.dev = dev;
1166      SCpnt->sense_buffer[0] = 0;
1167      scsi_do_cmd(SCpnt,
1168                  (void *) scmd, (void *) scsi_tapes[dev].buffer->b_data,
1169                  ST_BLOCK_SIZE, st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
1170 
1171      if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
1172      
1173      if (SCpnt->result || SCpnt->sense_buffer[0]) {
1174        mt_pos.mt_blkno = (-1);
1175 #ifdef DEBUG
1176        printk("st%d: Can't read tape position.\n", dev);
1177 #endif
1178        result = (-EIO);
1179      }
1180      else {
1181        result = 0;
1182        if (scsi_tapes[dev].device->scsi_level < SCSI_2)
1183          mt_pos.mt_blkno = (scsi_tapes[dev].buffer->b_data[0] << 16) 
1184            + (scsi_tapes[dev].buffer->b_data[1] << 8) 
1185              + scsi_tapes[dev].buffer->b_data[2];
1186        else
1187          mt_pos.mt_blkno = (scsi_tapes[dev].buffer->b_data[4] << 24)
1188            + (scsi_tapes[dev].buffer->b_data[5] << 16) 
1189              + (scsi_tapes[dev].buffer->b_data[6] << 8) 
1190                + scsi_tapes[dev].buffer->b_data[7];
1191 
1192      }
1193 
1194      SCpnt->request.dev = -1;  /* Mark as not busy */
1195 
1196      memcpy_tofs((char *)arg, (char *) (&mt_pos), sizeof(struct mtpos));
1197      return result;
1198    }
1199    else
1200      return scsi_ioctl(scsi_tapes[dev].device, cmd_in, (void *) arg);
1201 }
1202 
1203 
1204 
1205 static struct file_operations st_fops = {
1206    NULL,            /* lseek - default */
1207    st_read,         /* read - general block-dev read */
1208    st_write,        /* write - general block-dev write */
1209    NULL,            /* readdir - bad */
1210    NULL,            /* select */
1211    st_ioctl,        /* ioctl */
1212    NULL,            /* mmap */
1213    scsi_tape_open,  /* open */
1214    scsi_tape_close  /* release */
1215 };
1216 
1217 void st_attach(Scsi_Device * SDp){
     /* [previous][next][first][last][top][bottom][index][help] */
1218   scsi_tapes[NR_ST++].device = SDp;
1219   if(NR_ST > MAX_ST) panic ("scsi_devices corrupt (st)");
1220 };
1221 
1222 unsigned long st_init1(unsigned long mem_start, unsigned long mem_end){
     /* [previous][next][first][last][top][bottom][index][help] */
1223   scsi_tapes = (Scsi_Tape *) mem_start;
1224   mem_start += MAX_ST * sizeof(Scsi_Tape);
1225   return mem_start;
1226 };
1227 
1228 /* Driver initialization */
1229 unsigned long st_init(unsigned long mem_start, unsigned long mem_end)
     /* [previous][next][first][last][top][bottom][index][help] */
1230 {
1231   int i;
1232 
1233   if (register_chrdev(MAJOR_NR,"st",&st_fops)) {
1234     printk("Unable to get major %d for SCSI tapes\n",MAJOR_NR);
1235     return mem_start;
1236   }
1237   if (NR_ST == 0) return mem_start;
1238 
1239 #ifdef DEBUG
1240   printk("st: Init tape.\n");
1241 #endif
1242 
1243   for (i=0; i < NR_ST; ++i) {
1244     scsi_tapes[i].capacity = 0xfffff;
1245     scsi_tapes[i].dirty = 0;
1246     scsi_tapes[i].rw = 0;
1247     scsi_tapes[i].eof = 0;
1248     scsi_tapes[i].waiting = NULL;
1249     scsi_tapes[i].in_use = 0;
1250   }
1251 
1252 
1253   /* Allocate the buffers */
1254   if (NR_ST == 1)
1255     st_nbr_buffers = 1;
1256   else
1257     st_nbr_buffers = 2;
1258   for (i=0; i < st_nbr_buffers; i++) {
1259     st_buffers[i] = (ST_buffer *) mem_start;
1260 #ifdef DEBUG
1261     printk("st: Buffer address: %x\n", st_buffers[i]);
1262 #endif
1263     mem_start += sizeof(ST_buffer) - 1 + ST_BUFFER_BLOCKS * ST_BLOCK_SIZE;
1264     st_buffers[i]->mt_status = (struct mtget *) mem_start;
1265     mem_start += sizeof(struct mtget);
1266     st_buffers[i]->in_use = 0;
1267     st_buffers[i]->writing = 0;
1268 
1269     /* "generic" status */
1270     memset((void *) st_buffers[i]->mt_status, 0, sizeof(struct mtget));
1271     st_buffers[i]->mt_status->mt_type = MT_ISSCSI1;
1272   }
1273 
1274   return mem_start;
1275 }

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