/*
* The following are used to debug the driver:
*
- * Setting IDETAPE_DEBUG_INFO to 1 will report device capabilities.
* Setting IDETAPE_DEBUG_LOG to 1 will log driver flow control.
- * Setting IDETAPE_DEBUG_BUGS to 1 will enable self-sanity checks in
- * some places.
*
* Setting them to 0 will restore normal operation mode:
*
* is verified to be stable enough. This will make it much more
* esthetic.
*/
-#define IDETAPE_DEBUG_INFO 0
#define IDETAPE_DEBUG_LOG 0
-#define IDETAPE_DEBUG_BUGS 1
/*
* After each failed packet command we issue a request sense command
/* 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
*/
/* 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.
unsigned protocol :2; /* Protocol type */
};
-/*
- * INQUIRY packet command - Data Format (From Table 6-8 of QIC-157C)
- */
-typedef struct {
- unsigned device_type :5; /* Peripheral Device Type */
- unsigned reserved0_765 :3; /* Peripheral Qualifier - Reserved */
- unsigned reserved1_6t0 :7; /* Reserved */
- unsigned rmb :1; /* Removable Medium Bit */
- unsigned ansi_version :3; /* ANSI Version */
- unsigned ecma_version :3; /* ECMA Version */
- unsigned iso_version :2; /* ISO Version */
- unsigned response_format :4; /* Response Data Format */
- unsigned reserved3_45 :2; /* Reserved */
- unsigned reserved3_6 :1; /* TrmIOP - Reserved */
- unsigned reserved3_7 :1; /* AENC - Reserved */
- __u8 additional_length; /* Additional Length (total_length-4) */
- __u8 rsv5, rsv6, rsv7; /* Reserved */
- __u8 vendor_id[8]; /* Vendor Identification */
- __u8 product_id[16]; /* Product Identification */
- __u8 revision_level[4]; /* Revision Level */
- __u8 vendor_specific[20]; /* Vendor Specific - Optional */
- __u8 reserved56t95[40]; /* Reserved - Optional */
- /* Additional information may be returned */
-} idetape_inquiry_result_t;
-
/*
* READ POSITION packet command - Data Format (From Table 6-57)
*/
#define IDETAPE_BLOCK_SIZE_PAGE 0x30
#define IDETAPE_BUFFER_FILLING_PAGE 0x33
-/*
- * Mode Parameter Header for the MODE SENSE packet command
- */
-typedef struct {
- __u8 mode_data_length; /* Length of the following data transfer */
- __u8 medium_type; /* Medium Type */
- __u8 dsp; /* Device Specific Parameter */
- __u8 bdl; /* Block Descriptor Length */
-} idetape_mode_parameter_header_t;
-
/*
* Mode Parameter Block Descriptor the MODE SENSE packet command
*
__u8 length[3]; /* Block Length */
} idetape_parameter_block_descriptor_t;
-/*
- * The Data Compression Page, as returned by the MODE SENSE packet command.
- */
-typedef struct {
- unsigned page_code :6; /* Page Code - Should be 0xf */
- unsigned reserved0 :1; /* Reserved */
- unsigned ps :1;
- __u8 page_length; /* Page Length - Should be 14 */
- unsigned reserved2 :6; /* Reserved */
- unsigned dcc :1; /* Data Compression Capable */
- unsigned dce :1; /* Data Compression Enable */
- unsigned reserved3 :5; /* Reserved */
- unsigned red :2; /* Report Exception on Decompression */
- unsigned dde :1; /* Data Decompression Enable */
- __u32 ca; /* Compression Algorithm */
- __u32 da; /* Decompression Algorithm */
- __u8 reserved[4]; /* Reserved */
-} idetape_data_compression_page_t;
-
/*
* The Medium Partition Page, as returned by the MODE SENSE packet command.
*/
int count;
while (bcount) {
-#if IDETAPE_DEBUG_BUGS
if (bh == NULL) {
printk(KERN_ERR "ide-tape: bh == NULL in "
"idetape_input_buffers\n");
idetape_discard_data(drive, bcount);
return;
}
-#endif /* IDETAPE_DEBUG_BUGS */
count = min((unsigned int)(bh->b_size - atomic_read(&bh->b_count)), bcount);
HWIF(drive)->atapi_input_bytes(drive, bh->b_data + atomic_read(&bh->b_count), count);
bcount -= count;
int count;
while (bcount) {
-#if IDETAPE_DEBUG_BUGS
if (bh == NULL) {
printk(KERN_ERR "ide-tape: bh == NULL in "
"idetape_output_buffers\n");
return;
}
-#endif /* IDETAPE_DEBUG_BUGS */
count = min((unsigned int)pc->b_count, (unsigned int)bcount);
HWIF(drive)->atapi_output_bytes(drive, pc->b_data, count);
bcount -= count;
if (test_bit(PC_WRITING, &pc->flags))
return;
while (bcount) {
-#if IDETAPE_DEBUG_BUGS
if (bh == NULL) {
printk(KERN_ERR "ide-tape: bh == NULL in "
"idetape_update_buffers\n");
return;
}
-#endif /* IDETAPE_DEBUG_BUGS */
count = min((unsigned int)bh->b_size, (unsigned int)bcount);
atomic_set(&bh->b_count, count);
if (atomic_read(&bh->b_count) == bh->b_size)
if (tape->debug_level >= 4)
printk(KERN_INFO "ide-tape: Reached idetape_active_next_stage\n");
#endif /* IDETAPE_DEBUG_LOG */
-#if IDETAPE_DEBUG_BUGS
if (stage == NULL) {
printk(KERN_ERR "ide-tape: bug: Trying to activate a non existing stage\n");
return;
}
-#endif /* IDETAPE_DEBUG_BUGS */
rq->rq_disk = tape->disk;
rq->buffer = NULL;
if (tape->debug_level >= 4)
printk(KERN_INFO "ide-tape: Reached idetape_remove_stage_head\n");
#endif /* IDETAPE_DEBUG_LOG */
-#if IDETAPE_DEBUG_BUGS
if (tape->first_stage == NULL) {
printk(KERN_ERR "ide-tape: bug: tape->first_stage is NULL\n");
- return;
+ return;
}
if (tape->active_stage == tape->first_stage) {
printk(KERN_ERR "ide-tape: bug: Trying to free our active pipeline stage\n");
return;
}
-#endif /* IDETAPE_DEBUG_BUGS */
stage = tape->first_stage;
tape->first_stage = stage->next;
idetape_kfree_stage(tape, stage);
tape->nr_stages--;
if (tape->first_stage == NULL) {
tape->last_stage = NULL;
-#if IDETAPE_DEBUG_BUGS
if (tape->next_stage != NULL)
printk(KERN_ERR "ide-tape: bug: tape->next_stage != NULL\n");
if (tape->nr_stages)
printk(KERN_ERR "ide-tape: bug: nr_stages should be 0 now\n");
-#endif /* IDETAPE_DEBUG_BUGS */
}
}
int dma_ok = 0;
u16 bcount;
-#if IDETAPE_DEBUG_BUGS
if (tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD &&
pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
printk(KERN_ERR "ide-tape: possible ide-tape.c bug - "
"Two request sense in serial were issued\n");
}
-#endif /* IDETAPE_DEBUG_BUGS */
if (tape->failed_pc == NULL && pc->c[0] != IDETAPE_REQUEST_SENSE_CMD)
tape->failed_pc = pc;
tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
return idetape_issue_packet_command(drive, tape->failed_pc);
}
-#if IDETAPE_DEBUG_BUGS
if (postponed_rq != NULL)
if (rq != postponed_rq) {
printk(KERN_ERR "ide-tape: ide-tape.c bug - "
idetape_end_request(drive, 0, 0);
return ide_stopped;
}
-#endif /* IDETAPE_DEBUG_BUGS */
tape->postponed_rq = NULL;
int ret = 0;
while (n) {
-#if IDETAPE_DEBUG_BUGS
if (bh == NULL) {
printk(KERN_ERR "ide-tape: bh == NULL in "
"idetape_copy_stage_from_user\n");
return 1;
}
-#endif /* IDETAPE_DEBUG_BUGS */
count = min((unsigned int)(bh->b_size - atomic_read(&bh->b_count)), (unsigned int)n);
if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, count))
ret = 1;
int ret = 0;
while (n) {
-#if IDETAPE_DEBUG_BUGS
if (bh == NULL) {
printk(KERN_ERR "ide-tape: bh == NULL in "
"idetape_copy_stage_to_user\n");
return 1;
}
-#endif /* IDETAPE_DEBUG_BUGS */
count = min(tape->b_count, n);
if (copy_to_user(buf, tape->b_data, count))
ret = 1;
DECLARE_COMPLETION_ONSTACK(wait);
idetape_tape_t *tape = drive->driver_data;
-#if IDETAPE_DEBUG_BUGS
if (rq == NULL || !blk_special_request(rq)) {
printk (KERN_ERR "ide-tape: bug: Trying to sleep on non-valid request\n");
return;
}
-#endif /* IDETAPE_DEBUG_BUGS */
rq->end_io_data = &wait;
rq->end_io = blk_end_sync_rq;
spin_unlock_irq(&tape->spinlock);
{
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);
if (tape->debug_level >= 2)
printk(KERN_INFO "ide-tape: idetape_queue_rw_tail: cmd=%d\n",cmd);
#endif /* IDETAPE_DEBUG_LOG */
-#if IDETAPE_DEBUG_BUGS
if (idetape_pipeline_active(tape)) {
printk(KERN_ERR "ide-tape: bug: the pipeline is active in idetape_queue_rw_tail\n");
return (0);
}
-#endif /* IDETAPE_DEBUG_BUGS */
idetape_init_rq(&rq, cmd);
rq.rq_disk = tape->disk;
idetape_tape_t *tape = drive->driver_data;
int blocks, min;
struct idetape_bh *bh;
-
-#if IDETAPE_DEBUG_BUGS
+
if (tape->chrdev_direction != idetape_direction_write) {
printk(KERN_ERR "ide-tape: bug: Trying to empty write pipeline, but we are not writing.\n");
return;
printk(KERN_ERR "ide-tape: bug: merge_buffer too big\n");
tape->merge_stage_size = tape->stage_size;
}
-#endif /* IDETAPE_DEBUG_BUGS */
if (tape->merge_stage_size) {
blocks = tape->merge_stage_size / tape->tape_block_size;
if (tape->merge_stage_size % tape->tape_block_size) {
* can be totally different on the next backup).
*/
tape->max_stages = tape->min_pipeline;
-#if IDETAPE_DEBUG_BUGS
if (tape->first_stage != NULL ||
tape->next_stage != NULL ||
tape->last_stage != NULL ||
tape->first_stage, tape->next_stage,
tape->last_stage, tape->nr_stages);
}
-#endif /* IDETAPE_DEBUG_BUGS */
}
static void idetape_restart_speed_control (ide_drive_t *drive)
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_empty_write_pipeline(drive);
idetape_flush_tape_buffers(drive);
}
-#if IDETAPE_DEBUG_BUGS
if (tape->merge_stage || tape->merge_stage_size) {
printk (KERN_ERR "ide-tape: merge_stage_size should be 0 now\n");
tape->merge_stage_size = 0;
}
-#endif /* IDETAPE_DEBUG_BUGS */
if ((tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0)) == NULL)
return -ENOMEM;
tape->chrdev_direction = idetape_direction_read;
tape->pipeline_head++;
calculate_speeds(drive);
}
-#if IDETAPE_DEBUG_BUGS
if (bytes_read > blocks * tape->tape_block_size) {
printk(KERN_ERR "ide-tape: bug: trying to return more bytes than requested\n");
bytes_read = blocks * tape->tape_block_size;
}
-#endif /* IDETAPE_DEBUG_BUGS */
return (bytes_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->chrdev_direction != idetape_direction_write) {
if (tape->chrdev_direction == idetape_direction_read)
idetape_discard_read_pipeline(drive, 1);
-#if IDETAPE_DEBUG_BUGS
if (tape->merge_stage || tape->merge_stage_size) {
printk(KERN_ERR "ide-tape: merge_stage_size "
"should be 0 now\n");
tape->merge_stage_size = 0;
}
-#endif /* IDETAPE_DEBUG_BUGS */
if ((tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0)) == NULL)
return -ENOMEM;
tape->chrdev_direction = idetape_direction_write;
if (tape->restart_speed_control_req)
idetape_restart_speed_control(drive);
if (tape->merge_stage_size) {
-#if IDETAPE_DEBUG_BUGS
if (tape->merge_stage_size >= tape->stage_size) {
printk(KERN_ERR "ide-tape: bug: merge buffer too big\n");
tape->merge_stage_size = 0;
}
-#endif /* IDETAPE_DEBUG_BUGS */
actually_written = min((unsigned int)(tape->stage_size - tape->merge_stage_size), (unsigned int)count);
if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, actually_written))
ret = -EFAULT;
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);
*((unsigned short *) &gcw) = id->config;
-#if IDETAPE_DEBUG_INFO
- printk(KERN_INFO "ide-tape: Dumping ATAPI Identify Device tape parameters\n");
- printk(KERN_INFO "ide-tape: Protocol Type: ");
- switch (gcw.protocol) {
- case 0: case 1: printk("ATA\n");break;
- case 2: printk("ATAPI\n");break;
- case 3: printk("Reserved (Unknown to ide-tape)\n");break;
- }
- printk(KERN_INFO "ide-tape: Device Type: %x - ",gcw.device_type);
- switch (gcw.device_type) {
- case 0: printk("Direct-access Device\n");break;
- case 1: printk("Streaming Tape Device\n");break;
- case 2: case 3: case 4: printk("Reserved\n");break;
- case 5: printk("CD-ROM Device\n");break;
- case 6: printk("Reserved\n");
- case 7: printk("Optical memory Device\n");break;
- case 0x1f: printk("Unknown or no Device type\n");break;
- default: printk("Reserved\n");
- }
- printk(KERN_INFO "ide-tape: Removable: %s",gcw.removable ? "Yes\n":"No\n");
- printk(KERN_INFO "ide-tape: Command Packet DRQ Type: ");
- switch (gcw.drq_type) {
- case 0: printk("Microprocessor DRQ\n");break;
- case 1: printk("Interrupt DRQ\n");break;
- case 2: printk("Accelerated DRQ\n");break;
- case 3: printk("Reserved\n");break;
- }
- printk(KERN_INFO "ide-tape: Command Packet Size: ");
- switch (gcw.packet_size) {
- case 0: printk("12 bytes\n");break;
- case 1: printk("16 bytes\n");break;
- default: printk("Reserved\n");break;
- }
-#endif /* IDETAPE_DEBUG_INFO */
-
/* Check that we can support this device */
- if (gcw.protocol !=2 )
- printk(KERN_ERR "ide-tape: Protocol is not ATAPI\n");
+ if (gcw.protocol != 2)
+ printk(KERN_ERR "ide-tape: Protocol (0x%02x) is not ATAPI\n",
+ gcw.protocol);
else if (gcw.device_type != 1)
- printk(KERN_ERR "ide-tape: Device type is not set to tape\n");
+ printk(KERN_ERR "ide-tape: Device type (0x%02x) is not set "
+ "to tape\n", gcw.device_type);
else if (!gcw.removable)
printk(KERN_ERR "ide-tape: The removable flag is not set\n");
else if (gcw.packet_size != 0) {
- printk(KERN_ERR "ide-tape: Packet size is not 12 bytes long\n");
- if (gcw.packet_size == 1)
- printk(KERN_ERR "ide-tape: Sorry, padding to 16 bytes is still not supported\n");
+ printk(KERN_ERR "ide-tape: Packet size (0x%02x) is not 12 "
+ "bytes long\n", gcw.packet_size);
} else
return 1;
return 0;
}
-/*
- * Use INQUIRY to get the firmware revision
- */
-static void idetape_get_inquiry_results (ide_drive_t *drive)
+static void idetape_get_inquiry_results(ide_drive_t *drive)
{
char *r;
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t pc;
- idetape_inquiry_result_t *inquiry;
-
+
idetape_create_inquiry_cmd(&pc);
if (idetape_queue_pc_tail(drive, &pc)) {
- printk(KERN_ERR "ide-tape: %s: can't get INQUIRY results\n", tape->name);
+ printk(KERN_ERR "ide-tape: %s: can't get INQUIRY results\n",
+ tape->name);
return;
}
- inquiry = (idetape_inquiry_result_t *) pc.buffer;
- memcpy(tape->vendor_id, inquiry->vendor_id, 8);
- memcpy(tape->product_id, inquiry->product_id, 16);
- memcpy(tape->firmware_revision, inquiry->revision_level, 4);
+ memcpy(tape->vendor_id, &pc.buffer[8], 8);
+ memcpy(tape->product_id, &pc.buffer[16], 16);
+ memcpy(tape->firmware_revision, &pc.buffer[32], 4);
+
ide_fixstring(tape->vendor_id, 10, 0);
ide_fixstring(tape->product_id, 18, 0);
ide_fixstring(tape->firmware_revision, 6, 0);
r = tape->firmware_revision;
if (*(r + 1) == '.')
- tape->firmware_revision_num = (*r - '0') * 100 + (*(r + 2) - '0') * 10 + *(r + 3) - '0';
- printk(KERN_INFO "ide-tape: %s <-> %s: %s %s rev %s\n", drive->name, tape->name, tape->vendor_id, tape->product_id, tape->firmware_revision);
+ tape->firmware_revision_num = (*r - '0') * 100 +
+ (*(r + 2) - '0') * 10 + *(r + 3) - '0';
+ printk(KERN_INFO "ide-tape: %s <-> %s: %s %s rev %s\n",
+ drive->name, tape->name, tape->vendor_id,
+ tape->product_id, tape->firmware_revision);
}
/*
- * 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_mode_parameter_header_t *header;
- 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;
}
- header = (idetape_mode_parameter_header_t *) pc.buffer;
- capabilities = (idetape_capabilities_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl);
+ 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;
-
-#if IDETAPE_DEBUG_INFO
- printk(KERN_INFO "ide-tape: Dumping the results of the MODE SENSE packet command\n");
- printk(KERN_INFO "ide-tape: Mode Parameter Header:\n");
- printk(KERN_INFO "ide-tape: Mode Data Length - %d\n",header->mode_data_length);
- printk(KERN_INFO "ide-tape: Medium Type - %d\n",header->medium_type);
- printk(KERN_INFO "ide-tape: Device Specific Parameter - %d\n",header->dsp);
- printk(KERN_INFO "ide-tape: Block Descriptor Length - %d\n",header->bdl);
-
- printk(KERN_INFO "ide-tape: Capabilities and Mechanical Status Page:\n");
- printk(KERN_INFO "ide-tape: Page code - %d\n",capabilities->page_code);
- printk(KERN_INFO "ide-tape: Page length - %d\n",capabilities->page_length);
- printk(KERN_INFO "ide-tape: Read only - %s\n",capabilities->ro ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Supports reverse space - %s\n",capabilities->sprev ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Supports erase initiated formatting - %s\n",capabilities->efmt ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Supports QFA two Partition format - %s\n",capabilities->qfa ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Supports locking the medium - %s\n",capabilities->lock ? "Yes":"No");
- printk(KERN_INFO "ide-tape: The volume is currently locked - %s\n",capabilities->locked ? "Yes":"No");
- printk(KERN_INFO "ide-tape: The device defaults in the prevent state - %s\n",capabilities->prevent ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Supports ejecting the medium - %s\n",capabilities->eject ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Supports error correction - %s\n",capabilities->ecc ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Supports data compression - %s\n",capabilities->cmprs ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Supports 512 bytes block size - %s\n",capabilities->blk512 ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Supports 1024 bytes block size - %s\n",capabilities->blk1024 ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Supports 32768 bytes block size / Restricted byte count for PIO transfers - %s\n",capabilities->blk32768 ? "Yes":"No");
- printk(KERN_INFO "ide-tape: Maximum supported speed in KBps - %d\n",capabilities->max_speed);
- printk(KERN_INFO "ide-tape: Continuous transfer limits in blocks - %d\n",capabilities->ctl);
- printk(KERN_INFO "ide-tape: Current speed in KBps - %d\n",capabilities->speed);
- printk(KERN_INFO "ide-tape: Buffer size - %d\n",capabilities->buffer_size*512);
-#endif /* IDETAPE_DEBUG_INFO */
}
/*
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t pc;
- idetape_mode_parameter_header_t *header;
idetape_parameter_block_descriptor_t *block_descrp;
-
+
idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR);
if (idetape_queue_pc_tail(drive, &pc)) {
printk(KERN_ERR "ide-tape: Can't get block descriptor\n");
}
return;
}
- header = (idetape_mode_parameter_header_t *) pc.buffer;
- block_descrp = (idetape_parameter_block_descriptor_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t));
+ block_descrp = (idetape_parameter_block_descriptor_t *)(pc.buffer + 4);
tape->tape_block_size =( block_descrp->length[0]<<16) + (block_descrp->length[1]<<8) + block_descrp->length[2];
- tape->drv_write_prot = (header->dsp & 0x80) >> 7;
-
-#if IDETAPE_DEBUG_INFO
- printk(KERN_INFO "ide-tape: Adjusted block size - %d\n", tape->tape_block_size);
-#endif /* IDETAPE_DEBUG_INFO */
+ tape->drv_write_prot = (pc.buffer[2] & 0x80) >> 7;
}
#ifdef CONFIG_IDE_PROC_FS
/*
* 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,