|
@@ -259,47 +259,6 @@ typedef struct idetape_packet_command_s {
|
|
|
/* Data direction */
|
|
|
#define PC_WRITING 5
|
|
|
|
|
|
-/*
|
|
|
- * Capabilities and Mechanical Status Page
|
|
|
- */
|
|
|
-typedef struct {
|
|
|
- unsigned page_code :6; /* Page code - Should be 0x2a */
|
|
|
- __u8 reserved0_6 :1;
|
|
|
- __u8 ps :1; /* parameters saveable */
|
|
|
- __u8 page_length; /* Page Length - Should be 0x12 */
|
|
|
- __u8 reserved2, reserved3;
|
|
|
- unsigned ro :1; /* Read Only Mode */
|
|
|
- unsigned reserved4_1234 :4;
|
|
|
- unsigned sprev :1; /* Supports SPACE in the reverse direction */
|
|
|
- unsigned reserved4_67 :2;
|
|
|
- unsigned reserved5_012 :3;
|
|
|
- unsigned efmt :1; /* Supports ERASE command initiated formatting */
|
|
|
- unsigned reserved5_4 :1;
|
|
|
- unsigned qfa :1; /* Supports the QFA two partition formats */
|
|
|
- unsigned reserved5_67 :2;
|
|
|
- unsigned lock :1; /* Supports locking the volume */
|
|
|
- unsigned locked :1; /* The volume is locked */
|
|
|
- unsigned prevent :1; /* The device defaults in the prevent state after power up */
|
|
|
- unsigned eject :1; /* The device can eject the volume */
|
|
|
- __u8 disconnect :1; /* The device can break request > ctl */
|
|
|
- __u8 reserved6_5 :1;
|
|
|
- unsigned ecc :1; /* Supports error correction */
|
|
|
- unsigned cmprs :1; /* Supports data compression */
|
|
|
- unsigned reserved7_0 :1;
|
|
|
- unsigned blk512 :1; /* Supports 512 bytes block size */
|
|
|
- unsigned blk1024 :1; /* Supports 1024 bytes block size */
|
|
|
- unsigned reserved7_3_6 :4;
|
|
|
- unsigned blk32768 :1; /* slowb - the device restricts the byte count for PIO */
|
|
|
- /* transfers for slow buffer memory ??? */
|
|
|
- /* Also 32768 block size in some cases */
|
|
|
- __u16 max_speed; /* Maximum speed supported in KBps */
|
|
|
- __u8 reserved10, reserved11;
|
|
|
- __u16 ctl; /* Continuous Transfer Limit in blocks */
|
|
|
- __u16 speed; /* Current Speed, in KBps */
|
|
|
- __u16 buffer_size; /* Buffer Size, in 512 bytes */
|
|
|
- __u8 reserved18, reserved19;
|
|
|
-} idetape_capabilities_page_t;
|
|
|
-
|
|
|
/*
|
|
|
* Block Size Page
|
|
|
*/
|
|
@@ -417,8 +376,9 @@ typedef struct ide_tape_obj {
|
|
|
/* Usually 512 or 1024 bytes */
|
|
|
unsigned short tape_block_size;
|
|
|
int user_bs_factor;
|
|
|
+
|
|
|
/* Copy of the tape's Capabilities and Mechanical Page */
|
|
|
- idetape_capabilities_page_t capabilities;
|
|
|
+ u8 caps[20];
|
|
|
|
|
|
/*
|
|
|
* Active data transfer request parameters.
|
|
@@ -2464,7 +2424,8 @@ static int idetape_create_prevent_cmd (ide_drive_t *drive, idetape_pc_t *pc, int
|
|
|
{
|
|
|
idetape_tape_t *tape = drive->driver_data;
|
|
|
|
|
|
- if (!tape->capabilities.lock)
|
|
|
+ /* device supports locking according to capabilities page */
|
|
|
+ if (!(tape->caps[6] & 0x01))
|
|
|
return 0;
|
|
|
|
|
|
idetape_init_pc(pc);
|
|
@@ -2850,7 +2811,7 @@ static int idetape_initiate_read (ide_drive_t *drive, int max_stages)
|
|
|
idetape_stage_t *new_stage;
|
|
|
struct request rq;
|
|
|
int bytes_read;
|
|
|
- int blocks = tape->capabilities.ctl;
|
|
|
+ u16 blocks = *(u16 *)&tape->caps[12];
|
|
|
|
|
|
/* Initialize read operation */
|
|
|
if (tape->chrdev_direction != idetape_direction_read) {
|
|
@@ -3090,11 +3051,12 @@ static int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_c
|
|
|
idetape_pc_t pc;
|
|
|
unsigned long flags;
|
|
|
int retval,count=0;
|
|
|
+ int sprev = !!(tape->caps[4] & 0x20);
|
|
|
|
|
|
if (mt_count == 0)
|
|
|
return 0;
|
|
|
if (MTBSF == mt_op || MTBSFM == mt_op) {
|
|
|
- if (!tape->capabilities.sprev)
|
|
|
+ if (!sprev)
|
|
|
return -EIO;
|
|
|
mt_count = - mt_count;
|
|
|
}
|
|
@@ -3148,7 +3110,7 @@ static int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_c
|
|
|
return (idetape_queue_pc_tail(drive, &pc));
|
|
|
case MTFSFM:
|
|
|
case MTBSFM:
|
|
|
- if (!tape->capabilities.sprev)
|
|
|
+ if (!sprev)
|
|
|
return (-EIO);
|
|
|
retval = idetape_space_over_filemarks(drive, MTFSF, mt_count-count);
|
|
|
if (retval) return (retval);
|
|
@@ -3185,6 +3147,7 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
|
|
|
ide_drive_t *drive = tape->drive;
|
|
|
ssize_t bytes_read,temp, actually_read = 0, rc;
|
|
|
ssize_t ret = 0;
|
|
|
+ u16 ctl = *(u16 *)&tape->caps[12];
|
|
|
|
|
|
#if IDETAPE_DEBUG_LOG
|
|
|
if (tape->debug_level >= 3)
|
|
@@ -3210,7 +3173,7 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
|
|
|
count -= actually_read;
|
|
|
}
|
|
|
while (count >= tape->stage_size) {
|
|
|
- bytes_read = idetape_add_chrdev_read_request(drive, tape->capabilities.ctl);
|
|
|
+ bytes_read = idetape_add_chrdev_read_request(drive, ctl);
|
|
|
if (bytes_read <= 0)
|
|
|
goto finish;
|
|
|
if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, bytes_read))
|
|
@@ -3220,7 +3183,7 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
|
|
|
actually_read += bytes_read;
|
|
|
}
|
|
|
if (count) {
|
|
|
- bytes_read = idetape_add_chrdev_read_request(drive, tape->capabilities.ctl);
|
|
|
+ bytes_read = idetape_add_chrdev_read_request(drive, ctl);
|
|
|
if (bytes_read <= 0)
|
|
|
goto finish;
|
|
|
temp = min((unsigned long)count, (unsigned long)bytes_read);
|
|
@@ -3249,6 +3212,7 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
|
|
|
ide_drive_t *drive = tape->drive;
|
|
|
ssize_t actually_written = 0;
|
|
|
ssize_t ret = 0;
|
|
|
+ u16 ctl = *(u16 *)&tape->caps[12];
|
|
|
|
|
|
/* The drive is write protected. */
|
|
|
if (tape->write_prot)
|
|
@@ -3310,7 +3274,7 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
|
|
|
if (tape->merge_stage_size == tape->stage_size) {
|
|
|
ssize_t retval;
|
|
|
tape->merge_stage_size = 0;
|
|
|
- retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl);
|
|
|
+ retval = idetape_add_chrdev_write_request(drive, ctl);
|
|
|
if (retval <= 0)
|
|
|
return (retval);
|
|
|
}
|
|
@@ -3321,7 +3285,7 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
|
|
|
ret = -EFAULT;
|
|
|
buf += tape->stage_size;
|
|
|
count -= tape->stage_size;
|
|
|
- retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl);
|
|
|
+ retval = idetape_add_chrdev_write_request(drive, ctl);
|
|
|
actually_written += tape->stage_size;
|
|
|
if (retval <= 0)
|
|
|
return (retval);
|
|
@@ -3821,46 +3785,52 @@ static void idetape_get_inquiry_results (ide_drive_t *drive)
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * idetape_get_mode_sense_results asks the tape about its various
|
|
|
- * parameters. In particular, we will adjust our data transfer buffer
|
|
|
- * size to the recommended value as returned by the tape.
|
|
|
+ * Ask the tape about its various parameters. In particular, we will adjust our
|
|
|
+ * data transfer buffer size to the recommended value as returned by the tape.
|
|
|
*/
|
|
|
static void idetape_get_mode_sense_results (ide_drive_t *drive)
|
|
|
{
|
|
|
idetape_tape_t *tape = drive->driver_data;
|
|
|
idetape_pc_t pc;
|
|
|
- idetape_capabilities_page_t *capabilities;
|
|
|
+ u8 *caps;
|
|
|
+ u8 speed, max_speed;
|
|
|
|
|
|
idetape_create_mode_sense_cmd(&pc, IDETAPE_CAPABILITIES_PAGE);
|
|
|
if (idetape_queue_pc_tail(drive, &pc)) {
|
|
|
- printk(KERN_ERR "ide-tape: Can't get tape parameters - assuming some default values\n");
|
|
|
+ printk(KERN_ERR "ide-tape: Can't get tape parameters - assuming"
|
|
|
+ " some default values\n");
|
|
|
tape->tape_block_size = 512;
|
|
|
- tape->capabilities.ctl = 52;
|
|
|
- tape->capabilities.speed = 450;
|
|
|
- tape->capabilities.buffer_size = 6 * 52;
|
|
|
+ put_unaligned(52, (u16 *)&tape->caps[12]);
|
|
|
+ put_unaligned(540, (u16 *)&tape->caps[14]);
|
|
|
+ put_unaligned(6*52, (u16 *)&tape->caps[16]);
|
|
|
return;
|
|
|
}
|
|
|
- capabilities = (idetape_capabilities_page_t *)
|
|
|
- (pc.buffer + 4 + pc.buffer[3]);
|
|
|
+ caps = pc.buffer + 4 + pc.buffer[3];
|
|
|
+
|
|
|
+ /* convert to host order and save for later use */
|
|
|
+ speed = be16_to_cpu(*(u16 *)&caps[14]);
|
|
|
+ max_speed = be16_to_cpu(*(u16 *)&caps[8]);
|
|
|
|
|
|
- capabilities->max_speed = ntohs(capabilities->max_speed);
|
|
|
- capabilities->ctl = ntohs(capabilities->ctl);
|
|
|
- capabilities->speed = ntohs(capabilities->speed);
|
|
|
- capabilities->buffer_size = ntohs(capabilities->buffer_size);
|
|
|
+ put_unaligned(max_speed, (u16 *)&caps[8]);
|
|
|
+ put_unaligned(be16_to_cpu(*(u16 *)&caps[12]), (u16 *)&caps[12]);
|
|
|
+ put_unaligned(speed, (u16 *)&caps[14]);
|
|
|
+ put_unaligned(be16_to_cpu(*(u16 *)&caps[16]), (u16 *)&caps[16]);
|
|
|
|
|
|
- if (!capabilities->speed) {
|
|
|
- printk(KERN_INFO "ide-tape: %s: overriding capabilities->speed (assuming 650KB/sec)\n", drive->name);
|
|
|
- capabilities->speed = 650;
|
|
|
+ if (!speed) {
|
|
|
+ printk(KERN_INFO "ide-tape: %s: invalid tape speed "
|
|
|
+ "(assuming 650KB/sec)\n", drive->name);
|
|
|
+ put_unaligned(650, (u16 *)&caps[14]);
|
|
|
}
|
|
|
- if (!capabilities->max_speed) {
|
|
|
- printk(KERN_INFO "ide-tape: %s: overriding capabilities->max_speed (assuming 650KB/sec)\n", drive->name);
|
|
|
- capabilities->max_speed = 650;
|
|
|
+ if (!max_speed) {
|
|
|
+ printk(KERN_INFO "ide-tape: %s: invalid max_speed "
|
|
|
+ "(assuming 650KB/sec)\n", drive->name);
|
|
|
+ put_unaligned(650, (u16 *)&caps[8]);
|
|
|
}
|
|
|
|
|
|
- tape->capabilities = *capabilities; /* Save us a copy */
|
|
|
- if (capabilities->blk512)
|
|
|
+ memcpy(&tape->caps, caps, 20);
|
|
|
+ if (caps[7] & 0x02)
|
|
|
tape->tape_block_size = 512;
|
|
|
- else if (capabilities->blk1024)
|
|
|
+ else if (caps[7] & 0x04)
|
|
|
tape->tape_block_size = 1024;
|
|
|
}
|
|
|
|
|
@@ -3897,13 +3867,15 @@ static void idetape_add_settings (ide_drive_t *drive)
|
|
|
/*
|
|
|
* drive setting name read/write data type min max mul_factor div_factor data pointer set function
|
|
|
*/
|
|
|
- ide_add_setting(drive, "buffer", SETTING_READ, TYPE_SHORT, 0, 0xffff, 1, 2, &tape->capabilities.buffer_size, NULL);
|
|
|
+ ide_add_setting(drive, "buffer", SETTING_READ, TYPE_SHORT, 0, 0xffff,
|
|
|
+ 1, 2, (u16 *)&tape->caps[16], NULL);
|
|
|
ide_add_setting(drive, "pipeline_min", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL);
|
|
|
ide_add_setting(drive, "pipeline", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL);
|
|
|
ide_add_setting(drive, "pipeline_max", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL);
|
|
|
ide_add_setting(drive, "pipeline_used", SETTING_READ, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_stages, NULL);
|
|
|
ide_add_setting(drive, "pipeline_pending", SETTING_READ, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_pending_stages, NULL);
|
|
|
- ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->capabilities.speed, NULL);
|
|
|
+ ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff,
|
|
|
+ 1, 1, (u16 *)&tape->caps[14], NULL);
|
|
|
ide_add_setting(drive, "stage", SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1024, &tape->stage_size, NULL);
|
|
|
ide_add_setting(drive, "tdsc", SETTING_RW, TYPE_INT, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_frequency, NULL);
|
|
|
ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL);
|
|
@@ -3935,6 +3907,7 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
|
|
|
struct idetape_id_gcw gcw;
|
|
|
int stage_size;
|
|
|
struct sysinfo si;
|
|
|
+ u16 *ctl = (u16 *)&tape->caps[12];
|
|
|
|
|
|
spin_lock_init(&tape->spinlock);
|
|
|
drive->dsc_overlap = 1;
|
|
@@ -3964,11 +3937,11 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
|
|
|
idetape_get_mode_sense_results(drive);
|
|
|
idetape_get_blocksize_from_block_descriptor(drive);
|
|
|
tape->user_bs_factor = 1;
|
|
|
- tape->stage_size = tape->capabilities.ctl * tape->tape_block_size;
|
|
|
+ tape->stage_size = *ctl * tape->tape_block_size;
|
|
|
while (tape->stage_size > 0xffff) {
|
|
|
printk(KERN_NOTICE "ide-tape: decreasing stage size\n");
|
|
|
- tape->capabilities.ctl /= 2;
|
|
|
- tape->stage_size = tape->capabilities.ctl * tape->tape_block_size;
|
|
|
+ *ctl /= 2;
|
|
|
+ tape->stage_size = *ctl * tape->tape_block_size;
|
|
|
}
|
|
|
stage_size = tape->stage_size;
|
|
|
tape->pages_per_stage = stage_size / PAGE_SIZE;
|
|
@@ -3977,11 +3950,8 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
|
|
|
tape->excess_bh_size = PAGE_SIZE - stage_size % PAGE_SIZE;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * Select the "best" DSC read/write polling frequency
|
|
|
- * and pipeline size.
|
|
|
- */
|
|
|
- speed = max(tape->capabilities.speed, tape->capabilities.max_speed);
|
|
|
+ /* Select the "best" DSC read/write polling freq and pipeline size. */
|
|
|
+ speed = max(*(u16 *)&tape->caps[14], *(u16 *)&tape->caps[8]);
|
|
|
|
|
|
tape->max_stages = speed * 1000 * 10 / tape->stage_size;
|
|
|
|
|
@@ -3998,7 +3968,7 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
|
|
|
tape->max_stages = tape->min_pipeline = tape->max_pipeline = 1;
|
|
|
|
|
|
t1 = (tape->stage_size * HZ) / (speed * 1000);
|
|
|
- tmid = (tape->capabilities.buffer_size * 32 * HZ) / (speed * 125);
|
|
|
+ tmid = (*(u16 *)&tape->caps[16] * 32 * HZ) / (speed * 125);
|
|
|
tn = (IDETAPE_FIFO_THRESHOLD * tape->stage_size * HZ) / (speed * 1000);
|
|
|
|
|
|
if (tape->max_stages)
|
|
@@ -4013,8 +3983,8 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
|
|
|
tape->best_dsc_rw_frequency = max_t(unsigned long, min_t(unsigned long, t, IDETAPE_DSC_RW_MAX), IDETAPE_DSC_RW_MIN);
|
|
|
printk(KERN_INFO "ide-tape: %s <-> %s: %dKBps, %d*%dkB buffer, "
|
|
|
"%dkB pipeline, %lums tDSC%s\n",
|
|
|
- drive->name, tape->name, tape->capabilities.speed,
|
|
|
- (tape->capabilities.buffer_size * 512) / tape->stage_size,
|
|
|
+ drive->name, tape->name, *(u16 *)&tape->caps[14],
|
|
|
+ (*(u16 *)&tape->caps[16] * 512) / tape->stage_size,
|
|
|
tape->stage_size / 1024,
|
|
|
tape->max_stages * tape->stage_size / 1024,
|
|
|
tape->best_dsc_rw_frequency * 1000 / HZ,
|