Commit 0098b69e authored by Linus Torvalds's avatar Linus Torvalds

Merge http://linux-scsi.bkbits.net/scsi-for-linus-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 43d332b0 e5064e24
...@@ -485,13 +485,6 @@ int scsi_register_host(Scsi_Host_Template *shost_tp) ...@@ -485,13 +485,6 @@ int scsi_register_host(Scsi_Host_Template *shost_tp)
BUG_ON(!shost_tp->detect); BUG_ON(!shost_tp->detect);
if (!shost_tp->max_sectors) {
printk(KERN_WARNING
"scsi HBA driver %s didn't set max_sectors, "
"please fix the template\n", shost_tp->name);
shost_tp->max_sectors = 1024;
}
if (!shost_tp->release) { if (!shost_tp->release) {
printk(KERN_WARNING printk(KERN_WARNING
"scsi HBA driver %s didn't set a release method, " "scsi HBA driver %s didn't set a release method, "
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
*/ */
static const char * cvsid = "$Id: osst.c,v 1.65 2001/11/11 20:38:56 riede Exp $"; static const char * cvsid = "$Id: osst.c,v 1.65 2001/11/11 20:38:56 riede Exp $";
const char * osst_version = "0.99.0p3"; const char * osst_version = "0.99.0p5";
/* The "failure to reconnect" firmware bug */ /* The "failure to reconnect" firmware bug */
#define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/ #define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
...@@ -60,7 +60,6 @@ const char * osst_version = "0.99.0p3"; ...@@ -60,7 +60,6 @@ const char * osst_version = "0.99.0p3";
in the drivers are more widely classified, this may be changed to KERN_DEBUG. */ in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
#define OSST_DEB_MSG KERN_NOTICE #define OSST_DEB_MSG KERN_NOTICE
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
#include <scsi/scsi_ioctl.h> #include <scsi/scsi_ioctl.h>
...@@ -85,7 +84,7 @@ MODULE_PARM(max_dev, "i"); ...@@ -85,7 +84,7 @@ MODULE_PARM(max_dev, "i");
MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)"); MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
MODULE_PARM(write_threshold_kbs, "i"); MODULE_PARM(write_threshold_kbs, "i");
MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 30)"); MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
MODULE_PARM(max_sg_segs, "i"); MODULE_PARM(max_sg_segs, "i");
MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)"); MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
...@@ -170,8 +169,8 @@ struct Scsi_Device_Template osst_template = ...@@ -170,8 +169,8 @@ struct Scsi_Device_Template osst_template =
.attach = osst_attach, .attach = osst_attach,
.detach = osst_detach, .detach = osst_detach,
.scsi_driverfs_driver = { .scsi_driverfs_driver = {
.name = "osst", .name = "osst",
}, }
}; };
static int osst_int_ioctl(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, unsigned int cmd_in,unsigned long arg); static int osst_int_ioctl(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, unsigned int cmd_in,unsigned long arg);
...@@ -221,7 +220,7 @@ static int osst_chk_result(OS_Scsi_Tape * STp, Scsi_Request * SRpnt) ...@@ -221,7 +220,7 @@ static int osst_chk_result(OS_Scsi_Tape * STp, Scsi_Request * SRpnt)
if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n", if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
name, scode, sense[12], sense[13]); name, scode, sense[12], sense[13]);
if (driver_byte(result) & DRIVER_SENSE) if (driver_byte(result) & DRIVER_SENSE)
print_req_sense("osst", SRpnt); print_req_sense("osst ", SRpnt);
} }
// else // else
#endif #endif
...@@ -543,8 +542,6 @@ static int osst_verify_frame(OS_Scsi_Tape * STp, int frame_seq_number, int quiet ...@@ -543,8 +542,6 @@ static int osst_verify_frame(OS_Scsi_Tape * STp, int frame_seq_number, int quiet
STp->first_frame_position); STp->first_frame_position);
goto err_out; goto err_out;
} }
// STp->frame_in_buffer = 1;
if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) { if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
if (!quiet) if (!quiet)
#if DEBUG #if DEBUG
...@@ -749,7 +746,7 @@ static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt) ...@@ -749,7 +746,7 @@ static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
Scsi_Request * SRpnt; Scsi_Request * SRpnt;
int result = 0; int result = 0;
int delay = OSST_WAIT_LONG_WRITE_COMPLETE; int delay = OSST_WAIT_WRITE_COMPLETE;
#if DEBUG #if DEBUG
char *name = tape_name(STp); char *name = tape_name(STp);
...@@ -763,17 +760,14 @@ static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt) ...@@ -763,17 +760,14 @@ static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_WRITE_RETRIES, TRUE); SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_WRITE_RETRIES, TRUE);
*aSRpnt = SRpnt; *aSRpnt = SRpnt;
if (!SRpnt) return (-EBUSY); if (!SRpnt) return (-EBUSY);
//printk(OSST_DEB_MSG "%s:X: Write filemark returned %x:%02x:%02x:%02x\n",dev,STp->buffer->syscall_result,SRpnt->sr_sense_buffer[2] & 0x0f,SRpnt->sr_sense_buffer[12],SRpnt->sr_sense_buffer[13]);
if (STp->buffer->syscall_result) { if (STp->buffer->syscall_result) {
if ((SRpnt->sr_sense_buffer[2] & 0x0f) == 2 && SRpnt->sr_sense_buffer[12] == 4) { if ((SRpnt->sr_sense_buffer[2] & 0x0f) == 2 && SRpnt->sr_sense_buffer[12] == 4) {
if (SRpnt->sr_sense_buffer[13] == 8) { if (SRpnt->sr_sense_buffer[13] == 8) {
//printk(OSST_DEB_MSG "%s:X: Long initial delay\n", dev);
delay = OSST_WAIT_LONG_WRITE_COMPLETE; delay = OSST_WAIT_LONG_WRITE_COMPLETE;
} }
} else } else
result = osst_write_error_recovery(STp, aSRpnt, 0); result = osst_write_error_recovery(STp, aSRpnt, 0);
} }
//printk(OSST_DEB_MSG "%s:X: Entering wait ready (%d)\n",dev,delay);
result |= osst_wait_ready(STp, aSRpnt, 5 * 60, delay); result |= osst_wait_ready(STp, aSRpnt, 5 * 60, delay);
STp->ps[STp->partition].rw = OS_WRITING_COMPLETE; STp->ps[STp->partition].rw = OS_WRITING_COMPLETE;
...@@ -1708,12 +1702,7 @@ static int osst_space_over_filemarks_backward(OS_Scsi_Tape * STp, Scsi_Request * ...@@ -1708,12 +1702,7 @@ static int osst_space_over_filemarks_backward(OS_Scsi_Tape * STp, Scsi_Request *
name, last_mark_ppos); name, last_mark_ppos);
return (-EIO); return (-EIO);
} }
if (mt_op == MTBSFM) { goto found;
STp->frame_seq_number++;
STp->frame_in_buffer = 0;
STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
}
return 0;
} }
#if DEBUG #if DEBUG
printk(OSST_DEB_MSG "%s:D: Reverting to scan filemark backwards\n", name); printk(OSST_DEB_MSG "%s:D: Reverting to scan filemark backwards\n", name);
...@@ -1741,10 +1730,13 @@ static int osst_space_over_filemarks_backward(OS_Scsi_Tape * STp, Scsi_Request * ...@@ -1741,10 +1730,13 @@ static int osst_space_over_filemarks_backward(OS_Scsi_Tape * STp, Scsi_Request *
return (-EIO); return (-EIO);
} }
} }
found:
if (mt_op == MTBSFM) { if (mt_op == MTBSFM) {
STp->frame_seq_number++; STp->frame_seq_number++;
STp->frame_in_buffer = 0; STp->frame_in_buffer = 0;
STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt); STp->buffer->buffer_bytes = 0;
STp->buffer->read_pointer = 0;
STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
} }
return 0; return 0;
} }
...@@ -1797,8 +1789,10 @@ static int osst_space_over_filemarks_forward_slow(OS_Scsi_Tape * STp, Scsi_Reque ...@@ -1797,8 +1789,10 @@ static int osst_space_over_filemarks_forward_slow(OS_Scsi_Tape * STp, Scsi_Reque
} }
if (mt_op == MTFSF) { if (mt_op == MTFSF) {
STp->frame_seq_number++; STp->frame_seq_number++;
STp->frame_in_buffer = 0; STp->frame_in_buffer = 0;
STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt); STp->buffer->buffer_bytes = 0;
STp->buffer->read_pointer = 0;
STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
} }
return 0; return 0;
} }
...@@ -1944,9 +1938,10 @@ static int osst_space_over_filemarks_forward_fast(OS_Scsi_Tape * STp, Scsi_Reque ...@@ -1944,9 +1938,10 @@ static int osst_space_over_filemarks_forward_fast(OS_Scsi_Tape * STp, Scsi_Reque
} }
if (mt_op == MTFSF) { if (mt_op == MTFSF) {
STp->frame_seq_number++; STp->frame_seq_number++;
STp->frame_in_buffer = 0; STp->frame_in_buffer = 0;
STp->buffer->buffer_bytes = 0;
STp->buffer->read_pointer = 0; STp->buffer->read_pointer = 0;
STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt); STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
} }
return 0; return 0;
} }
...@@ -3215,8 +3210,8 @@ static ssize_t osst_write(struct file * filp, const char * buf, size_t count, lo ...@@ -3215,8 +3210,8 @@ static ssize_t osst_write(struct file * filp, const char * buf, size_t count, lo
/* Write must be integral number of blocks */ /* Write must be integral number of blocks */
if (STp->block_size != 0 && (count % STp->block_size) != 0) { if (STp->block_size != 0 && (count % STp->block_size) != 0) {
printk(KERN_ERR "%s:E: Write (%ld bytes) not multiple of tape block size (%d%c).\n", printk(KERN_ERR "%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
name, (unsigned long)count, STp->block_size<1024? name, count, STp->block_size<1024?
STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k'); STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
retval = (-EINVAL); retval = (-EINVAL);
goto out; goto out;
...@@ -4140,8 +4135,14 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned i ...@@ -4140,8 +4135,14 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned i
if (cmd_in == MTEOM) if (cmd_in == MTEOM)
STps->eof = ST_EOD; STps->eof = ST_EOD;
else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) {
ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num - 1); ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num-1);
STps->drv_block++;
STp->logical_blk_num++;
STp->frame_seq_number++;
STp->frame_in_buffer = 0;
STp->buffer->read_pointer = 0;
}
else if (cmd_in == MTFSF) else if (cmd_in == MTFSF)
STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM; STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
else if (chg_eof) else if (chg_eof)
...@@ -4233,8 +4234,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp) ...@@ -4233,8 +4234,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
#endif #endif
return (-EBUSY); return (-EBUSY);
} }
if (scsi_device_get(STp->device)) {
if (!scsi_device_get(STp->device)) {
write_unlock(&os_scsi_tapes_lock); write_unlock(&os_scsi_tapes_lock);
#if DEBUG #if DEBUG
printk(OSST_DEB_MSG "%s:D: Failed scsi_device_get.\n", name); printk(OSST_DEB_MSG "%s:D: Failed scsi_device_get.\n", name);
...@@ -4856,12 +4856,6 @@ static int osst_ioctl(struct inode * inode,struct file * file, ...@@ -4856,12 +4856,6 @@ static int osst_ioctl(struct inode * inode,struct file * file,
} }
if (mtc.mt_op == MTSETPART) { if (mtc.mt_op == MTSETPART) {
/* if (!STp->can_partitions ||
mtc.mt_count < 0 || mtc.mt_count >= ST_NBR_PARTITIONS)
return (-EINVAL);
if (mtc.mt_count >= STp->nbr_partitions &&
(STp->nbr_partitions = nbr_partitions(inode)) < 0)
return (-EIO);*/
if (mtc.mt_count >= STp->nbr_partitions) if (mtc.mt_count >= STp->nbr_partitions)
retval = -EINVAL; retval = -EINVAL;
else { else {
...@@ -4909,10 +4903,6 @@ static int osst_ioctl(struct inode * inode,struct file * file, ...@@ -4909,10 +4903,6 @@ static int osst_ioctl(struct inode * inode,struct file * file,
goto out; goto out;
} }
/* if (STp->can_partitions && STp->ready == ST_READY &&
(i = update_partition(inode)) < 0)
{retval=i;goto out;}*/
if (mtc.mt_op == MTCOMPRESSION) if (mtc.mt_op == MTCOMPRESSION)
retval = -EINVAL /*osst_compression(STp, (mtc.mt_count & 1))*/; retval = -EINVAL /*osst_compression(STp, (mtc.mt_count & 1))*/;
else else
...@@ -4931,10 +4921,6 @@ static int osst_ioctl(struct inode * inode,struct file * file, ...@@ -4931,10 +4921,6 @@ static int osst_ioctl(struct inode * inode,struct file * file,
goto out; goto out;
} }
/* if (STp->can_partitions &&
(i = update_partition(inode)) < 0)
{retval=i;goto out;}*/
if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) { if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
struct mtget mt_status; struct mtget mt_status;
...@@ -5110,9 +5096,7 @@ static int enlarge_buffer(OSST_buffer *STbuffer, int need_dma) ...@@ -5110,9 +5096,7 @@ static int enlarge_buffer(OSST_buffer *STbuffer, int need_dma)
for (segs=STbuffer->sg_segs=1, got=b_size; for (segs=STbuffer->sg_segs=1, got=b_size;
segs < max_segs && got < OS_FRAME_SIZE; ) { segs < max_segs && got < OS_FRAME_SIZE; ) {
STbuffer->sg[segs].page = STbuffer->sg[segs].page =
(OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order);
kmalloc(OS_FRAME_SIZE - got, priority):
alloc_pages(priority, order);
STbuffer->sg[segs].offset = 0; STbuffer->sg[segs].offset = 0;
if (STbuffer->sg[segs].page == NULL) { if (STbuffer->sg[segs].page == NULL) {
if (OS_FRAME_SIZE - got <= (max_segs - segs) * b_size / 2 && order) { if (OS_FRAME_SIZE - got <= (max_segs - segs) * b_size / 2 && order) {
...@@ -5320,10 +5304,8 @@ static void validate_options (void) ...@@ -5320,10 +5304,8 @@ static void validate_options (void)
if (max_sg_segs >= OSST_FIRST_SG) if (max_sg_segs >= OSST_FIRST_SG)
osst_max_sg_segs = max_sg_segs; osst_max_sg_segs = max_sg_segs;
#if DEBUG #if DEBUG
printk(OSST_DEB_MSG "osst :D: max tapes %d, write threshold %d, s/g segs %d.\n", printk(OSST_DEB_MSG "osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
osst_max_dev, osst_write_threshold, osst_max_sg_segs); osst_max_dev, osst_write_threshold, osst_max_sg_segs);
//printk(OSST_DEB_MSG "osst :D: sizeof(header) = %d (%s)\n",
// sizeof(os_header_t),sizeof(os_header_t)==OS_DATA_SIZE?"ok":"error");
#endif #endif
} }
...@@ -5446,7 +5428,7 @@ static int osst_attach(Scsi_Device * SDp) ...@@ -5446,7 +5428,7 @@ static int osst_attach(Scsi_Device * SDp)
drive = alloc_disk(1); drive = alloc_disk(1);
if (!drive) { if (!drive) {
printk(KERN_ERR "osst :E: Out of memory. Device not attached.\n"); printk(KERN_ERR "osst :E: Out of memory. Device not attached.\n");
return 1; goto out_slave_detach;
} }
/* if this is the first attach, build the infrastructure */ /* if this is the first attach, build the infrastructure */
...@@ -5458,7 +5440,7 @@ static int osst_attach(Scsi_Device * SDp) ...@@ -5458,7 +5440,7 @@ static int osst_attach(Scsi_Device * SDp)
if (os_scsi_tapes == NULL) { if (os_scsi_tapes == NULL) {
write_unlock(&os_scsi_tapes_lock); write_unlock(&os_scsi_tapes_lock);
printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n"); printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
return 1; goto out_put_disk;
} }
for (i=0; i < osst_max_dev; ++i) os_scsi_tapes[i] = NULL; for (i=0; i < osst_max_dev; ++i) os_scsi_tapes[i] = NULL;
} }
...@@ -5466,8 +5448,7 @@ static int osst_attach(Scsi_Device * SDp) ...@@ -5466,8 +5448,7 @@ static int osst_attach(Scsi_Device * SDp)
if (osst_nr_dev >= osst_max_dev) { if (osst_nr_dev >= osst_max_dev) {
write_unlock(&os_scsi_tapes_lock); write_unlock(&os_scsi_tapes_lock);
printk(KERN_ERR "osst :E: Too many tape devices (max. %d).\n", osst_max_dev); printk(KERN_ERR "osst :E: Too many tape devices (max. %d).\n", osst_max_dev);
put_disk(drive); goto out_put_disk;
return 1;
} }
/* find a free minor number */ /* find a free minor number */
...@@ -5480,9 +5461,7 @@ static int osst_attach(Scsi_Device * SDp) ...@@ -5480,9 +5461,7 @@ static int osst_attach(Scsi_Device * SDp)
if (tpnt == NULL) { if (tpnt == NULL) {
write_unlock(&os_scsi_tapes_lock); write_unlock(&os_scsi_tapes_lock);
printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n"); printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
put_disk(drive); goto out_put_disk;
scsi_slave_detach(SDp);
return 1;
} }
memset(tpnt, 0, sizeof(OS_Scsi_Tape)); memset(tpnt, 0, sizeof(OS_Scsi_Tape));
...@@ -5495,9 +5474,7 @@ static int osst_attach(Scsi_Device * SDp) ...@@ -5495,9 +5474,7 @@ static int osst_attach(Scsi_Device * SDp)
write_unlock(&os_scsi_tapes_lock); write_unlock(&os_scsi_tapes_lock);
printk(KERN_ERR "osst :E: Unable to allocate a tape buffer, device not attached.\n"); printk(KERN_ERR "osst :E: Unable to allocate a tape buffer, device not attached.\n");
kfree(tpnt); kfree(tpnt);
put_disk(drive); goto out_put_disk;
scsi_slave_detach(SDp);
return 1;
} }
os_scsi_tapes[dev_num] = tpnt; os_scsi_tapes[dev_num] = tpnt;
tpnt->buffer = buffer; tpnt->buffer = buffer;
...@@ -5623,6 +5600,12 @@ static int osst_attach(Scsi_Device * SDp) ...@@ -5623,6 +5600,12 @@ static int osst_attach(Scsi_Device * SDp)
SDp->model, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun, tape_name(tpnt)); SDp->model, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun, tape_name(tpnt));
return 0; return 0;
out_put_disk:
put_disk(drive);
out_slave_detach:
scsi_slave_detach(SDp);
return 1;
}; };
static void osst_detach(Scsi_Device * SDp) static void osst_detach(Scsi_Device * SDp)
...@@ -5630,48 +5613,46 @@ static void osst_detach(Scsi_Device * SDp) ...@@ -5630,48 +5613,46 @@ static void osst_detach(Scsi_Device * SDp)
OS_Scsi_Tape * tpnt; OS_Scsi_Tape * tpnt;
int i, mode; int i, mode;
if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
return;
write_lock(&os_scsi_tapes_lock); write_lock(&os_scsi_tapes_lock);
if (os_scsi_tapes != NULL) { for(i=0; i < osst_max_dev; i++) {
for(i=0; i<osst_max_dev; i++) { if((tpnt = os_scsi_tapes[i]) && (tpnt->device == SDp)) {
tpnt = os_scsi_tapes[i]; tpnt->device = NULL;
if(tpnt != NULL && tpnt->device == SDp) { for (mode = 0; mode < ST_NBR_MODES; ++mode) {
tpnt->device = NULL; devfs_unregister (tpnt->de_r[mode]);
for (mode = 0; mode < ST_NBR_MODES; ++mode) { tpnt->de_r[mode] = NULL;
devfs_unregister (tpnt->de_r[mode]); devfs_unregister (tpnt->de_n[mode]);
tpnt->de_r[mode] = NULL; tpnt->de_n[mode] = NULL;
devfs_unregister (tpnt->de_n[mode]); }
tpnt->de_n[mode] = NULL; devfs_unregister_tape(tpnt->drive->number);
} put_disk(tpnt->drive);
devfs_unregister_tape(tpnt->drive->number); os_scsi_tapes[i] = NULL;
put_disk(tpnt->drive); scsi_slave_detach(SDp);
os_scsi_tapes[i] = NULL; osst_nr_dev--;
scsi_slave_detach(SDp); write_unlock(&os_scsi_tapes_lock);
osst_nr_dev--; for (mode = 0; mode < ST_NBR_MODES; ++mode) {
write_unlock(&os_scsi_tapes_lock); device_remove_file(&tpnt->driverfs_dev_r[mode],
for (mode = 0; mode < ST_NBR_MODES; ++mode) { &dev_attr_type);
device_remove_file(&tpnt->driverfs_dev_r[mode], device_remove_file(&tpnt->driverfs_dev_r[mode],
&dev_attr_type); &dev_attr_kdev);
device_remove_file(&tpnt->driverfs_dev_r[mode], device_unregister(&tpnt->driverfs_dev_r[mode]);
&dev_attr_kdev); device_remove_file(&tpnt->driverfs_dev_n[mode],
device_unregister(&tpnt->driverfs_dev_r[mode]); &dev_attr_type);
device_remove_file(&tpnt->driverfs_dev_n[mode], device_remove_file(&tpnt->driverfs_dev_n[mode],
&dev_attr_type); &dev_attr_kdev);
device_remove_file(&tpnt->driverfs_dev_n[mode], device_unregister(&tpnt->driverfs_dev_n[mode]);
&dev_attr_kdev);
device_unregister(&tpnt->driverfs_dev_n[mode]);
}
if (tpnt->header_cache != NULL)
vfree(tpnt->header_cache);
if (tpnt->buffer) {
normalize_buffer(tpnt->buffer);
kfree(tpnt->buffer);
} }
kfree(tpnt); if (tpnt->header_cache != NULL) vfree(tpnt->header_cache);
break; if (tpnt->buffer) {
normalize_buffer(tpnt->buffer);
kfree(tpnt->buffer);
} }
} kfree(tpnt);
return;
}
} }
write_unlock(&os_scsi_tapes_lock); write_unlock(&os_scsi_tapes_lock);
return; return;
} }
...@@ -5681,12 +5662,8 @@ static int __init init_osst(void) ...@@ -5681,12 +5662,8 @@ static int __init init_osst(void)
printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid); printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
validate_options(); validate_options();
#if DEBUG
printk(OSST_DEB_MSG "osst :D: %d s/g segments, write threshold %d bytes.\n", if ((register_chrdev(OSST_MAJOR,"osst", &osst_fops) < 0) || scsi_register_device(&osst_template)) {
max_sg_segs, osst_write_threshold);
#endif
if ((register_chrdev(OSST_MAJOR, "osst", &osst_fops) < 0) ||
scsi_register_device(&osst_template)) {
printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR); printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
return 1; return 1;
} }
......
...@@ -177,6 +177,13 @@ void scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt) ...@@ -177,6 +177,13 @@ void scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt)
*/ */
blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS); blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
if(!SHpnt->max_sectors)
/* driver imposes no hard sector transfer limit.
* start at machine infinity initially */
SHpnt->max_sectors = SCSI_DEFAULT_MAX_SECTORS;
/* FIXME: we should also adjust this limit later on
* after we know what the device capabilities are */
blk_queue_max_sectors(q, SHpnt->max_sectors); blk_queue_max_sectors(q, SHpnt->max_sectors);
if (!SHpnt->use_clustering) if (!SHpnt->use_clustering)
......
...@@ -373,6 +373,14 @@ extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE]; ...@@ -373,6 +373,14 @@ extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
#define ASKED_FOR_SENSE 0x20 #define ASKED_FOR_SENSE 0x20
#define SYNC_RESET 0x40 #define SYNC_RESET 0x40
/*
* This specifies "machine infinity" for host templates which don't
* limit the transfer size. Note this limit represents an absolute
* maximum, and may be over the transfer limits allowed for individual
* devices (e.g. 256 for SCSI-1)
*/
#define SCSI_DEFAULT_MAX_SECTORS 1024
/* /*
* This is the crap from the old error handling code. We have it in a special * This is the crap from the old error handling code. We have it in a special
* place so that we can more easily delete it later on. * place so that we can more easily delete it later on.
......
...@@ -172,7 +172,7 @@ static inline struct scsi_disk *scsi_disk(struct gendisk *disk) ...@@ -172,7 +172,7 @@ static inline struct scsi_disk *scsi_disk(struct gendisk *disk)
**/ **/
static int sd_init_command(struct scsi_cmnd * SCpnt) static int sd_init_command(struct scsi_cmnd * SCpnt)
{ {
int this_count, timeout; unsigned int this_count, timeout;
struct gendisk *disk; struct gendisk *disk;
sector_t block; sector_t block;
struct scsi_device *sdp = SCpnt->device; struct scsi_device *sdp = SCpnt->device;
...@@ -298,8 +298,23 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) ...@@ -298,8 +298,23 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
"writing" : "reading", this_count, SCpnt->request->nr_sectors)); "writing" : "reading", this_count, SCpnt->request->nr_sectors));
SCpnt->cmnd[1] = 0; SCpnt->cmnd[1] = 0;
if (((this_count > 0xff) || (block > 0x1fffff)) || SCpnt->device->ten) { if (block > 0xffffffff) {
SCpnt->cmnd[0] += READ_16 - READ_6;
SCpnt->cmnd[2] = (unsigned char) (block >> 56) & 0xff;
SCpnt->cmnd[3] = (unsigned char) (block >> 48) & 0xff;
SCpnt->cmnd[4] = (unsigned char) (block >> 40) & 0xff;
SCpnt->cmnd[5] = (unsigned char) (block >> 32) & 0xff;
SCpnt->cmnd[6] = (unsigned char) (block >> 24) & 0xff;
SCpnt->cmnd[7] = (unsigned char) (block >> 16) & 0xff;
SCpnt->cmnd[8] = (unsigned char) (block >> 8) & 0xff;
SCpnt->cmnd[9] = (unsigned char) block & 0xff;
SCpnt->cmnd[10] = (unsigned char) (this_count >> 24) & 0xff;
SCpnt->cmnd[11] = (unsigned char) (this_count >> 16) & 0xff;
SCpnt->cmnd[12] = (unsigned char) (this_count >> 8) & 0xff;
SCpnt->cmnd[13] = (unsigned char) this_count & 0xff;
SCpnt->cmnd[14] = SCpnt->cmnd[15] = 0;
} else if (((this_count > 0xff) || (block > 0x1fffff)) || SCpnt->device->ten) {
if (this_count > 0xffff) if (this_count > 0xffff)
this_count = 0xffff; this_count = 0xffff;
...@@ -904,24 +919,34 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, ...@@ -904,24 +919,34 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
static void static void
sd_read_capacity(struct scsi_disk *sdkp, char *diskname, sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
struct scsi_request *SRpnt, unsigned char *buffer) { struct scsi_request *SRpnt, unsigned char *buffer) {
unsigned char cmd[10]; unsigned char cmd[16];
struct scsi_device *sdp = sdkp->device; struct scsi_device *sdp = sdkp->device;
int the_result, retries; int the_result, retries;
int sector_size; int sector_size = 0;
int longrc = 0;
repeat:
retries = 3; retries = 3;
do { do {
cmd[0] = READ_CAPACITY; if (longrc) {
memset((void *) &cmd[1], 0, 9); memset((void *) cmd, 0, 16);
memset((void *) buffer, 0, 8); cmd[0] = SERVICE_ACTION_IN;
cmd[1] = 0x10; /* READ CAPACITY (16) */
cmd[13] = 12;
memset((void *) buffer, 0, 12);
} else {
cmd[0] = READ_CAPACITY;
memset((void *) &cmd[1], 0, 9);
memset((void *) buffer, 0, 8);
}
SRpnt->sr_cmd_len = 0; SRpnt->sr_cmd_len = 0;
SRpnt->sr_sense_buffer[0] = 0; SRpnt->sr_sense_buffer[0] = 0;
SRpnt->sr_sense_buffer[2] = 0; SRpnt->sr_sense_buffer[2] = 0;
SRpnt->sr_data_direction = SCSI_DATA_READ; SRpnt->sr_data_direction = SCSI_DATA_READ;
scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer, scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
8, SD_TIMEOUT, SD_MAX_RETRIES); longrc ? 12 : 8, SD_TIMEOUT, SD_MAX_RETRIES);
if (media_not_present(sdkp, SRpnt)) if (media_not_present(sdkp, SRpnt))
return; return;
...@@ -931,7 +956,7 @@ sd_read_capacity(struct scsi_disk *sdkp, char *diskname, ...@@ -931,7 +956,7 @@ sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
} while (the_result && retries); } while (the_result && retries);
if (the_result) { if (the_result && !longrc) {
printk(KERN_NOTICE "%s : READ CAPACITY failed.\n" printk(KERN_NOTICE "%s : READ CAPACITY failed.\n"
"%s : status=%x, message=%02x, host=%d, driver=%02x \n", "%s : status=%x, message=%02x, host=%d, driver=%02x \n",
diskname, diskname, diskname, diskname,
...@@ -957,16 +982,51 @@ sd_read_capacity(struct scsi_disk *sdkp, char *diskname, ...@@ -957,16 +982,51 @@ sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
sdkp->capacity = 0x200000; /* 1 GB - random */ sdkp->capacity = 0x200000; /* 1 GB - random */
return; return;
} } else if (the_result && longrc) {
/* READ CAPACITY(16) has been failed */
sdkp->capacity = 1 + (((sector_t)buffer[0] << 24) | printk(KERN_NOTICE "%s : READ CAPACITY(16) failed.\n"
(buffer[1] << 16) | "%s : status=%x, message=%02x, host=%d, driver=%02x \n",
(buffer[2] << 8) | diskname, diskname,
buffer[3]); status_byte(the_result),
msg_byte(the_result),
sector_size = (buffer[4] << 24) | host_byte(the_result),
(buffer[5] << 16) | (buffer[6] << 8) | buffer[7]; driver_byte(the_result));
printk(KERN_NOTICE "%s : use 0xffffffff as device size\n",
diskname);
sdkp->capacity = 1 + (sector_t) 0xffffffff;
goto got_data;
}
if (!longrc) {
sector_size = (buffer[4] << 24) |
(buffer[5] << 16) | (buffer[6] << 8) | buffer[7];
if (buffer[0] == 0xff && buffer[1] == 0xff &&
buffer[2] == 0xff && buffer[3] == 0xff) {
printk(KERN_NOTICE "%s : very big device. try to use"
" READ CAPACITY(16).\n", diskname);
longrc = 1;
goto repeat;
}
sdkp->capacity = 1 + (((sector_t)buffer[0] << 24) |
(buffer[1] << 16) |
(buffer[2] << 8) |
buffer[3]);
} else {
sdkp->capacity = 1 + (((sector_t)buffer[0] << 56) |
((sector_t)buffer[1] << 48) |
((sector_t)buffer[2] << 40) |
((sector_t)buffer[3] << 32) |
((sector_t)buffer[4] << 24) |
((sector_t)buffer[5] << 16) |
((sector_t)buffer[6] << 8) |
(sector_t)buffer[7]);
sector_size = (buffer[8] << 24) |
(buffer[9] << 16) | (buffer[10] << 8) | buffer[11];
}
got_data:
if (sector_size == 0) { if (sector_size == 0) {
sector_size = 512; sector_size = 512;
printk(KERN_NOTICE "%s : sector size 0 reported, " printk(KERN_NOTICE "%s : sector size 0 reported, "
...@@ -1139,10 +1199,10 @@ sd_init_onedisk(struct scsi_disk * sdkp, struct gendisk *disk) ...@@ -1139,10 +1199,10 @@ sd_init_onedisk(struct scsi_disk * sdkp, struct gendisk *disk)
if (sdkp->media_present) if (sdkp->media_present)
sd_read_capacity(sdkp, disk->disk_name, SRpnt, buffer); sd_read_capacity(sdkp, disk->disk_name, SRpnt, buffer);
if (sdp->removable && sdkp->media_present) if (sdp->removable && sdkp->media_present)
sd_read_write_protect_flag(sdkp, disk->disk_name, SRpnt, buffer); sd_read_write_protect_flag(sdkp, disk->disk_name, SRpnt, buffer);
SRpnt->sr_device->ten = 1; SRpnt->sr_device->ten = 1;
SRpnt->sr_device->remap = 1; SRpnt->sr_device->remap = 1;
......
...@@ -96,6 +96,10 @@ extern const unsigned char scsi_command_size[8]; ...@@ -96,6 +96,10 @@ extern const unsigned char scsi_command_size[8];
#define READ_ELEMENT_STATUS 0xb8 #define READ_ELEMENT_STATUS 0xb8
#define SEND_VOLUME_TAG 0xb6 #define SEND_VOLUME_TAG 0xb6
#define WRITE_LONG_2 0xea #define WRITE_LONG_2 0xea
#define READ_16 0x88
#define WRITE_16 0x8a
#define SERVICE_ACTION_IN 0x9e
/* /*
* Status codes * Status codes
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment