* Add struct ide_tp_ops for transport methods.
* Add 'const struct ide_tp_ops *tp_ops' to struct ide_port_info
  and ide_hwif_t.
* Set the default hwif->tp_ops in ide_init_port_data().
* Set host driver specific hwif->tp_ops in ide_init_port().
* Export ide_exec_command(), ide_read_status(), ide_read_altstatus(),
  ide_read_sff_dma_status(), ide_set_irq(), ide_tf_{load,read}()
  and ata_{in,out}put_data().
* Convert host drivers and core code to use struct ide_tp_ops.
* Remove no longer needed default_hwif_transport().
* Cleanup ide_hwif_t from methods that are now in struct ide_tp_ops.
While at it:
* Use struct ide_port_info in falconide.c and q40ide.c.
* Rename ata_{in,out}put_data() to ide_{in,out}put_data().
v2:
* Fix missing convertion in ns87415.c.
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
        if (icside_dma_test_irq(drive))
                return;
 
-       ide_dump_status(drive, "DMA timeout", hwif->read_status(hwif));
+       ide_dump_status(drive, "DMA timeout", hwif->tp_ops->read_status(hwif));
 
        icside_dma_end(drive);
 }
 
        mm_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
 }
 
+static const struct ide_tp_ops h8300_tp_ops = {
+       .exec_command           = ide_exec_command,
+       .read_status            = ide_read_status,
+       .read_altstatus         = ide_read_altstatus,
+       .read_sff_dma_status    = ide_read_sff_dma_status,
+
+       .set_irq                = ide_set_irq,
+
+       .tf_load                = h8300_tf_load,
+       .tf_read                = h8300_tf_read,
+
+       .input_data             = h8300_input_data,
+       .output_data            = h8300_output_data,
+};
+
 #define H8300_IDE_GAP (2)
 
 static inline void hw_setup(hw_regs_t *hw)
        hw->chipset = ide_generic;
 }
 
-static inline void hwif_setup(ide_hwif_t *hwif)
-{
-       hwif->tf_load = h8300_tf_load;
-       hwif->tf_read = h8300_tf_read;
-
-       hwif->input_data  = h8300_input_data;
-       hwif->output_data = h8300_output_data;
-}
-
 static const struct ide_port_info h8300_port_info = {
+       .tp_ops                 = &h8300_tp_ops,
        .host_flags             = IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_NO_DMA,
 };
 
                return -ENOENT;
 
        index = hwif->index;
-       hwif_setup(hwif);
 
        idx[0] = index;
 
 
        void (*io_buffers)(ide_drive_t *, struct ide_atapi_pc *, unsigned, int))
 {
        ide_hwif_t *hwif = drive->hwif;
+       const struct ide_tp_ops *tp_ops = hwif->tp_ops;
        xfer_func_t *xferfunc;
        unsigned int temp;
        u16 bcount;
        }
 
        /* Clear the interrupt */
-       stat = hwif->read_status(hwif);
+       stat = tp_ops->read_status(hwif);
 
        if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
                if (hwif->dma_ops->dma_end(drive) ||
                                        if (pc->sg)
                                                io_buffers(drive, pc, temp, 0);
                                        else
-                                               hwif->input_data(drive, NULL,
+                                               tp_ops->input_data(drive, NULL,
                                                        pc->cur_pos, temp);
                                        printk(KERN_ERR "%s: transferred %d of "
                                                        "%d bytes\n",
                        debug_log("The device wants to send us more data than "
                                  "expected - allowing transfer\n");
                }
-               xferfunc = hwif->input_data;
+               xferfunc = tp_ops->input_data;
        } else
-               xferfunc = hwif->output_data;
+               xferfunc = tp_ops->output_data;
 
        if ((drive->media == ide_floppy && !scsi && !pc->buf) ||
            (drive->media == ide_tape && !scsi && pc->bh) ||
        memset(&task, 0, sizeof(task));
        task.tf_flags = IDE_TFLAG_IN_NSECT;
 
-       drive->hwif->tf_read(drive, &task);
+       drive->hwif->tp_ops->tf_read(drive, &task);
 
        return task.tf.nsect & 3;
 }
 
        /* Send the actual packet */
        if ((pc->flags & PC_FLAG_ZIP_DRIVE) == 0)
-               hwif->output_data(drive, NULL, pc->c, 12);
+               hwif->tp_ops->output_data(drive, NULL, pc->c, 12);
 
        return ide_started;
 }
 
        int stat, err, sense_key;
 
        /* check for errors */
-       stat = hwif->read_status(hwif);
+       stat = hwif->tp_ops->read_status(hwif);
 
        if (stat_ret)
                *stat_ret = stat;
                cmd_len = ATAPI_MIN_CDB_BYTES;
 
        /* send the command to the device */
-       hwif->output_data(drive, NULL, rq->cmd, cmd_len);
+       hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len);
 
        /* start the DMA if need be */
        if (info->dma)
                 * Some drives (ASUS) seem to tell us that status info is
                 * available.  Just get it and ignore.
                 */
