⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 st.c

📁 LINUX 1.0 内核c源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
      printk(
	"st%d: Density %x, tape length: %x, blocksize: %d, drv buffer: %d\n",
	     dev, STp->density, (STp->buffer)->b_data[5] * 65536 +
	     (STp->buffer)->b_data[6] * 256 + (STp->buffer)->b_data[7],
	     STp->block_size, STp->drv_buffer);
#endif
      if (STp->block_size > ST_BUFFER_SIZE) {
	printk("st%d: Blocksize %d too large for buffer.\n", dev,
	       STp->block_size);
	(STp->buffer)->in_use = 0;
	STp->in_use = 0;
	return (-EIO);
      }

    }
    else
      STp->block_size = ST_BLOCK_SIZE;

    if (STp->block_size > 0) {
      (STp->buffer)->buffer_blocks = ST_BUFFER_SIZE / STp->block_size;
      (STp->buffer)->buffer_size =
	(STp->buffer)->buffer_blocks * STp->block_size;
    }
    else {
      (STp->buffer)->buffer_blocks = 1;
      (STp->buffer)->buffer_size = ST_BUFFER_SIZE;
    }
    (STp->buffer)->buffer_bytes = (STp->buffer)->read_pointer = 0;

#ifdef DEBUG
    printk("st%d: Block size: %d, buffer size: %d (%d blocks).\n", dev,
	   STp->block_size, (STp->buffer)->buffer_size,
	   (STp->buffer)->buffer_blocks);
#endif

    if ((STp->buffer)->b_data[2] & 0x80) {
      STp->write_prot = 1;
#ifdef DEBUG
      printk( "st%d: Write protected\n", dev);
#endif
    }

    return 0;
}


/* Close the device*/
	static void
scsi_tape_close(struct inode * inode, struct file * filp)
{
    int dev;
    int result;
    int rewind;
    static unsigned char cmd[10];
    Scsi_Cmnd * SCpnt;
    Scsi_Tape * STp;
   
    dev = MINOR(inode->i_rdev);
    rewind = (dev & 0x80) == 0;
    dev = dev & 127;
    STp = &(scsi_tapes[dev]);

    if ( STp->rw == ST_WRITING) {

      result = flush_write_buffer(dev);

#ifdef DEBUG
      printk("st%d: File length %d bytes.\n", dev, filp->f_pos);
#endif

      if (result == 0 || result == (-ENOSPC)) {
	SCpnt = allocate_device(NULL, (STp->device)->index, 1);

	SCpnt->sense_buffer[0] = 0;
	memset(cmd, 0, 10);
	cmd[0] = WRITE_FILEMARKS;
	cmd[4] = 1;
	SCpnt->request.dev = dev;
	scsi_do_cmd( SCpnt,
		    (void *) cmd, (void *) (STp->buffer)->b_data,
		    ST_BLOCK_SIZE, st_sleep_done, ST_TIMEOUT, MAX_RETRIES);

	if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );

	if ((STp->buffer)->last_result_fatal != 0)
	  printk("st%d: Error on write filemark.\n", dev);

	SCpnt->request.dev = -1;  /* Mark as not busy */
      }

#ifdef DEBUG
      printk("st%d: Buffer flushed, EOF written\n", dev);
#endif
    }
    else if (!rewind) {
#ifndef ST_IN_FILE_POS
      if ((STp->eof == ST_FM) && !STp->eof_hit)
	st_int_ioctl(inode, filp, MTBSF, 1); /* Back over the EOF hit */
#else
      flush_buffer(inode, filp, 0);
#endif
    }

    if (rewind)
      st_int_ioctl(inode, filp, MTREW, 1);

    (STp->buffer)->in_use = 0;
    STp->in_use = 0;

    return;
}


/* Write command */
	static int
