📄 st.c
字号:
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 + -