root/drivers/scsi/st.c

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

DEFINITIONS

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

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