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

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