#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
*/
typedef struct {
/* 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.
{
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);
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) {
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;
}
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);
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)
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))
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);
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)
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);
}
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);
}
/*
- * 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;
}
/*
* 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);
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;
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;
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;
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)
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,