-               (void)hwif->read_status(hwif);
+               (void)hwif->tp_ops->read_status(hwif);
                return 0;
        } else {
                /* drive wants a command packet, or invalid ireason... */
 
        if (ireason == 0) {
                write = 1;
-               xferfunc = hwif->output_data;
+               xferfunc = hwif->tp_ops->output_data;
        } else {
                write = 0;
-               xferfunc = hwif->input_data;
+               xferfunc = hwif->tp_ops->input_data;
        }
 
        /* transfer data */
                if (info->cd_flags & IDE_CD_FLAG_SEEKING) {
                        ide_hwif_t *hwif = drive->hwif;
                        unsigned long elapsed = jiffies - info->start_seek;
-                       int stat = hwif->read_status(hwif);
+                       int stat = hwif->tp_ops->read_status(hwif);
 
                        if ((stat & SEEK_STAT) != SEEK_STAT) {
                                if (elapsed < IDECD_SEEK_TIMEOUT) {
 
        u8 stat = 0, dma_stat = 0;
 
        dma_stat = hwif->dma_ops->dma_end(drive);
-       stat = hwif->read_status(hwif);
+       stat = hwif->tp_ops->read_status(hwif);
 
        if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
                if (!dma_stat) {
 static int dma_timer_expiry (ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
-       u8 dma_stat             = hwif->read_sff_dma_status(hwif);
+       u8 dma_stat             = hwif->tp_ops->read_sff_dma_status(hwif);
 
        printk(KERN_WARNING "%s: dma_timer_expiry: dma status == 0x%02x\n",
                drive->name, dma_stat);
 {
        ide_hwif_t *hwif        = HWIF(drive);
        u8 unit                 = (drive->select.b.unit & 0x01);
-       u8 dma_stat             = hwif->read_sff_dma_status(hwif);
+       u8 dma_stat             = hwif->tp_ops->read_sff_dma_status(hwif);
 
        if (on)
                dma_stat |= (1 << (5 + unit));
                outb(reading, hwif->dma_base + ATA_DMA_CMD);
 
        /* read DMA status for INTR & ERROR flags */
-       dma_stat = hwif->read_sff_dma_status(hwif);
+       dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
 
        /* clear INTR & ERROR flags */
        if (mmio)
        }
 
        /* get DMA status */
-       dma_stat = hwif->read_sff_dma_status(hwif);
+       dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
 
        if (mmio)
                /* clear the INTR & ERROR bits */
 int ide_dma_test_irq(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
-       u8 dma_stat             = hwif->read_sff_dma_status(hwif);
+       u8 dma_stat             = hwif->tp_ops->read_sff_dma_status(hwif);
 
        /* return 1 if INTR asserted */
        if ((dma_stat & 4) == 4)
 
 
                data = bvec_kmap_irq(bvec, &flags);
                if (direction)
-                       hwif->output_data(drive, NULL, data, count);
+                       hwif->tp_ops->output_data(drive, NULL, data, count);
                else
-                       hwif->input_data(drive, NULL, data, count);
+                       hwif->tp_ops->input_data(drive, NULL, data, count);
                bvec_kunmap_irq(data, &flags);
 
                bcount -= count;
        idefloppy_floppy_t *floppy = drive->driver_data;
 
        /* Send the actual packet */
-       drive->hwif->output_data(drive, NULL, floppy->pc->c, 12);
+       drive->hwif->tp_ops->output_data(drive, NULL, floppy->pc->c, 12);
 
        /* Timeout for the packet command */
        return IDEFLOPPY_WAIT_CMD;
                u8 stat;
 
                local_irq_save(flags);
-               stat = hwif->read_status(hwif);
+               stat = hwif->tp_ops->read_status(hwif);
                local_irq_restore(flags);
 
                progress_indication = ((stat & SEEK_STAT) == 0) ? 0 : 0x10000;
 
                        tf->error = err;
                        tf->status = stat;
 
-                       drive->hwif->tf_read(drive, task);
+                       drive->hwif->tp_ops->tf_read(drive, task);
 
                        if (task->tf_flags & IDE_TFLAG_DYN)
                                kfree(task);
                if (err == ABRT_ERR) {
                        if (drive->select.b.lba &&
                            /* some newer drives don't support WIN_SPECIFY */
-                           hwif->read_status(hwif) == WIN_SPECIFY)
+                           hwif->tp_ops->read_status(hwif) == WIN_SPECIFY)
                                return ide_stopped;
                } else if ((err & BAD_CRC) == BAD_CRC) {
                        /* UDMA crc error, just retry the operation */
                return ide_stopped;
        }
 
-       if (hwif->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
+       if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
                rq->errors |= ERROR_RESET;
 
        if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
                /* add decoding error stuff */
        }
 
-       if (hwif->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
+       if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
                /* force an abort */
-               hwif->exec_command(hwif, WIN_IDLEIMMEDIATE);
+               hwif->tp_ops->exec_command(hwif, WIN_IDLEIMMEDIATE);
 
        if (rq->errors >= ERROR_MAX) {
                ide_kill_rq(drive, rq);
 #ifdef DEBUG
        printk("%s: DRIVE_CMD (null)\n", drive->name);
 #endif
-       ide_end_drive_cmd(drive, hwif->read_status(hwif),
+       ide_end_drive_cmd(drive, hwif->tp_ops->read_status(hwif),
                          ide_read_error(drive));
 
        return ide_stopped;
                if (rc)
                        printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name);
                SELECT_DRIVE(drive);
-               hwif->set_irq(hwif, 1);
+               hwif->tp_ops->set_irq(hwif, 1);
                rc = ide_wait_not_busy(hwif, 100000);
                if (rc)
                        printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
                         * quirk_list may not like intr setups/cleanups
                         */
                        if (drive->quirk_list != 1)
-                               hwif->set_irq(hwif, 0);
+                               hwif->tp_ops->set_irq(hwif, 0);
                }
                hwgroup->hwif = hwif;
                hwgroup->drive = drive;
                printk(KERN_WARNING "%s: DMA timeout error\n", drive->name);
                (void)hwif->dma_ops->dma_end(drive);
                ret = ide_error(drive, "dma timeout error",
-                               hwif->read_status(hwif));
+                               hwif->tp_ops->read_status(hwif));
        } else {
                printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
                hwif->dma_ops->dma_timeout(drive);
                                } else
                                        startstop =
                                        ide_error(drive, "irq timeout",
-                                                 hwif->read_status(hwif));
+                                                 hwif->tp_ops->read_status(hwif));
                        }
                        drive->service_time = jiffies - drive->service_start;
                        spin_lock_irq(&ide_lock);
         */
        do {
                if (hwif->irq == irq) {
-                       stat = hwif->read_status(hwif);
+                       stat = hwif->tp_ops->read_status(hwif);
 
                        if (!OK_STAT(stat, READY_STAT, BAD_STAT)) {
                                /* Try to not flood the console with msgs */
                         * Whack the status register, just in case
                         * we have a leftover pending IRQ.
                         */
-                       (void)hwif->read_status(hwif);
+                       (void)hwif->tp_ops->read_status(hwif);
 #endif /* CONFIG_BLK_DEV_IDEPCI */
                }
                spin_unlock_irqrestore(&ide_lock, flags);
        task.tf.lbah    = (bcount >> 8) & 0xff;
 
        ide_tf_dump(drive->name, &task.tf);
-       hwif->set_irq(hwif, 1);
+       hwif->tp_ops->set_irq(hwif, 1);
        SELECT_MASK(drive, 0);
-       hwif->tf_load(drive, &task);
+       hwif->tp_ops->tf_load(drive, &task);
 }
 
 EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load);
 
        while (len > 0) {
                if (write)
-                       hwif->output_data(drive, NULL, buf, min(4, len));
+                       hwif->tp_ops->output_data(drive, NULL, buf, min(4, len));
                else
-                       hwif->input_data(drive, NULL, buf, min(4, len));
+                       hwif->tp_ops->input_data(drive, NULL, buf, min(4, len));
                len -= 4;
        }
 }
 
        memset(&task, 0, sizeof(task));
        task.tf_flags = IDE_TFLAG_OUT_DEVICE;
 
-       drive->hwif->tf_load(drive, &task);
+       drive->hwif->tp_ops->tf_load(drive, &task);
 }
 
 void SELECT_MASK(ide_drive_t *drive, int mask)
                port_ops->maskproc(drive, mask);
 }
 
-static void ide_exec_command(ide_hwif_t *hwif, u8 cmd)
+void ide_exec_command(ide_hwif_t *hwif, u8 cmd)
 {
        if (hwif->host_flags & IDE_HFLAG_MMIO)
                writeb(cmd, (void __iomem *)hwif->io_ports.command_addr);
        else
                outb(cmd, hwif->io_ports.command_addr);
 }
+EXPORT_SYMBOL_GPL(ide_exec_command);
 
-static u8 ide_read_status(ide_hwif_t *hwif)
+u8 ide_read_status(ide_hwif_t *hwif)
 {
        if (hwif->host_flags & IDE_HFLAG_MMIO)
                return readb((void __iomem *)hwif->io_ports.status_addr);
        else
                return inb(hwif->io_ports.status_addr);
 }
+EXPORT_SYMBOL_GPL(ide_read_status);
 
-static u8 ide_read_altstatus(ide_hwif_t *hwif)
+u8 ide_read_altstatus(ide_hwif_t *hwif)
 {
        if (hwif->host_flags & IDE_HFLAG_MMIO)
                return readb((void __iomem *)hwif->io_ports.ctl_addr);
        else
                return inb(hwif->io_ports.ctl_addr);
 }
+EXPORT_SYMBOL_GPL(ide_read_altstatus);
 
-static u8 ide_read_sff_dma_status(ide_hwif_t *hwif)
+u8 ide_read_sff_dma_status(ide_hwif_t *hwif)
 {
        if (hwif->host_flags & IDE_HFLAG_MMIO)
                return readb((void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
        else
                return inb(hwif->dma_base + ATA_DMA_STATUS);
 }
+EXPORT_SYMBOL_GPL(ide_read_sff_dma_status);
 
-static void ide_set_irq(ide_hwif_t *hwif, int on)
+void ide_set_irq(ide_hwif_t *hwif, int on)
 {
        u8 ctl = ATA_DEVCTL_OBS;
 
        else
                outb(ctl, hwif->io_ports.ctl_addr);
 }
+EXPORT_SYMBOL_GPL(ide_set_irq);
 
-static void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
+void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
 {
        ide_hwif_t *hwif = drive->hwif;
        struct ide_io_ports *io_ports = &hwif->io_ports;
                tf_outb((tf->device & HIHI) | drive->select.all,
                         io_ports->device_addr);
 }
+EXPORT_SYMBOL_GPL(ide_tf_load);
 
-static void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
+void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
 {
        ide_hwif_t *hwif = drive->hwif;
        struct ide_io_ports *io_ports = &hwif->io_ports;
                        tf->hob_lbah    = tf_inb(io_ports->lbah_addr);
        }
 }
+EXPORT_SYMBOL_GPL(ide_tf_read);
 
 /*
  * Some localbus EIDE interfaces require a special access sequence
  * so if an odd len is specified, be sure that there's at least one
  * extra byte allocated for the buffer.
  */
-static void ata_input_data(ide_drive_t *drive, struct request *rq,
-                          void *buf, unsigned int len)
+void ide_input_data(ide_drive_t *drive, struct request *rq, void *buf,
+                   unsigned int len)
 {
        ide_hwif_t *hwif = drive->hwif;
        struct ide_io_ports *io_ports = &hwif->io_ports;
                        insw(data_addr, buf, len / 2);
        }
 }
+EXPORT_SYMBOL_GPL(ide_input_data);
 
 /*
  * This is used for most PIO data transfers *to* the IDE interface
  */
-static void ata_output_data(ide_drive_t *drive, struct request *rq,
-                           void *buf, unsigned int len)
+void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf,
+                    unsigned int len)
 {
        ide_hwif_t *hwif = drive->hwif;
        struct ide_io_ports *io_ports = &hwif->io_ports;
                        outsw(data_addr, buf, len / 2);
        }
 }
-
-void default_hwif_transport(ide_hwif_t *hwif)
-{
-       hwif->exec_command        = ide_exec_command;
-       hwif->read_status         = ide_read_status;
-       hwif->read_altstatus      = ide_read_altstatus;
-       hwif->read_sff_dma_status = ide_read_sff_dma_status;
-
-       hwif->set_irq     = ide_set_irq;
-
-       hwif->tf_load     = ide_tf_load;
-       hwif->tf_read     = ide_tf_read;
-
-       hwif->input_data  = ata_input_data;
-       hwif->output_data = ata_output_data;
-}
+EXPORT_SYMBOL_GPL(ide_output_data);
 
 u8 ide_read_error(ide_drive_t *drive)
 {
        memset(&task, 0, sizeof(task));
        task.tf_flags = IDE_TFLAG_IN_FEATURE;
 
-       drive->hwif->tf_read(drive, &task);
+       drive->hwif->tp_ops->tf_read(drive, &task);
 
        return task.tf.error;
 }
        task.tf_flags = IDE_TFLAG_IN_LBAH | IDE_TFLAG_IN_LBAM |
                        IDE_TFLAG_IN_NSECT;
 
-       drive->hwif->tf_read(drive, &task);
+       drive->hwif->tp_ops->tf_read(drive, &task);
 
        *bcount = (task.tf.lbah << 8) | task.tf.lbam;
        *ireason = task.tf.nsect & 3;
 }
 EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason);
 
