/* 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.
 {
        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,