diff options
-rw-r--r-- | drivers/ide/ide-tape.c | 142 |
1 files changed, 56 insertions, 86 deletions
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 3d15e8e729ef..6fa6a38d8116 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -260,47 +260,6 @@ typedef struct idetape_packet_command_s { #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 { @@ -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, |