st_write(struct inode * inode, struct file * filp, char * buf, int count)
{
    int dev;
    int total, do_count, blks, retval, transfer;
    int write_threshold;
    static unsigned char cmd[10];
    char *b_point;
    Scsi_Cmnd * SCpnt;
    Scsi_Tape * STp;

    dev = MINOR(inode->i_rdev) & 127;
    STp = &(scsi_tapes[dev]);
#ifdef DEBUG
    if (!STp->in_use) {
      printk("st%d: Incorrect device.\n", dev);
      return (-EIO);
    }
#endif

    if (STp->write_prot)
      return (-EACCES);

    if (STp->block_size == 0 && count > ST_BUFFER_SIZE)
      return (-EOVERFLOW);

    if (STp->rw == ST_READING) {
      retval = flush_buffer(inode, filp, 0);
      if (retval)
	return retval;
      STp->rw = ST_WRITING;
    }

#if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS
    if ((STp->buffer)->writing) {
      write_behind_check(dev);
      if ((STp->buffer)->last_result_fatal) {
#ifdef DEBUG
	printk("st%d: Async write error %x.\n", dev,
	       (STp->buffer)->last_result);
#endif
	if ((STp->buffer)->last_result == INT_MAX) {
	  retval = (-ENOSPC);  /* All has been written */
	  STp->eof = ST_EOM_OK;
	}
	else
	  retval = (-EIO);
	return retval;
      }
    }
#endif

    if (STp->eof == ST_EOM_OK)
      return (-ENOSPC);
    else if (STp->eof == ST_EOM_ERROR)
      return (-EIO);

#ifdef ST_NO_DELAYED_WRITES
    if (STp->block_size != 0 && (count % STp->block_size) != 0)
      return (-EIO);   /* Write must be integral number of blocks */
    write_threshold = 1;
#else
    write_threshold = (STp->buffer)->buffer_size;
#endif

    SCpnt = allocate_device(NULL, (STp->device)->index, 1);

    total = count;

    memset(cmd, 0, 10);
    cmd[0] = WRITE_6;
    cmd[1] = (STp->block_size != 0);

    STp->rw = ST_WRITING;

    b_point = buf;
    while(
#if ST_WRITE_THRESHOLD_BLOCKS  < ST_BUFFER_BLOCKS
	  STp->block_size != 0 &&
	  ((STp->buffer)->buffer_bytes + count) >
	  write_threshold)
#else
	  (STp->block_size == 0 && count > 0) ||
	  ((STp->buffer)->buffer_bytes + count) >=
	  write_threshold)
#endif
    {
      if (STp->block_size == 0)
	do_count = count;
      else {
	do_count = (STp->buffer)->buffer_size - (STp->buffer)->buffer_bytes;
	if (do_count > count)
	  do_count = count;
      }
      memcpy_fromfs((STp->buffer)->b_data +
		    (STp->buffer)->buffer_bytes, b_point, do_count);

      if (STp->block_size == 0)
        blks = do_count;
      else
	blks = ((STp->buffer)->buffer_bytes + do_count) /
	  STp->block_size;
      cmd[2] = blks >> 16;
      cmd[3] = blks >> 8;
      cmd[4] = blks;
      SCpnt->sense_buffer[0] = 0;
      SCpnt->request.dev = dev;
      scsi_do_cmd (SCpnt,
		   (void *) cmd, (STp->buffer)->b_data,
		   (STp->buffer)->buffer_size,
		   st_sleep_done, ST_TIMEOUT, MAX_RETRIES);

      if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );

      if ((STp->buffer)->last_result_fatal != 0) {
#ifdef DEBUG
	printk("st%d: Error on write:\n", dev);
#endif
	if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
	    (SCpnt->sense_buffer[2] & 0x40)) {
	  if (STp->block_size != 0 && (SCpnt->sense_buffer[0] & 0x80) != 0)
	    transfer = (SCpnt->sense_buffer[3] << 24) |
	      (SCpnt->sense_buffer[4] << 16) |
		(SCpnt->sense_buffer[5] << 8) | SCpnt->sense_buffer[6];
	  else if (STp->block_size == 0 &&
		   (SCpnt->sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW)
	    transfer = do_count;
	  else
	    transfer = 0;
	  if (STp->block_size != 0)
	    transfer *= STp->block_size;
	  if (transfer <= do_count) {
	    filp->f_pos += do_count - transfer;
	    count -= do_count - transfer;
	    STp->eof = ST_EOM_OK;
	    retval = (-ENOSPC); /* EOM within current request */
#ifdef DEBUG
	    printk("st%d: EOM with %d bytes unwritten.\n",
		   dev, transfer);
#endif
	  }
	  else {
	    STp->eof = ST_EOM_ERROR;
	    retval = (-EIO); /* EOM for old data */
#ifdef DEBUG
	    printk("st%d: EOM with lost data.\n", dev);
#endif
	  }
	}
	else
	  retval = (-EIO);

	SCpnt->request.dev = -1;  /* Mark as not busy */
	(STp->buffer)->buffer_bytes = 0;
	STp->dirty = 0;
	if (count < total)
	  return total - count;
	else
	  return retval;
      }
      filp->f_pos += do_count;
      b_point += do_count;
      count -= do_count;
      (STp->buffer)->buffer_bytes = 0;
      STp->dirty = 0;
    }
    if (count != 0) {
      STp->dirty = 1;
      memcpy_fromfs((STp->buffer)->b_data +
		    (STp->buffer)->buffer_bytes,b_point,count);
      filp->f_pos += count;
      (STp->buffer)->buffer_bytes += count;
      count = 0;
    }

    if ((STp->buffer)->last_result_fatal != 0) {
      SCpnt->request.dev = -1;
      return (STp->buffer)->last_result_fatal;
    }