+const struct ide_tp_ops default_tp_ops = {
+       .exec_command           = ide_exec_command,
+       .read_status            = ide_read_status,
+       .read_altstatus         = ide_read_altstatus,
+       .read_sff_dma_status    = ide_read_sff_dma_status,
+
+       .set_irq                = ide_set_irq,
+
+       .tf_load                = ide_tf_load,
+       .tf_read                = ide_tf_read,
+
+       .input_data             = ide_input_data,
+       .output_data            = ide_output_data,
+};
+
 void ide_fix_driveid (struct hd_driveid *id)
 {
 #ifndef __LITTLE_ENDIAN
         * about possible isa-pnp and pci-pnp issues yet.
         */
        if (hwif->io_ports.ctl_addr)
-               stat = hwif->read_altstatus(hwif);
+               stat = hwif->tp_ops->read_altstatus(hwif);
        else
                /* Note: this may clear a pending IRQ!! */
-               stat = hwif->read_status(hwif);
+               stat = hwif->tp_ops->read_status(hwif);
 
        if (stat & BUSY_STAT)
                /* drive busy:  definitely not interrupting */
 static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout, u8 *rstat)
 {
        ide_hwif_t *hwif = drive->hwif;
+       const struct ide_tp_ops *tp_ops = hwif->tp_ops;
        unsigned long flags;
        int i;
        u8 stat;
 
        udelay(1);      /* spec allows drive 400ns to assert "BUSY" */
-       stat = hwif->read_status(hwif);
+       stat = tp_ops->read_status(hwif);
 
        if (stat & BUSY_STAT) {
                local_irq_set(flags);
                timeout += jiffies;
-               while ((stat = hwif->read_status(hwif)) & BUSY_STAT) {
+               while ((stat = tp_ops->read_status(hwif)) & BUSY_STAT) {
                        if (time_after(jiffies, timeout)) {
                                /*
                                 * One last read after the timeout in case
                                 * heavy interrupt load made us not make any
                                 * progress during the timeout..
                                 */
-                               stat = hwif->read_status(hwif);
+                               stat = tp_ops->read_status(hwif);
                                if (!(stat & BUSY_STAT))
                                        break;
 
         */
        for (i = 0; i < 10; i++) {
                udelay(1);
-               stat = hwif->read_status(hwif);
+               stat = tp_ops->read_status(hwif);
 
                if (OK_STAT(stat, good, bad)) {
                        *rstat = stat;
 int ide_driveid_update(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
+       const struct ide_tp_ops *tp_ops = hwif->tp_ops;
        struct hd_driveid *id;
        unsigned long timeout, flags;
        u8 stat;
         */
 
        SELECT_MASK(drive, 1);
-       hwif->set_irq(hwif, 0);
+       tp_ops->set_irq(hwif, 0);
        msleep(50);
-       hwif->exec_command(hwif, WIN_IDENTIFY);
+       tp_ops->exec_command(hwif, WIN_IDENTIFY);
        timeout = jiffies + WAIT_WORSTCASE;
        do {
                if (time_after(jiffies, timeout)) {
                }
 
                msleep(50);     /* give drive a breather */
-               stat = hwif->read_altstatus(hwif);
+               stat = tp_ops->read_altstatus(hwif);
        } while (stat & BUSY_STAT);
 
        msleep(50);     /* wait for IRQ and DRQ_STAT */
-       stat = hwif->read_status(hwif);
+       stat = tp_ops->read_status(hwif);
 
        if (!OK_STAT(stat, DRQ_STAT, BAD_R_STAT)) {
                SELECT_MASK(drive, 0);
                local_irq_restore(flags);
                return 0;
        }
-       hwif->input_data(drive, NULL, id, SECTOR_SIZE);
-       (void)hwif->read_status(hwif);  /* clear drive IRQ */
+       tp_ops->input_data(drive, NULL, id, SECTOR_SIZE);
+       (void)tp_ops->read_status(hwif);        /* clear drive IRQ */
        local_irq_enable();
        local_irq_restore(flags);
        ide_fix_driveid(id);
 int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
 {
        ide_hwif_t *hwif = drive->hwif;
+       const struct ide_tp_ops *tp_ops = hwif->tp_ops;
        int error = 0;
        u8 stat;
        ide_task_t task;
        SELECT_DRIVE(drive);
        SELECT_MASK(drive, 0);
        udelay(1);
-       hwif->set_irq(hwif, 0);
+       tp_ops->set_irq(hwif, 0);
 
        memset(&task, 0, sizeof(task));
        task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT;
        task.tf.feature = SETFEATURES_XFER;
        task.tf.nsect   = speed;
 
-       hwif->tf_load(drive, &task);
+       tp_ops->tf_load(drive, &task);
 
-       hwif->exec_command(hwif, WIN_SETFEATURES);
+       tp_ops->exec_command(hwif, WIN_SETFEATURES);
 
        if (drive->quirk_list == 2)
-               hwif->set_irq(hwif, 1);
+               tp_ops->set_irq(hwif, 1);
 
        error = __ide_wait_stat(drive, drive->ready_stat,
                                BUSY_STAT|DRQ_STAT|ERR_STAT,
 
        spin_lock_irqsave(&ide_lock, flags);
        __ide_set_handler(drive, handler, timeout, expiry);
-       hwif->exec_command(hwif, cmd);
+       hwif->tp_ops->exec_command(hwif, cmd);
        /*
         * Drive takes 400nS to respond, we must avoid the IRQ being
         * serviced before that.
        unsigned long flags;
 
        spin_lock_irqsave(&ide_lock, flags);
-       hwif->exec_command(hwif, WIN_PACKETCMD);
+       hwif->tp_ops->exec_command(hwif, WIN_PACKETCMD);
        ndelay(400);
        spin_unlock_irqrestore(&ide_lock, flags);
 }
 
        SELECT_DRIVE(drive);
        udelay (10);
-       stat = hwif->read_status(hwif);
+       stat = hwif->tp_ops->read_status(hwif);
 
        if (OK_STAT(stat, 0, BUSY_STAT))
                printk("%s: ATAPI reset complete\n", drive->name);
                }
        }
 
-       tmp = hwif->read_status(hwif);
+       tmp = hwif->tp_ops->read_status(hwif);
 
        if (!OK_STAT(tmp, 0, BUSY_STAT)) {
                if (time_before(jiffies, hwgroup->poll_timeout)) {
        ide_hwif_t *hwif;
        ide_hwgroup_t *hwgroup;
        struct ide_io_ports *io_ports;
+       const struct ide_tp_ops *tp_ops;
        const struct ide_port_ops *port_ops;
 
        spin_lock_irqsave(&ide_lock, flags);
 
        io_ports = &hwif->io_ports;
 
+       tp_ops = hwif->tp_ops;
+
        /* We must not reset with running handlers */
        BUG_ON(hwgroup->handler != NULL);
 
                pre_reset(drive);
                SELECT_DRIVE(drive);
                udelay (20);
-               hwif->exec_command(hwif, WIN_SRST);
+               tp_ops->exec_command(hwif, WIN_SRST);
                ndelay(400);
                hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
                hwgroup->polling = 1;
         * TODO: add ->softreset method and stop abusing ->set_irq
         */
        /* set SRST and nIEN */
-       hwif->set_irq(hwif, 4);
+       tp_ops->set_irq(hwif, 4);
        /* more than enough time */
        udelay(10);
        /* clear SRST, leave nIEN (unless device is on the quirk list) */
-       hwif->set_irq(hwif, drive->quirk_list == 2);
+       tp_ops->set_irq(hwif, drive->quirk_list == 2);
        /* more than enough time */
        udelay(10);
        hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
                 * about locking issues (2.5 work ?).
                 */
                mdelay(1);
-               stat = hwif->read_status(hwif);
+               stat = hwif->tp_ops->read_status(hwif);
                if ((stat & BUSY_STAT) == 0)
                        return 0;
                /*
 
        else
                task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE;
 
-       drive->hwif->tf_read(drive, &task);
+       drive->hwif->tp_ops->tf_read(drive, &task);
 
        if (lba48 || (tf->device & ATA_LBA))
                printk(", LBAsect=%llu",
 
 
        id = drive->id;
        /* read 512 bytes of id info */
-       hwif->input_data(drive, NULL, id, SECTOR_SIZE);
+       hwif->tp_ops->input_data(drive, NULL, id, SECTOR_SIZE);
 
        drive->id_read = 1;
        local_irq_enable();
 {
        ide_hwif_t *hwif = HWIF(drive);
        struct ide_io_ports *io_ports = &hwif->io_ports;
+       const struct ide_tp_ops *tp_ops = hwif->tp_ops;
        int use_altstatus = 0, rc;
        unsigned long timeout;
        u8 s = 0, a = 0;
        msleep(50);
 
        if (io_ports->ctl_addr) {
-               a = hwif->read_altstatus(hwif);
-               s = hwif->read_status(hwif);
+               a = tp_ops->read_altstatus(hwif);
+               s = tp_ops->read_status(hwif);
                if ((a ^ s) & ~INDEX_STAT)
                        /* ancient Seagate drives, broken interfaces */
                        printk(KERN_INFO "%s: probing with STATUS(0x%02x) "
                /* disable DMA & overlap */
                task.tf_flags = IDE_TFLAG_OUT_FEATURE;
 
-               drive->hwif->tf_load(drive, &task);
+               tp_ops->tf_load(drive, &task);
        }
 
        /* ask drive for ID */
-       hwif->exec_command(hwif, cmd);
+       tp_ops->exec_command(hwif, cmd);
 
        timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
        timeout += jiffies;
                }
                /* give drive a breather */
                msleep(50);
-               s = use_altstatus ? hwif->read_altstatus(hwif)
-                                 : hwif->read_status(hwif);
+               s = use_altstatus ? tp_ops->read_altstatus(hwif)
+                                 : tp_ops->read_status(hwif);
        } while (s & BUSY_STAT);
 
        /* wait for IRQ and DRQ_STAT */
        msleep(50);
-       s = hwif->read_status(hwif);
+       s = tp_ops->read_status(hwif);
 
        if (OK_STAT(s, DRQ_STAT, BAD_R_STAT)) {
                unsigned long flags;
                /* drive responded with ID */
                rc = 0;
                /* clear drive IRQ */
-               (void)hwif->read_status(hwif);
+               (void)tp_ops->read_status(hwif);
                local_irq_restore(flags);
        } else {
                /* drive refused ID */
 static int try_to_identify (ide_drive_t *drive, u8 cmd)
 {
        ide_hwif_t *hwif = HWIF(drive);
+       const struct ide_tp_ops *tp_ops = hwif->tp_ops;
        int retval;
        int autoprobe = 0;
        unsigned long cookie = 0;
                        autoprobe = 1;
                        cookie = probe_irq_on();
                }
-               hwif->set_irq(hwif, autoprobe);
+               tp_ops->set_irq(hwif, autoprobe);
        }
 
        retval = actual_try_to_identify(drive, cmd);
        if (autoprobe) {
                int irq;
 
-               hwif->set_irq(hwif, 0);
+               tp_ops->set_irq(hwif, 0);
                /* clear drive IRQ */
-               (void)hwif->read_status(hwif);
+               (void)tp_ops->read_status(hwif);
                udelay(5);
                irq = probe_irq_off(cookie);
                if (!hwif->irq) {
 
        do {
                msleep(50);
-               stat = hwif->read_status(hwif);
+               stat = hwif->tp_ops->read_status(hwif);
                if ((stat & BUSY_STAT) == 0)
                        return 0;
        } while (time_before(jiffies, timeout));
        memset(&task, 0, sizeof(task));
        task.tf_flags = IDE_TFLAG_IN_DEVICE;
 
-       drive->hwif->tf_read(drive, &task);
+       drive->hwif->tp_ops->tf_read(drive, &task);
 
        return task.tf.device;
 }
 static int do_probe (ide_drive_t *drive, u8 cmd)
 {
        ide_hwif_t *hwif = HWIF(drive);
+       const struct ide_tp_ops *tp_ops = hwif->tp_ops;
        int rc;
        u8 stat;
 
                return 3;
        }
 
-       stat = hwif->read_status(hwif);
+       stat = tp_ops->read_status(hwif);
 
        if (OK_STAT(stat, READY_STAT, BUSY_STAT) ||
            drive->present || cmd == WIN_PIDENTIFY) {
                        rc = try_to_identify(drive,cmd);
                }
 
-               stat = hwif->read_status(hwif);
+               stat = tp_ops->read_status(hwif);
 
                if (stat == (BUSY_STAT | READY_STAT))
                        return 4;
                        msleep(50);
                        SELECT_DRIVE(drive);
                        msleep(50);
-                       hwif->exec_command(hwif, WIN_SRST);
+                       tp_ops->exec_command(hwif, WIN_SRST);
                        (void)ide_busy_sleep(hwif);
                        rc = try_to_identify(drive, cmd);
                }
 
                /* ensure drive IRQ is clear */
-               stat = hwif->read_status(hwif);
+               stat = tp_ops->read_status(hwif);
 
                if (rc == 1)
                        printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
                SELECT_DRIVE(&hwif->drives[0]);
                msleep(50);
                /* ensure drive irq is clear */
-               (void)hwif->read_status(hwif);
+               (void)tp_ops->read_status(hwif);
        }
        return rc;
 }
 static void enable_nest (ide_drive_t *drive)
 {
        ide_hwif_t *hwif = HWIF(drive);
+       const struct ide_tp_ops *tp_ops = hwif->tp_ops;
        u8 stat;
 
        printk("%s: enabling %s -- ", hwif->name, drive->id->model);
        SELECT_DRIVE(drive);
        msleep(50);
-       hwif->exec_command(hwif, EXABYTE_ENABLE_NEST);
+       tp_ops->exec_command(hwif, EXABYTE_ENABLE_NEST);
 
        if (ide_busy_sleep(hwif)) {
                printk(KERN_CONT "failed (timeout)\n");
 
        msleep(50);
 
-       stat = hwif->read_status(hwif);
+       stat = tp_ops->read_status(hwif);
 
        if (!OK_STAT(stat, 0, BAD_STAT))
                printk(KERN_CONT "failed (status = 0x%02x)\n", stat);
                /* Ignore disks that we will not probe for later. */
                if (!drive->noprobe || drive->present) {
                        SELECT_DRIVE(drive);
-                       hwif->set_irq(hwif, 1);
+                       hwif->tp_ops->set_irq(hwif, 1);
                        mdelay(2);
                        rc = ide_wait_not_busy(hwif, 35000);
                        if (rc)
                        sa = IRQF_SHARED;
 
                if (io_ports->ctl_addr)
-                       hwif->set_irq(hwif, 1);
+                       hwif->tp_ops->set_irq(hwif, 1);
 
                if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup))
                        goto out_unlink;
        hwif->host_flags |= d->host_flags;
        hwif->pio_mask = d->pio_mask;
 
+       if (d->tp_ops)
+               hwif->tp_ops = d->tp_ops;
+
        /* ->set_pio_mode for DTC2278 is currently limited to port 0 */
        if (hwif->chipset != ide_dtc2278 || hwif->channel == 0)
                hwif->port_ops = d->port_ops;
 
                count = min(
                        (unsigned int)(bh->b_size - atomic_read(&bh->b_count)),
                        bcount);
-               drive->hwif->input_data(drive, NULL, bh->b_data +
+               drive->hwif->tp_ops->input_data(drive, NULL, bh->b_data +
                                        atomic_read(&bh->b_count), count);
                bcount -= count;
                atomic_add(count, &bh->b_count);
                        return;
                }
                count = min((unsigned int)pc->b_count, (unsigned int)bcount);
-               drive->hwif->output_data(drive, NULL, pc->b_data, count);
+               drive->hwif->tp_ops->output_data(drive, NULL, pc->b_data, count);
                bcount -= count;
                pc->b_data += count;
                pc->b_count -= count;
        struct ide_atapi_pc *pc = tape->pc;
        u8 stat;
 
-       stat = hwif->read_status(hwif);
+       stat = hwif->tp_ops->read_status(hwif);
 
        if (stat & SEEK_STAT) {
                if (stat & ERR_STAT) {
         * If the tape is still busy, postpone our request and service
         * the other device meanwhile.
         */
-       stat = hwif->read_status(hwif);
+       stat = hwif->tp_ops->read_status(hwif);
 
        if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2))
                set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
 
        ide_hwif_t *hwif        = HWIF(drive);
        struct ide_taskfile *tf = &task->tf;
        ide_handler_t *handler = NULL;
+       const struct ide_tp_ops *tp_ops = hwif->tp_ops;
        const struct ide_dma_ops *dma_ops = hwif->dma_ops;
 
        if (task->data_phase == TASKFILE_MULTI_IN ||
 
        if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) {
                ide_tf_dump(drive->name, tf);
-               hwif->set_irq(hwif, 1);
+               tp_ops->set_irq(hwif, 1);
                SELECT_MASK(drive, 0);
-               hwif->tf_load(drive, task);
+               tp_ops->tf_load(drive, task);
        }
 
        switch (task->data_phase) {
        case TASKFILE_MULTI_OUT:
        case TASKFILE_OUT:
-               hwif->exec_command(hwif, tf->command);
+               tp_ops->exec_command(hwif, tf->command);
                ndelay(400);    /* FIXME */
                return pre_task_out_intr(drive, task->rq);
        case TASKFILE_MULTI_IN:
 static ide_startstop_t set_multmode_intr(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
-       u8 stat = hwif->read_status(hwif);
+       u8 stat = hwif->tp_ops->read_status(hwif);
 
        if (OK_STAT(stat, READY_STAT, BAD_STAT))
                drive->mult_count = drive->mult_req;
        int retries = 5;
        u8 stat;
 
-       while (((stat = hwif->read_status(hwif)) & BUSY_STAT) && retries--)
+       while (1) {
+               stat = hwif->tp_ops->read_status(hwif);
+               if ((stat & BUSY_STAT) == 0 || retries-- == 0)
+                       break;
                udelay(10);
+       };
 
        if (OK_STAT(stat, READY_STAT, BAD_STAT))
                return ide_stopped;
 static ide_startstop_t recal_intr(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
-       u8 stat = hwif->read_status(hwif);
+       u8 stat = hwif->tp_ops->read_status(hwif);
 
        if (!OK_STAT(stat, READY_STAT, BAD_STAT))
                return ide_error(drive, "recal_intr", stat);
        u8 stat;
 
        local_irq_enable_in_hardirq();
-       stat = hwif->read_status(hwif);
+       stat = hwif->tp_ops->read_status(hwif);
 
        if (!OK_STAT(stat, READY_STAT, BAD_STAT))
                return ide_error(drive, "task_no_data_intr", stat);
         * take up to 6 ms on some ATAPI devices, so we will wait max 10 ms.
         */
        for (retries = 0; retries < 1000; retries++) {
-               stat = hwif->read_status(hwif);
+               stat = hwif->tp_ops->read_status(hwif);
 
                if (stat & BUSY_STAT)
                        udelay(10);
 
        /* do the actual data transfer */
        if (write)
-               hwif->output_data(drive, rq, buf, SECTOR_SIZE);
+               hwif->tp_ops->output_data(drive, rq, buf, SECTOR_SIZE);
        else
-               hwif->input_data(drive, rq, buf, SECTOR_SIZE);
+               hwif->tp_ops->input_data(drive, rq, buf, SECTOR_SIZE);
 
        kunmap_atomic(buf, KM_BIO_SRC_IRQ);
 #ifdef CONFIG_HIGHMEM
 {
        ide_hwif_t *hwif = drive->hwif;
        struct request *rq = hwif->hwgroup->rq;
-       u8 stat = hwif->read_status(hwif);
+       u8 stat = hwif->tp_ops->read_status(hwif);
 
        /* Error? */
        if (stat & ERR_STAT)
 {
        ide_hwif_t *hwif = drive->hwif;
        struct request *rq = HWGROUP(drive)->rq;
-       u8 stat = hwif->read_status(hwif);
+       u8 stat = hwif->tp_ops->read_status(hwif);
 
        if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
                return task_error(drive, rq, __func__, stat);
 
 
        init_completion(&hwif->gendev_rel_comp);
 
-       default_hwif_transport(hwif);
+       hwif->tp_ops = &default_tp_ops;
 
        ide_port_init_devices_data(hwif);
 }
 
        outsw_swapw(data_addr, buf, (len + 1) / 2);
 }
 
+/* Atari has a byte-swapped IDE interface */
+static const struct ide_tp_ops falconide_tp_ops = {
+       .exec_command           = ide_exec_command,
+       .read_status            = ide_read_status,
+       .read_altstatus         = ide_read_altstatus,
+       .read_sff_dma_status    = ide_read_sff_dma_status,
+
+       .set_irq                = ide_set_irq,
+
+       .tf_load                = ide_tf_load,
+       .tf_read                = ide_tf_read,
+
+       .input_data             = falconide_input_data,
+       .output_data            = falconide_output_data,
+};
+
+static const struct ide_port_info falconide_port_info = {
+       .tp_ops                 = &falconide_tp_ops,
+       .host_flags             = IDE_HFLAG_NO_DMA,
+};
+
 static void __init falconide_setup_ports(hw_regs_t *hw)
 {
        int i;
                u8 index = hwif->index;
                u8 idx[4] = { index, 0xff, 0xff, 0xff };
 
-               /* Atari has a byte-swapped IDE interface */
-               hwif->input_data  = falconide_input_data;
-               hwif->output_data = falconide_output_data;
-
                ide_get_lock(NULL, NULL);
-               ide_device_add(idx, NULL, hws);
+               ide_device_add(idx, &falconide_port_info, hws);
                ide_release_lock();
        }
 
 
        outsw_swapw(data_addr, buf, (len + 1) / 2);
 }
 
+/* Q40 has a byte-swapped IDE interface */
+static const struct ide_tp_ops q40ide_tp_ops = {
+       .exec_command           = ide_exec_command,
+       .read_status            = ide_read_status,
+       .read_altstatus         = ide_read_altstatus,
+       .read_sff_dma_status    = ide_read_sff_dma_status,
+
+       .set_irq                = ide_set_irq,
+
+       .tf_load                = ide_tf_load,
+       .tf_read                = ide_tf_read,
+
+       .input_data             = q40ide_input_data,
+       .output_data            = q40ide_output_data,
+};
+
+static const struct ide_port_info q40ide_port_info = {
+       .tp_ops                 = &q40ide_tp_ops,
+       .host_flags             = IDE_HFLAG_NO_DMA,
+};
+
 /* 
  * the static array is needed to have the name reported in /proc/ioports,
  * hwif->name unfortunately isn't available yet
        if (hwif) {
                hwif->chipset = ide_generic;
 
-               /* Q40 has a byte-swapped IDE interface */
-               hwif->input_data  = q40ide_input_data;
-               hwif->output_data = q40ide_output_data;
-
                hws[i] = &hw[i];
                idx[i] = hwif->index;
        }
     }
 
-    ide_device_add(idx, NULL, hws);
+    ide_device_add(idx, &q40ide_port_info, hws);
 
     return 0;
 }
 
        *ata_regs = ahwif->regbase + (14 << IDE_REG_SHIFT);
 }
 
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+static const struct ide_tp_ops au1xxx_tp_ops = {
+       .exec_command           = ide_exec_command,
+       .read_status            = ide_read_status,
+       .read_altstatus         = ide_read_altstatus,
+       .read_sff_dma_status    = ide_read_sff_dma_status,
+
+       .set_irq                = ide_set_irq,
+
+       .tf_load                = ide_tf_load,
+       .tf_read                = ide_tf_read,
+
+       .input_data             = au1xxx_input_data,
+       .output_data            = au1xxx_output_data,
+};
+#endif
+
 static const struct ide_port_ops au1xxx_port_ops = {
        .set_pio_mode           = au1xxx_set_pio_mode,
        .set_dma_mode           = auide_set_dma_mode,
 
 static const struct ide_port_info au1xxx_port_info = {
        .init_dma               = auide_ddma_init,
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+       .tp_ops                 = &au1xxx_tp_ops,
+#endif
        .port_ops               = &au1xxx_port_ops,
 #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
        .dma_ops                = &au1xxx_dma_ops,
        hw.dev = dev;
        hw.chipset = ide_au1xxx;
 
-       /* If the user has selected DDMA assisted copies,
-          then set up a few local I/O function entry points 
-       */
-
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA     
-       hwif->input_data  = au1xxx_input_data;
-       hwif->output_data = au1xxx_output_data;
-#endif
-
        auide_hwif.hwif                 = hwif;
 
        idx[0] = hwif->index;
 
        }
 }
 
-static void __devinit superio_ide_init_iops (struct hwif_s *hwif)
+static const struct ide_tp_ops superio_tp_ops = {
+       .exec_command           = ide_exec_command,
+       .read_status            = superio_read_status,
+       .read_altstatus         = ide_read_altstatus,
+       .read_sff_dma_status    = superio_read_sff_dma_status,
+
+       .set_irq                = ide_set_irq,
+
+       .tf_load                = ide_tf_load,
+       .tf_read                = superio_tf_read,
+
+       .input_data             = ide_input_data,
+       .output_data            = ide_output_data,
+};
+
+static void __devinit superio_init_iops(struct hwif_s *hwif)
 {
        struct pci_dev *pdev = to_pci_dev(hwif->dev);
        u32 dma_stat;
        /* Clear error/interrupt, enable dma */
        tmp = superio_ide_inb(dma_stat);
        outb(tmp | 0x66, dma_stat);
-
-       hwif->read_status         = superio_read_status;
-       hwif->read_sff_dma_status = superio_read_sff_dma_status;
-
-       hwif->tf_read = superio_tf_read;
-
-}
-
-static void __devinit init_iops_ns87415(ide_hwif_t *hwif)
-{
-       struct pci_dev *dev = to_pci_dev(hwif->dev);
-
-       if (PCI_SLOT(dev->devfn) == 0xE)
-               /* Built-in - assume it's under superio. */
-               superio_ide_init_iops(hwif);
 }
 #endif
 
        u8 dma_stat = 0, dma_cmd = 0;
 
        drive->waiting_for_dma = 0;
-       dma_stat = hwif->read_sff_dma_status(hwif);
+       dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
        /* get DMA command mode */
        dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
        /* stop DMA */
                outb(8, hwif->io_ports.ctl_addr);
                do {
                        udelay(50);
-                       stat = hwif->read_status(hwif);
+                       stat = hwif->tp_ops->read_status(hwif);
                        if (stat == 0xff)
                                break;
                } while ((stat & BUSY_STAT) && --timeout);
 
 static const struct ide_port_info ns87415_chipset __devinitdata = {
        .name           = "NS87415",
-#ifdef CONFIG_SUPERIO
-       .init_iops      = init_iops_ns87415,
-#endif
        .init_hwif      = init_hwif_ns87415,
        .port_ops       = &ns87415_port_ops,
        .dma_ops        = &ns87415_dma_ops,
 
 static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       return ide_setup_pci_device(dev, &ns87415_chipset);
+       struct ide_port_info d = ns87415_chipset;
+
+#ifdef CONFIG_SUPERIO
+       if (PCI_SLOT(dev->devfn) == 0xE) {
+               /* Built-in - assume it's under superio. */
+               d.init_iops = superio_init_iops;
+               d.tp_ops = &superio_tp_ops;
+       }
+#endif
+       return ide_setup_pci_device(dev, &d);
 }
 
 static const struct pci_device_id ns87415_pci_tbl[] = {
 
 
        ide_set_hwifdata(hwif, ports);
 
-       hwif->exec_command        = scc_exec_command;
-       hwif->read_status         = scc_read_status;
-       hwif->read_altstatus      = scc_read_altstatus;
-       hwif->read_sff_dma_status = scc_read_sff_dma_status;
-
-       hwif->set_irq = scc_set_irq;
-
-       hwif->tf_load = scc_tf_load;
-       hwif->tf_read = scc_tf_read;
-
-       hwif->input_data  = scc_input_data;
-       hwif->output_data = scc_output_data;
-
        hwif->dma_base = dma_base;
        hwif->config_data = ports->ctl;
 }
                hwif->ultra_mask = ATA_UDMA5; /* 100MHz */
 }
 
+static const struct ide_tp_ops scc_tp_ops = {
+       .exec_command           = scc_exec_command,
+       .read_status            = scc_read_status,
+       .read_altstatus         = scc_read_altstatus,
+       .read_sff_dma_status    = scc_read_sff_dma_status,
+
+       .set_irq                = scc_set_irq,
+
+       .tf_load                = scc_tf_load,
+       .tf_read                = scc_tf_read,
+
+       .input_data             = scc_input_data,
+       .output_data            = scc_output_data,
+};
+
 static const struct ide_port_ops scc_port_ops = {
        .set_pio_mode           = scc_set_pio_mode,
        .set_dma_mode           = scc_set_dma_mode,
       .name            = name_str,                     \
       .init_iops       = init_iops_scc,                \
       .init_hwif       = init_hwif_scc,                \
+      .tp_ops          = &scc_tp_ops,          \
       .port_ops                = &scc_port_ops,                \
       .dma_ops         = &scc_dma_ops,                 \
       .host_flags      = IDE_HFLAG_SINGLE,             \
 
        return 0;
 }
 
+static const struct ide_tp_ops sgiioc4_tp_ops = {
+       .exec_command           = ide_exec_command,
+       .read_status            = sgiioc4_read_status,
+       .read_altstatus         = ide_read_altstatus,
+       .read_sff_dma_status    = ide_read_sff_dma_status,
+
+       .set_irq                = ide_set_irq,
+
+       .tf_load                = ide_tf_load,
+       .tf_read                = ide_tf_read,
+
+       .input_data             = ide_input_data,
+       .output_data            = ide_output_data,
+};
+
 static const struct ide_port_ops sgiioc4_port_ops = {
        .set_dma_mode           = sgiioc4_set_dma_mode,
        /* reset DMA engine, clear IRQs */
        .name                   = DRV_NAME,
        .chipset                = ide_pci,
        .init_dma               = ide_dma_sgiioc4,
+       .tp_ops                 = &sgiioc4_tp_ops,
        .port_ops               = &sgiioc4_port_ops,
        .dma_ops                = &sgiioc4_dma_ops,
        .host_flags             = IDE_HFLAG_MMIO,
        /* Initializing chipset IRQ Registers */
        writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4));
 
-       hwif->read_status = sgiioc4_read_status;
-
        idx[0] = hwif->index;
 
        if (ide_device_add(idx, &d, hws))
 
        }
 }
 
+static const struct ide_tp_ops pmac_tp_ops = {
+       .exec_command           = pmac_exec_command,
+       .read_status            = ide_read_status,
+       .read_altstatus         = ide_read_altstatus,
+       .read_sff_dma_status    = ide_read_sff_dma_status,
+
+       .set_irq                = pmac_set_irq,
+
+       .tf_load                = ide_tf_load,
+       .tf_read                = ide_tf_read,
+
+       .input_data             = ide_input_data,
+       .output_data            = ide_output_data,
+};
+
 static const struct ide_port_ops pmac_ide_ata6_port_ops = {
        .init_dev               = pmac_ide_init_dev,
        .set_pio_mode           = pmac_ide_set_pio_mode,
        .name                   = DRV_NAME,
        .init_dma               = pmac_ide_init_dma,
        .chipset                = ide_pmac,
+       .tp_ops                 = &pmac_tp_ops,
+       .port_ops               = &pmac_ide_port_ops,
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
        .dma_ops                = &pmac_dma_ops,
 #endif
-       .port_ops               = &pmac_ide_port_ops,
        .host_flags             = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
                                  IDE_HFLAG_POST_SET_MODE |
                                  IDE_HFLAG_MMIO |
        if (hwif == NULL)
                return -ENOENT;
 
-       hwif->exec_command = pmac_exec_command;
-       hwif->set_irq      = pmac_set_irq;
-
        idx[0] = hwif->index;
 
        ide_device_add(idx, &d, hws);
 
         * we tune the drive then try to grab DMA ownership if we want to be
         * the DMA end.  This has to be become dynamic to handle hot-plug.
         */
-       dma_stat = hwif->read_sff_dma_status(hwif);
+       dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
        if ((dma_stat & 0x80) && hwif->mate && hwif->mate->dma_base) {
                printk(KERN_INFO "%s: simplex device: DMA disabled\n", d->name);
                return -1;
 
                                unsigned int bcount, int write)
 {
        ide_hwif_t *hwif = drive->hwif;
-       xfer_func_t *xf = write ? hwif->output_data : hwif->input_data;
+       const struct ide_tp_ops *tp_ops = hwif->tp_ops;
+       xfer_func_t *xf = write ? tp_ops->output_data : tp_ops->input_data;
        char *buf;
        int count;
 
 {
        ide_hwif_t *hwif = drive->hwif;
 
-       if (hwif->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
+       if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
                /* force an abort */
-               hwif->exec_command(hwif, WIN_IDLEIMMEDIATE);
+               hwif->tp_ops->exec_command(hwif, WIN_IDLEIMMEDIATE);
 
        rq->errors++;
 
 
     ((1<<ide_pci)|(1<<ide_cmd646)|(1<<ide_ali14xx))
 #define IDE_CHIPSET_IS_PCI(c)  ((IDE_CHIPSET_PCI_MASK >> (c)) & 1)
 
+struct ide_task_s;
 struct ide_port_info;
 
+struct ide_tp_ops {
+       void    (*exec_command)(struct hwif_s *, u8);
+       u8      (*read_status)(struct hwif_s *);
+       u8      (*read_altstatus)(struct hwif_s *);
+       u8      (*read_sff_dma_status)(struct hwif_s *);
+
+       void    (*set_irq)(struct hwif_s *, int);
+
+       void    (*tf_load)(ide_drive_t *, struct ide_task_s *);
+       void    (*tf_read)(ide_drive_t *, struct ide_task_s *);
+
+       void    (*input_data)(ide_drive_t *, struct request *, void *,
+                             unsigned int);
+       void    (*output_data)(ide_drive_t *, struct request *, void *,
+                              unsigned int);
+};
+
+extern const struct ide_tp_ops default_tp_ops;
+
 struct ide_port_ops {
        /* host specific initialization of a device */
        void    (*init_dev)(ide_drive_t *);
        void    (*dma_timeout)(struct ide_drive_s *);
 };
 
-struct ide_task_s;
-
 typedef struct hwif_s {
        struct hwif_s *next;            /* for linked-list in ide_hwgroup_t */
        struct hwif_s *mate;            /* other hwif from same PCI chip */
 
        void (*rw_disk)(ide_drive_t *, struct request *);
 
+       const struct ide_tp_ops         *tp_ops;
        const struct ide_port_ops       *port_ops;
        const struct ide_dma_ops        *dma_ops;
 
-       void    (*exec_command)(struct hwif_s *, u8);
-       u8      (*read_status)(struct hwif_s *);
-       u8      (*read_altstatus)(struct hwif_s *);
-       u8      (*read_sff_dma_status)(struct hwif_s *);
-
-       void    (*set_irq)(struct hwif_s *, int);
-
-       void (*tf_load)(ide_drive_t *, struct ide_task_s *);
-       void (*tf_read)(ide_drive_t *, struct ide_task_s *);
-
-       void (*input_data)(ide_drive_t *, struct request *, void *, unsigned);
-       void (*output_data)(ide_drive_t *, struct request *, void *, unsigned);
-
        void (*ide_dma_clear_irq)(ide_drive_t *drive);
 
        /* dma physical region descriptor table (cpu view) */
 
 void ide_tf_dump(const char *, struct ide_taskfile *);
 
+void ide_exec_command(ide_hwif_t *, u8);
+u8 ide_read_status(ide_hwif_t *);
+u8 ide_read_altstatus(ide_hwif_t *);
+u8 ide_read_sff_dma_status(ide_hwif_t *);
+
+void ide_set_irq(ide_hwif_t *, int);
+
+void ide_tf_load(ide_drive_t *, ide_task_t *);
+void ide_tf_read(ide_drive_t *, ide_task_t *);
+
+void ide_input_data(ide_drive_t *, struct request *, void *, unsigned int);
+void ide_output_data(ide_drive_t *, struct request *, void *, unsigned int);
+
 extern void SELECT_DRIVE(ide_drive_t *);
 void SELECT_MASK(ide_drive_t *, int);
 
 }
 #endif
 
-extern void default_hwif_transport(ide_hwif_t *);
-
 typedef struct ide_pci_enablebit_s {
        u8      reg;    /* byte pci reg holding the enable-bit */
        u8      mask;   /* mask to isolate the enable-bit */
        int                     (*init_dma)(ide_hwif_t *,
                                            const struct ide_port_info *);
 
+       const struct ide_tp_ops         *tp_ops;
        const struct ide_port_ops       *port_ops;
        const struct ide_dma_ops        *dma_ops;