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

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