#if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS
    if ((STp->buffer)->buffer_bytes >= ST_WRITE_THRESHOLD ||
	STp->block_size == 0) {
      /* Schedule an asynchronous write */
      if (STp->block_size == 0)
	(STp->buffer)->writing = (STp->buffer)->buffer_bytes;
      else
	(STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
	  STp->block_size) * STp->block_size;
      STp->dirty = 0;

      if (STp->block_size == 0)
	blks = (STp->buffer)->writing;
      else
	blks = (STp->buffer)->writing / STp->block_size;
      cmd[2] = blks >> 16;
      cmd[3] = blks >> 8;
      cmd[4] = blks;
      SCpnt->result = (STp->buffer)->last_result = -1;
      SCpnt->sense_buffer[0] = 0;
      SCpnt->request.dev = dev;
      scsi_do_cmd (SCpnt,
		   (void *) cmd, (STp->buffer)->b_data,
		   (STp->buffer)->writing,
		   st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
    }
    else
#endif
      SCpnt->request.dev = -1;  /* Mark as not busy */

    return( total);
}   


/* Read command */
	static int
st_read(struct inode * inode, struct file * filp, char * buf, int count)
{
    int dev;
    int total;
    int transfer, blks, bytes;
    static unsigned char cmd[10];
    Scsi_Cmnd * SCpnt;
    Scsi_Tape * STp;

    dev = MINOR(inode->i_rdev) & 127;
    STp = &(scsi_tapes[dev]);
#ifdef DEBUG
    if (!STp->in_use) {
      printk("st%d: Incorrect device.\n", dev);
      return (-EIO);
    }
#endif

    if (STp->block_size == 0 && count > ST_BUFFER_SIZE)
      return (-EOVERFLOW);

    if (STp->rw == ST_WRITING) {
      transfer = flush_buffer(inode, filp, 0);
      if (transfer)
	return transfer;
      STp->rw = ST_READING;
    }

#ifdef DEBUG
    if (STp->eof != ST_NOEOF)
      printk("st%d: EOF flag up. Bytes %d\n", dev,
	     (STp->buffer)->buffer_bytes);
#endif
    if (((STp->buffer)->buffer_bytes == 0) &&
	STp->eof == ST_EOM_OK)  /* EOM or Blank Check */
      return (-EIO);

    STp->rw = ST_READING;

    SCpnt = allocate_device(NULL, (STp->device)->index, 1);

    for (total = 0; total < count; ) {

      if ((STp->buffer)->buffer_bytes == 0 &&
	  STp->eof == ST_NOEOF) {

	memset(cmd, 0, 10);
	cmd[0] = READ_6;
	cmd[1] = (STp->block_size != 0);
	if (STp->block_size == 0)
	  blks = bytes = count;
	else {
	  blks = (STp->buffer)->buffer_blocks;
	  bytes = blks * STp->block_size;
	}
	cmd[2] = blks >> 16;
	cmd[3] = blks >> 8;
	cmd[4] = blks;

	SCpnt->sense_buffer[0] = 0;
	SCpnt->request.dev = dev;
	scsi_do_cmd (SCpnt,
		     (void *) cmd, (STp->buffer)->b_data,
		     (STp->buffer)->buffer_size,
		     st_sleep_done, ST_TIMEOUT, MAX_RETRIES);

	if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );

	(STp->buffer)->read_pointer = 0;
	STp->eof_hit = 0;

	if ((STp->buffer)->last_result_fatal) {
#ifdef DEBUG
	  printk("st%d: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n", dev,
		 SCpnt->sense_buffer[0], SCpnt->sense_buffer[1],
		 SCpnt->sense_buffer[2], SCpnt->sense_buffer[3],
		 SCpnt->sense_buffer[4], SCpnt->sense_buffer[5],
		 SCpnt->sense_buffer[6], SCpnt->sense_buffer[7]);
#endif
	  if ((SCpnt->sense_buffer[0] & 0x70) == 0x70) { /* extended sense */

	    if ((SCpnt->sense_buffer[2] & 0xe0) != 0) { /* EOF, EOM, or ILI */

	      if ((SCpnt->sense_buffer[0] & 0x80) != 0)
		transfer = (SCpnt->sense_buffer[3] << 24) |
		  (SCpnt->sense_buffer[4] << 16) |
		    (SCpnt->sense_buffer[5] << 8) | SCpnt->sense_buffer[6];
	      else
		transfer = 0;
	      if (STp->block_size == 0 &&
		  (SCpnt->sense_buffer[2] & 0x0f) == MEDIUM_ERROR)
		transfer = bytes;

	      if (SCpnt->sense_buffer[2] & 0x20) {
		if (STp->block_size == 0) {
		  if (transfer <= 0)
		    transfer = 0;
		  (STp->buffer)->buffer_bytes = count - transfer;
		}
		else {
		  printk("st%d: Incorrect block size.\n", dev);
		  SCpnt->request.dev = -1;  /* Mark as not busy */
		  return (-EIO);
		}
	      }
	      else if (SCpnt->sense_buffer[2] & 0x40) {
		STp->eof = ST_EOM_OK;
		if (STp->block_size == 0)
		  (STp->buffer)->buffer_bytes = count - transfer;
		else
		  (STp->buffer)->buffer_bytes =
		    ((STp->buffer)->buffer_blocks - transfer) *
		      STp->block_size;
#ifdef DEBUG
		printk("st%d: EOM detected (%d bytes read).\n", dev,
		       (STp->buffer)->buffer_bytes);
#endif
	      }
	      else if (SCpnt->sense_buffer[2] & 0x80) {
		STp->eof = ST_FM;
		if (STp->block_size == 0)
		  (STp->buffer)->buffer_bytes = 0;
		else
		  (STp->buffer)->buffer_bytes =
		    ((STp->buffer)->buffer_blocks - transfer) *
		      STp->block_size;
#ifdef DEBUG
		printk(
		 "st%d: EOF detected (%d bytes read, transferred %d bytes).\n",
		       dev, (STp->buffer)->buffer_bytes, total);
#endif
	      } /* end of EOF, EOM, ILI test */
	    }
	    else { /* nonzero sense key */
#ifdef DEBUG
	      printk("st%d: Tape error while reading.\n", dev);
#endif
	      SCpnt->request.dev = -1;
	      if (total)
		return total;
	      else
		return -EIO;
	    }
	  }
	  else {
	    transfer = (STp->buffer)->last_result_fatal;
	    SCpnt->request.dev = -1;  /* Mark as not busy */
	    return transfer;
	  }
	}
	else /* Read successful */
	  (STp->buffer)->buffer_bytes = bytes;

      } /* if ((STp->buffer)->buffer_bytes == 0 &&
	   STp->eof == ST_NOEOF) */

      if ((STp->buffer)->buffer_bytes > 0) {
#ifdef DEBUG
	if (STp->eof != ST_NOEOF)
	  printk("st%d: EOF up. Left %d, needed %d.\n", dev,
		 (STp->buffer)->buffer_bytes, count - total);
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -