diff options
author | Jiri Kosina <jkosina@suse.cz> | 2008-05-06 16:57:55 +0200 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2008-05-06 16:57:55 +0200 |
commit | 7022b15e2a9f878fd5184586064c63352c3dd225 (patch) | |
tree | 5365c2f5bc82ae1946636ee8d5cd5d3b7e804f1b /drivers/ide/ide-iops.c | |
parent | aaad2b0c757f3e6e02552cb0bdcd91a5ec0d6305 (diff) | |
parent | a15306365a16380f3bafee9e181ba01231d4acd7 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers/ide/ide-iops.c')
-rw-r--r-- | drivers/ide/ide-iops.c | 428 |
1 files changed, 246 insertions, 182 deletions
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 45944219eea..57d9a9a79a6 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -37,21 +37,6 @@ static u8 ide_inb (unsigned long port) return (u8) inb(port); } -static u16 ide_inw (unsigned long port) -{ - return (u16) inw(port); -} - -static void ide_insw (unsigned long port, void *addr, u32 count) -{ - insw(port, addr, count); -} - -static void ide_insl (unsigned long port, void *addr, u32 count) -{ - insl(port, addr, count); -} - static void ide_outb (u8 val, unsigned long port) { outb(val, port); @@ -62,32 +47,11 @@ static void ide_outbsync (ide_drive_t *drive, u8 addr, unsigned long port) outb(addr, port); } -static void ide_outw (u16 val, unsigned long port) -{ - outw(val, port); -} - -static void ide_outsw (unsigned long port, void *addr, u32 count) -{ - outsw(port, addr, count); -} - -static void ide_outsl (unsigned long port, void *addr, u32 count) -{ - outsl(port, addr, count); -} - void default_hwif_iops (ide_hwif_t *hwif) { hwif->OUTB = ide_outb; hwif->OUTBSYNC = ide_outbsync; - hwif->OUTW = ide_outw; - hwif->OUTSW = ide_outsw; - hwif->OUTSL = ide_outsl; hwif->INB = ide_inb; - hwif->INW = ide_inw; - hwif->INSW = ide_insw; - hwif->INSL = ide_insl; } /* @@ -99,21 +63,6 @@ static u8 ide_mm_inb (unsigned long port) return (u8) readb((void __iomem *) port); } -static u16 ide_mm_inw (unsigned long port) -{ - return (u16) readw((void __iomem *) port); -} - -static void ide_mm_insw (unsigned long port, void *addr, u32 count) -{ - __ide_mm_insw((void __iomem *) port, addr, count); -} - -static void ide_mm_insl (unsigned long port, void *addr, u32 count) -{ - __ide_mm_insl((void __iomem *) port, addr, count); -} - static void ide_mm_outb (u8 value, unsigned long port) { writeb(value, (void __iomem *) port); @@ -124,34 +73,13 @@ static void ide_mm_outbsync (ide_drive_t *drive, u8 value, unsigned long port) writeb(value, (void __iomem *) port); } -static void ide_mm_outw (u16 value, unsigned long port) -{ - writew(value, (void __iomem *) port); -} - -static void ide_mm_outsw (unsigned long port, void *addr, u32 count) -{ - __ide_mm_outsw((void __iomem *) port, addr, count); -} - -static void ide_mm_outsl (unsigned long port, void *addr, u32 count) -{ - __ide_mm_outsl((void __iomem *) port, addr, count); -} - void default_hwif_mmiops (ide_hwif_t *hwif) { hwif->OUTB = ide_mm_outb; /* Most systems will need to override OUTBSYNC, alas however this one is controller specific! */ hwif->OUTBSYNC = ide_mm_outbsync; - hwif->OUTW = ide_mm_outw; - hwif->OUTSW = ide_mm_outsw; - hwif->OUTSL = ide_mm_outsl; hwif->INB = ide_mm_inb; - hwif->INW = ide_mm_inw; - hwif->INSW = ide_mm_insw; - hwif->INSL = ide_mm_insl; } EXPORT_SYMBOL(default_hwif_mmiops); @@ -159,17 +87,137 @@ EXPORT_SYMBOL(default_hwif_mmiops); void SELECT_DRIVE (ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; + const struct ide_port_ops *port_ops = hwif->port_ops; - if (hwif->selectproc) - hwif->selectproc(drive); + if (port_ops && port_ops->selectproc) + port_ops->selectproc(drive); - hwif->OUTB(drive->select.all, hwif->io_ports[IDE_SELECT_OFFSET]); + hwif->OUTB(drive->select.all, hwif->io_ports.device_addr); } void SELECT_MASK (ide_drive_t *drive, int mask) { - if (HWIF(drive)->maskproc) - HWIF(drive)->maskproc(drive, mask); + const struct ide_port_ops *port_ops = drive->hwif->port_ops; + + if (port_ops && port_ops->maskproc) + port_ops->maskproc(drive, mask); +} + +static 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; + struct ide_taskfile *tf = &task->tf; + void (*tf_outb)(u8 addr, unsigned long port); + u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; + u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; + + if (mmio) + tf_outb = ide_mm_outb; + else + tf_outb = ide_outb; + + if (task->tf_flags & IDE_TFLAG_FLAGGED) + HIHI = 0xFF; + + ide_set_irq(drive, 1); + + if ((task->tf_flags & IDE_TFLAG_NO_SELECT_MASK) == 0) + SELECT_MASK(drive, 0); + + if (task->tf_flags & IDE_TFLAG_OUT_DATA) { + u16 data = (tf->hob_data << 8) | tf->data; + + if (mmio) + writew(data, (void __iomem *)io_ports->data_addr); + else + outw(data, io_ports->data_addr); + } + + if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) + tf_outb(tf->hob_feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) + tf_outb(tf->hob_nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) + tf_outb(tf->hob_lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) + tf_outb(tf->hob_lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) + tf_outb(tf->hob_lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) + tf_outb(tf->feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_NSECT) + tf_outb(tf->nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAL) + tf_outb(tf->lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAM) + tf_outb(tf->lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAH) + tf_outb(tf->lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) + tf_outb((tf->device & HIHI) | drive->select.all, + io_ports->device_addr); +} + +static 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; + struct ide_taskfile *tf = &task->tf; + void (*tf_outb)(u8 addr, unsigned long port); + u8 (*tf_inb)(unsigned long port); + u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; + + if (mmio) { + tf_outb = ide_mm_outb; + tf_inb = ide_mm_inb; + } else { + tf_outb = ide_outb; + tf_inb = ide_inb; + } + + if (task->tf_flags & IDE_TFLAG_IN_DATA) { + u16 data; + + if (mmio) + data = readw((void __iomem *)io_ports->data_addr); + else + data = inw(io_ports->data_addr); + + tf->data = data & 0xff; + tf->hob_data = (data >> 8) & 0xff; + } + + /* be sure we're looking at the low order bits */ + tf_outb(drive->ctl & ~0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_NSECT) + tf->nsect = tf_inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAL) + tf->lbal = tf_inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAM) + tf->lbam = tf_inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAH) + tf->lbah = tf_inb(io_ports->lbah_addr); + if (task->tf_flags & IDE_TFLAG_IN_DEVICE) + tf->device = tf_inb(io_ports->device_addr); + + if (task->tf_flags & IDE_TFLAG_LBA48) { + tf_outb(drive->ctl | 0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) + tf->hob_feature = tf_inb(io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) + tf->hob_nsect = tf_inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) + tf->hob_lbal = tf_inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) + tf->hob_lbam = tf_inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) + tf->hob_lbah = tf_inb(io_ports->lbah_addr); + } } /* @@ -179,115 +227,112 @@ void SELECT_MASK (ide_drive_t *drive, int mask) * of the sector count register location, with interrupts disabled * to ensure that the reads all happen together. */ -static void ata_vlb_sync(ide_drive_t *drive, unsigned long port) +static void ata_vlb_sync(unsigned long port) { - (void) HWIF(drive)->INB(port); - (void) HWIF(drive)->INB(port); - (void) HWIF(drive)->INB(port); + (void)inb(port); + (void)inb(port); + (void)inb(port); } /* * This is used for most PIO data transfers *from* the IDE interface + * + * These routines will round up any request for an odd number of bytes, + * 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, void *buffer, u32 wcount) +static void ata_input_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) { - ide_hwif_t *hwif = HWIF(drive); - u8 io_32bit = drive->io_32bit; + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + unsigned long data_addr = io_ports->data_addr; + u8 io_32bit = drive->io_32bit; + u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; + + len++; if (io_32bit) { - if (io_32bit & 2) { - unsigned long flags; + unsigned long uninitialized_var(flags); + if ((io_32bit & 2) && !mmio) { local_irq_save(flags); - ata_vlb_sync(drive, hwif->io_ports[IDE_NSECTOR_OFFSET]); - hwif->INSL(hwif->io_ports[IDE_DATA_OFFSET], buffer, - wcount); + ata_vlb_sync(io_ports->nsect_addr); + } + + if (mmio) + __ide_mm_insl((void __iomem *)data_addr, buf, len / 4); + else + insl(data_addr, buf, len / 4); + + if ((io_32bit & 2) && !mmio) local_irq_restore(flags); - } else - hwif->INSL(hwif->io_ports[IDE_DATA_OFFSET], buffer, - wcount); - } else - hwif->INSW(hwif->io_ports[IDE_DATA_OFFSET], buffer, - wcount << 1); + + if ((len & 3) >= 2) { + if (mmio) + __ide_mm_insw((void __iomem *)data_addr, + (u8 *)buf + (len & ~3), 1); + else + insw(data_addr, (u8 *)buf + (len & ~3), 1); + } + } else { + if (mmio) + __ide_mm_insw((void __iomem *)data_addr, buf, len / 2); + else + insw(data_addr, buf, len / 2); + } } /* * This is used for most PIO data transfers *to* the IDE interface */ -static void ata_output_data(ide_drive_t *drive, void *buffer, u32 wcount) +static void ata_output_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) { - ide_hwif_t *hwif = HWIF(drive); - u8 io_32bit = drive->io_32bit; + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + unsigned long data_addr = io_ports->data_addr; + u8 io_32bit = drive->io_32bit; + u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; if (io_32bit) { - if (io_32bit & 2) { - unsigned long flags; + unsigned long uninitialized_var(flags); + if ((io_32bit & 2) && !mmio) { local_irq_save(flags); - ata_vlb_sync(drive, hwif->io_ports[IDE_NSECTOR_OFFSET]); - hwif->OUTSL(hwif->io_ports[IDE_DATA_OFFSET], buffer, - wcount); - local_irq_restore(flags); - } else - hwif->OUTSL(hwif->io_ports[IDE_DATA_OFFSET], buffer, - wcount); - } else - hwif->OUTSW(hwif->io_ports[IDE_DATA_OFFSET], buffer, - wcount << 1); -} - -/* - * The following routines are mainly used by the ATAPI drivers. - * - * These routines will round up any request for an odd number of bytes, - * so if an odd bytecount is specified, be sure that there's at least one - * extra byte allocated for the buffer. - */ - -static void atapi_input_bytes(ide_drive_t *drive, void *buffer, u32 bytecount) -{ - ide_hwif_t *hwif = HWIF(drive); + ata_vlb_sync(io_ports->nsect_addr); + } - ++bytecount; -#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) - if (MACH_IS_ATARI || MACH_IS_Q40) { - /* Atari has a byte-swapped IDE interface */ - insw_swapw(hwif->io_ports[IDE_DATA_OFFSET], buffer, - bytecount / 2); - return; - } -#endif /* CONFIG_ATARI || CONFIG_Q40 */ - hwif->ata_input_data(drive, buffer, bytecount / 4); - if ((bytecount & 0x03) >= 2) - hwif->INSW(hwif->io_ports[IDE_DATA_OFFSET], - (u8 *)buffer + (bytecount & ~0x03), 1); -} + if (mmio) + __ide_mm_outsl((void __iomem *)data_addr, buf, len / 4); + else + outsl(data_addr, buf, len / 4); -static void atapi_output_bytes(ide_drive_t *drive, void *buffer, u32 bytecount) -{ - ide_hwif_t *hwif = HWIF(drive); + if ((io_32bit & 2) && !mmio) + local_irq_restore(flags); - ++bytecount; -#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) - if (MACH_IS_ATARI || MACH_IS_Q40) { - /* Atari has a byte-swapped IDE interface */ - outsw_swapw(hwif->io_ports[IDE_DATA_OFFSET], buffer, - bytecount / 2); - return; + if ((len & 3) >= 2) { + if (mmio) + __ide_mm_outsw((void __iomem *)data_addr, + (u8 *)buf + (len & ~3), 1); + else + outsw(data_addr, (u8 *)buf + (len & ~3), 1); + } + } else { + if (mmio) + __ide_mm_outsw((void __iomem *)data_addr, buf, len / 2); + else + outsw(data_addr, buf, len / 2); } -#endif /* CONFIG_ATARI || CONFIG_Q40 */ - hwif->ata_output_data(drive, buffer, bytecount / 4); - if ((bytecount & 0x03) >= 2) - hwif->OUTSW(hwif->io_ports[IDE_DATA_OFFSET], - (u8 *)buffer + (bytecount & ~0x03), 1); } void default_hwif_transport(ide_hwif_t *hwif) { - hwif->ata_input_data = ata_input_data; - hwif->ata_output_data = ata_output_data; - hwif->atapi_input_bytes = atapi_input_bytes; - hwif->atapi_output_bytes = atapi_output_bytes; + hwif->tf_load = ide_tf_load; + hwif->tf_read = ide_tf_read; + + hwif->input_data = ata_input_data; + hwif->output_data = ata_output_data; } void ide_fix_driveid (struct hd_driveid *id) @@ -429,7 +474,7 @@ int drive_is_ready (ide_drive_t *drive) u8 stat = 0; if (drive->waiting_for_dma) - return hwif->ide_dma_test_irq(drive); + return hwif->dma_ops->dma_test_irq(drive); #if 0 /* need to guarantee 400ns since last command was issued */ @@ -442,7 +487,7 @@ int drive_is_ready (ide_drive_t *drive) * an interrupt with another pci card/device. We make no assumptions * about possible isa-pnp and pci-pnp issues yet. */ - if (hwif->io_ports[IDE_CONTROL_OFFSET]) + if (hwif->io_ports.ctl_addr) stat = ide_read_altstatus(drive); else /* Note: this may clear a pending IRQ!! */ @@ -580,6 +625,8 @@ static const struct drive_list_entry ivb_list[] = { { "TSSTcorp CDDVDW SH-S202J" , "SB01" }, { "TSSTcorp CDDVDW SH-S202N" , "SB00" }, { "TSSTcorp CDDVDW SH-S202N" , "SB01" }, + { "TSSTcorp CDDVDW SH-S202H" , "SB00" }, + { "TSSTcorp CDDVDW SH-S202H" , "SB01" }, { NULL , NULL } }; @@ -644,7 +691,7 @@ int ide_driveid_update(ide_drive_t *drive) SELECT_MASK(drive, 1); ide_set_irq(drive, 1); msleep(50); - hwif->OUTB(WIN_IDENTIFY, hwif->io_ports[IDE_COMMAND_OFFSET]); + hwif->OUTBSYNC(drive, WIN_IDENTIFY, hwif->io_ports.command_addr); timeout = jiffies + WAIT_WORSTCASE; do { if (time_after(jiffies, timeout)) { @@ -671,7 +718,7 @@ int ide_driveid_update(ide_drive_t *drive) local_irq_restore(flags); return 0; } - hwif->ata_input_data(drive, id, SECTOR_WORDS); + hwif->input_data(drive, NULL, id, SECTOR_SIZE); (void)ide_read_status(drive); /* clear drive IRQ */ local_irq_enable(); local_irq_restore(flags); @@ -693,6 +740,7 @@ int ide_driveid_update(ide_drive_t *drive) int ide_config_drive_speed(ide_drive_t *drive, u8 speed) { ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; int error = 0; u8 stat; @@ -700,8 +748,8 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) // msleep(50); #ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_host_set) /* check if host supports DMA */ - hwif->dma_host_set(drive, 0); + if (hwif->dma_ops) /* check if host supports DMA */ + hwif->dma_ops->dma_host_set(drive, 0); #endif /* Skip setting PIO flow-control modes on pre-EIDE drives */ @@ -731,10 +779,9 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) SELECT_MASK(drive, 0); udelay(1); ide_set_irq(drive, 0); - hwif->OUTB(speed, hwif->io_ports[IDE_NSECTOR_OFFSET]); - hwif->OUTB(SETFEATURES_XFER, hwif->io_ports[IDE_FEATURE_OFFSET]); - hwif->OUTBSYNC(drive, WIN_SETFEATURES, - hwif->io_ports[IDE_COMMAND_OFFSET]); + hwif->OUTB(speed, io_ports->nsect_addr); + hwif->OUTB(SETFEATURES_XFER, io_ports->feature_addr); + hwif->OUTBSYNC(drive, WIN_SETFEATURES, io_ports->command_addr); if (drive->quirk_list == 2) ide_set_irq(drive, 1); @@ -759,8 +806,8 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) #ifdef CONFIG_BLK_DEV_IDEDMA if ((speed >= XFER_SW_DMA_0 || (hwif->host_flags & IDE_HFLAG_VDMA)) && drive->using_dma) - hwif->dma_host_set(drive, 1); - else if (hwif->dma_host_set) /* check if host supports DMA */ + hwif->dma_ops->dma_host_set(drive, 1); + else if (hwif->dma_ops) /* check if host supports DMA */ ide_dma_off_quietly(drive); #endif @@ -842,7 +889,7 @@ void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler, spin_lock_irqsave(&ide_lock, flags); __ide_set_handler(drive, handler, timeout, expiry); - hwif->OUTBSYNC(drive, cmd, hwif->io_ports[IDE_COMMAND_OFFSET]); + hwif->OUTBSYNC(drive, cmd, hwif->io_ports.command_addr); /* * Drive takes 400nS to respond, we must avoid the IRQ being * serviced before that. @@ -852,9 +899,19 @@ void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler, ndelay(400); spin_unlock_irqrestore(&ide_lock, flags); } - EXPORT_SYMBOL(ide_execute_command); +void ide_execute_pkt_cmd(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + unsigned long flags; + + spin_lock_irqsave(&ide_lock, flags); + hwif->OUTBSYNC(drive, WIN_PACKETCMD, hwif->io_ports.command_addr); + ndelay(400); + spin_unlock_irqrestore(&ide_lock, flags); +} +EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd); /* needed below */ static ide_startstop_t do_reset1 (ide_drive_t *, int); @@ -905,10 +962,11 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive) { ide_hwgroup_t *hwgroup = HWGROUP(drive); ide_hwif_t *hwif = HWIF(drive); + const struct ide_port_ops *port_ops = hwif->port_ops; u8 tmp; - if (hwif->reset_poll != NULL) { - if (hwif->reset_poll(drive)) { + if (port_ops && port_ops->reset_poll) { + if (port_ops->reset_poll(drive)) { printk(KERN_ERR "%s: host reset_poll failure for %s.\n", hwif->name, drive->name); return ide_stopped; @@ -974,6 +1032,8 @@ static void ide_disk_pre_reset(ide_drive_t *drive) static void pre_reset(ide_drive_t *drive) { + const struct ide_port_ops *port_ops = drive->hwif->port_ops; + if (drive->media == ide_disk) ide_disk_pre_reset(drive); else @@ -994,8 +1054,8 @@ static void pre_reset(ide_drive_t *drive) return; } - if (HWIF(drive)->pre_reset != NULL) - HWIF(drive)->pre_reset(drive); + if (port_ops && port_ops->pre_reset) + port_ops->pre_reset(drive); if (drive->current_speed != 0xff) drive->desired_speed = drive->current_speed; @@ -1023,12 +1083,16 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) unsigned long flags; ide_hwif_t *hwif; ide_hwgroup_t *hwgroup; + struct ide_io_ports *io_ports; + const struct ide_port_ops *port_ops; u8 ctl; spin_lock_irqsave(&ide_lock, flags); hwif = HWIF(drive); hwgroup = HWGROUP(drive); + io_ports = &hwif->io_ports; + /* We must not reset with running handlers */ BUG_ON(hwgroup->handler != NULL); @@ -1038,8 +1102,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) pre_reset(drive); SELECT_DRIVE(drive); udelay (20); - hwif->OUTBSYNC(drive, WIN_SRST, - hwif->io_ports[IDE_COMMAND_OFFSET]); + hwif->OUTBSYNC(drive, WIN_SRST, io_ports->command_addr); ndelay(400); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; hwgroup->polling = 1; @@ -1055,7 +1118,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) for (unit = 0; unit < MAX_DRIVES; ++unit) pre_reset(&hwif->drives[unit]); - if (hwif->io_ports[IDE_CONTROL_OFFSET] == 0) { + if (io_ports->ctl_addr == 0) { spin_unlock_irqrestore(&ide_lock, flags); return ide_stopped; } @@ -1070,14 +1133,14 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) * recover from reset very quickly, saving us the first 50ms wait time. */ /* set SRST and nIEN */ - hwif->OUTBSYNC(drive, drive->ctl|6, hwif->io_ports[IDE_CONTROL_OFFSET]); + hwif->OUTBSYNC(drive, drive->ctl|6, io_ports->ctl_addr); /* more than enough time */ udelay(10); if (drive->quirk_list == 2) ctl = drive->ctl; /* clear SRST and nIEN */ else ctl = drive->ctl | 2; /* clear SRST, leave nIEN */ - hwif->OUTBSYNC(drive, ctl, hwif->io_ports[IDE_CONTROL_OFFSET]); + hwif->OUTBSYNC(drive, ctl, io_ports->ctl_addr); /* more than enough time */ udelay(10); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; @@ -1089,8 +1152,9 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) * state when the disks are reset this way. At least, the Winbond * 553 documentation says that */ - if (hwif->resetproc) - hwif->resetproc(drive); + port_ops = hwif->port_ops; + if (port_ops && port_ops->resetproc) + port_ops->resetproc(drive); spin_unlock_irqrestore(&ide_lock, flags); return ide_started; @@ -1121,7 +1185,7 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout) * about locking issues (2.5 work ?). */ mdelay(1); - stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); + stat = hwif->INB(hwif->io_ports.status_addr); if ((stat & BUSY_STAT) == 0) return 0; /* |