diff options
Diffstat (limited to 'drivers/ide')
57 files changed, 1638 insertions, 3543 deletions
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 3f9e10001e19..f702f9152ce6 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -862,40 +862,6 @@ config BLK_DEV_IDE_BAST Say Y here if you want to support the onboard IDE channels on the Simtec BAST or the Thorcom VR1000 -config ETRAX_IDE - tristate "ETRAX IDE support" - depends on CRIS && BROKEN - select BLK_DEV_IDEDMA - help - Enables the ETRAX IDE driver. - - You can't use parallel ports or SCSI ports at the same time. - -config ETRAX_IDE_DELAY - int "Delay for drives to regain consciousness" - depends on ETRAX_IDE && ETRAX_ARCH_V10 - default 15 - help - Number of seconds to wait for IDE drives to spin up after an IDE - reset. - -choice - prompt "IDE reset pin" - depends on ETRAX_IDE && ETRAX_ARCH_V10 - default ETRAX_IDE_PB7_RESET - -config ETRAX_IDE_PB7_RESET - bool "Port_PB_Bit_7" - help - IDE reset on pin 7 on port B - -config ETRAX_IDE_G27_RESET - bool "Port_G_Bit_27" - help - IDE reset on pin 27 on port G - -endchoice - config IDE_H8300 tristate "H8300 IDE support" depends on H8300 diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 571544c37bb2..f94b679b611e 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -35,7 +35,7 @@ ifeq ($(CONFIG_BLK_DEV_CMD640), y) obj-y += cmd640-core.o endif -obj-$(CONFIG_BLK_DEV_IDE) += cris/ ppc/ +obj-$(CONFIG_BLK_DEV_IDE) += ppc/ obj-$(CONFIG_IDE_H8300) += h8300/ obj-$(CONFIG_IDE_GENERIC) += ide-generic.o obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o diff --git a/drivers/ide/arm/bast-ide.c b/drivers/ide/arm/bast-ide.c index d158f579bde2..713cef20622e 100644 --- a/drivers/ide/arm/bast-ide.c +++ b/drivers/ide/arm/bast-ide.c @@ -35,12 +35,12 @@ static int __init bastide_register(unsigned int base, unsigned int aux, int irq) base += BAST_IDE_CS; aux += BAST_IDE_CS; - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hw.io_ports[i] = (unsigned long)base; + for (i = 0; i <= 7; i++) { + hw.io_ports_array[i] = (unsigned long)base; base += 0x20; } - hw.io_ports[IDE_CONTROL_OFFSET] = aux + (6 * 0x20); + hw.io_ports.ctl_addr = aux + (6 * 0x20); hw.irq = irq; hwif = ide_find_port(); @@ -49,11 +49,7 @@ static int __init bastide_register(unsigned int base, unsigned int aux, int irq) i = hwif->index; - if (hwif->present) - ide_unregister(i); - else - ide_init_port_data(hwif, i); - + ide_init_port_data(hwif, i); ide_init_port_hw(hwif, &hw); hwif->port_ops = NULL; diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c index 7d642f44e35b..061456914ca3 100644 --- a/drivers/ide/arm/icside.c +++ b/drivers/ide/arm/icside.c @@ -419,18 +419,21 @@ icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *e hwif = ide_find_port(); if (hwif) { - int i; - /* * Ensure we're using MMIO */ default_hwif_mmiops(hwif); - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hwif->io_ports[i] = port; - port += 1 << info->stepping; - } - hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)base + info->ctrloffset; + hwif->io_ports.data_addr = port; + hwif->io_ports.error_addr = port + (1 << info->stepping); + hwif->io_ports.nsect_addr = port + (2 << info->stepping); + hwif->io_ports.lbal_addr = port + (3 << info->stepping); + hwif->io_ports.lbam_addr = port + (4 << info->stepping); + hwif->io_ports.lbah_addr = port + (5 << info->stepping); + hwif->io_ports.device_addr = port + (6 << info->stepping); + hwif->io_ports.status_addr = port + (7 << info->stepping); + hwif->io_ports.ctl_addr = + (unsigned long)base + info->ctrloffset; hwif->irq = ec->irq; hwif->chipset = ide_acorn; hwif->gendev.parent = &ec->dev; @@ -480,8 +483,7 @@ static const struct ide_port_info icside_v6_port_info __initdata = { .init_dma = icside_dma_off_init, .port_ops = &icside_v6_no_dma_port_ops, .dma_ops = &icside_v6_dma_ops, - .host_flags = IDE_HFLAG_SERIALIZE | - IDE_HFLAG_NO_AUTOTUNE, + .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO, .mwdma_mask = ATA_MWDMA2, .swdma_mask = ATA_SWDMA2, }; @@ -547,14 +549,13 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) hwif->config_data = (unsigned long)ioc_base; hwif->select_data = sel; - mate->maskproc = icside_maskproc; mate->hwif_data = state; mate->config_data = (unsigned long)ioc_base; mate->select_data = sel | 1; if (ec->dma != NO_DMA && !request_dma(ec->dma, hwif->name)) { d.init_dma = icside_dma_init; - d.port_ops = &icside_v6_dma_port_ops; + d.port_ops = &icside_v6_port_ops; d.dma_ops = NULL; } diff --git a/drivers/ide/arm/palm_bk3710.c b/drivers/ide/arm/palm_bk3710.c index 8fa34e26443a..96378ebfb31f 100644 --- a/drivers/ide/arm/palm_bk3710.c +++ b/drivers/ide/arm/palm_bk3710.c @@ -321,7 +321,7 @@ static int __devinit palm_bk3710_init_dma(ide_hwif_t *hwif, const struct ide_port_info *d) { unsigned long base = - hwif->io_ports[IDE_DATA_OFFSET] - IDE_PALM_ATA_PRI_REG_OFFSET; + hwif->io_ports.data_addr - IDE_PALM_ATA_PRI_REG_OFFSET; printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name); @@ -342,6 +342,7 @@ static const struct ide_port_ops palm_bk3710_ports_ops = { static const struct ide_port_info __devinitdata palm_bk3710_port_info = { .init_dma = palm_bk3710_init_dma, .port_ops = &palm_bk3710_ports_ops, + .host_flags = IDE_HFLAG_MMIO, .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA4, /* (input clk 99MHz) */ .mwdma_mask = ATA_MWDMA2, @@ -386,8 +387,8 @@ static int __devinit palm_bk3710_probe(struct platform_device *pdev) pribase = mem->start + IDE_PALM_ATA_PRI_REG_OFFSET; for (i = 0; i < IDE_NR_PORTS - 2; i++) - hw.io_ports[i] = pribase + i; - hw.io_ports[IDE_CONTROL_OFFSET] = mem->start + + hw.io_ports_array[i] = pribase + i; + hw.io_ports.ctl_addr = mem->start + IDE_PALM_ATA_PRI_CTL_OFFSET; hw.irq = irq->start; hw.chipset = ide_palm3710; @@ -398,11 +399,7 @@ static int __devinit palm_bk3710_probe(struct platform_device *pdev) i = hwif->index; - if (hwif->present) - ide_unregister(i); - else - ide_init_port_data(hwif, i); - + ide_init_port_data(hwif, i); ide_init_port_hw(hwif, &hw); hwif->mmio = 1; diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c index c0581bd98d0d..1747b2358775 100644 --- a/drivers/ide/arm/rapide.c +++ b/drivers/ide/arm/rapide.c @@ -17,11 +17,11 @@ static void rapide_setup_ports(hw_regs_t *hw, void __iomem *base, unsigned long port = (unsigned long)base; int i; - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hw->io_ports[i] = port; + for (i = 0; i <= 7; i++) { + hw->io_ports_array[i] = port; port += sz; } - hw->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl; + hw->io_ports.ctl_addr = (unsigned long)ctrl; hw->irq = irq; } @@ -53,6 +53,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id) ide_init_port_hw(hwif, &hw); + hwif->host_flags = IDE_HFLAG_MMIO; default_hwif_mmiops(hwif); idx[0] = hwif->index; @@ -75,7 +76,7 @@ static void __devexit rapide_remove(struct expansion_card *ec) ecard_set_drvdata(ec, NULL); - ide_unregister(hwif->index); + ide_unregister(hwif); ecard_release_resources(ec); } diff --git a/drivers/ide/cris/Makefile b/drivers/ide/cris/Makefile deleted file mode 100644 index 20b95960531f..000000000000 --- a/drivers/ide/cris/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -EXTRA_CFLAGS += -Idrivers/ide - -obj-$(CONFIG_IDE_ETRAX) += ide-cris.o diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c deleted file mode 100644 index a62ca75c7e28..000000000000 --- a/drivers/ide/cris/ide-cris.c +++ /dev/null @@ -1,1086 +0,0 @@ -/* - * Etrax specific IDE functions, like init and PIO-mode setting etc. - * Almost the entire ide.c is used for the rest of the Etrax ATA driver. - * Copyright (c) 2000-2005 Axis Communications AB - * - * Authors: Bjorn Wesen (initial version) - * Mikael Starvik (crisv32 port) - */ - -/* Regarding DMA: - * - * There are two forms of DMA - "DMA handshaking" between the interface and the drive, - * and DMA between the memory and the interface. We can ALWAYS use the latter, since it's - * something built-in in the Etrax. However only some drives support the DMA-mode handshaking - * on the ATA-bus. The normal PC driver and Triton interface disables memory-if DMA when the - * device can't do DMA handshaking for some stupid reason. We don't need to do that. - */ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/blkdev.h> -#include <linux/hdreg.h> -#include <linux/ide.h> -#include <linux/init.h> - -#include <asm/io.h> -#include <asm/dma.h> - -/* number of DMA descriptors */ -#define MAX_DMA_DESCRS 64 - -/* number of times to retry busy-flags when reading/writing IDE-registers - * this can't be too high because a hung harddisk might cause the watchdog - * to trigger (sometimes INB and OUTB are called with irq's disabled) - */ - -#define IDE_REGISTER_TIMEOUT 300 - -#define LOWDB(x) -#define D(x) - -enum /* Transfer types */ -{ - TYPE_PIO, - TYPE_DMA, - TYPE_UDMA -}; - -/* CRISv32 specifics */ -#ifdef CONFIG_ETRAX_ARCH_V32 -#include <asm/arch/hwregs/ata_defs.h> -#include <asm/arch/hwregs/dma_defs.h> -#include <asm/arch/hwregs/dma.h> -#include <asm/arch/pinmux.h> - -#define ATA_UDMA2_CYC 2 -#define ATA_UDMA2_DVS 3 -#define ATA_UDMA1_CYC 2 -#define ATA_UDMA1_DVS 4 -#define ATA_UDMA0_CYC 4 -#define ATA_UDMA0_DVS 6 -#define ATA_DMA2_STROBE 7 -#define ATA_DMA2_HOLD 1 -#define ATA_DMA1_STROBE 8 -#define ATA_DMA1_HOLD 3 -#define ATA_DMA0_STROBE 25 -#define ATA_DMA0_HOLD 19 -#define ATA_PIO4_SETUP 3 -#define ATA_PIO4_STROBE 7 -#define ATA_PIO4_HOLD 1 -#define ATA_PIO3_SETUP 3 -#define ATA_PIO3_STROBE 9 -#define ATA_PIO3_HOLD 3 -#define ATA_PIO2_SETUP 3 -#define ATA_PIO2_STROBE 13 -#define ATA_PIO2_HOLD 5 -#define ATA_PIO1_SETUP 5 -#define ATA_PIO1_STROBE 23 -#define ATA_PIO1_HOLD 9 -#define ATA_PIO0_SETUP 9 -#define ATA_PIO0_STROBE 39 -#define ATA_PIO0_HOLD 9 - -int -cris_ide_ack_intr(ide_hwif_t* hwif) -{ - reg_ata_rw_ctrl2 ctrl2 = REG_TYPE_CONV(reg_ata_rw_ctrl2, - int, hwif->io_ports[0]); - REG_WR_INT(ata, regi_ata, rw_ack_intr, 1 << ctrl2.sel); - return 1; -} - -static inline int -cris_ide_busy(void) -{ - reg_ata_rs_stat_data stat_data; - stat_data = REG_RD(ata, regi_ata, rs_stat_data); - return stat_data.busy; -} - -static inline int -cris_ide_ready(void) -{ - return !cris_ide_busy(); -} - -static inline int -cris_ide_data_available(unsigned short* data) -{ - reg_ata_rs_stat_data stat_data; - stat_data = REG_RD(ata, regi_ata, rs_stat_data); - *data = stat_data.data; - return stat_data.dav; -} - -static void -cris_ide_write_command(unsigned long command) -{ - REG_WR_INT(ata, regi_ata, rw_ctrl2, command); /* write data to the drive's register */ -} - -static void -cris_ide_set_speed(int type, int setup, int strobe, int hold) -{ - reg_ata_rw_ctrl0 ctrl0 = REG_RD(ata, regi_ata, rw_ctrl0); - reg_ata_rw_ctrl1 ctrl1 = REG_RD(ata, regi_ata, rw_ctrl1); - - if (type == TYPE_PIO) { - ctrl0.pio_setup = setup; - ctrl0.pio_strb = strobe; - ctrl0.pio_hold = hold; - } else if (type == TYPE_DMA) { - ctrl0.dma_strb = strobe; - ctrl0.dma_hold = hold; - } else if (type == TYPE_UDMA) { - ctrl1.udma_tcyc = setup; - ctrl1.udma_tdvs = strobe; - } - REG_WR(ata, regi_ata, rw_ctrl0, ctrl0); - REG_WR(ata, regi_ata, rw_ctrl1, ctrl1); -} - -static unsigned long -cris_ide_base_address(int bus) -{ - reg_ata_rw_ctrl2 ctrl2 = {0}; - ctrl2.sel = bus; - return REG_TYPE_CONV(int, reg_ata_rw_ctrl2, ctrl2); -} - -static unsigned long -cris_ide_reg_addr(unsigned long addr, int cs0, int cs1) -{ - reg_ata_rw_ctrl2 ctrl2 = {0}; - ctrl2.addr = addr; - ctrl2.cs1 = cs1; - ctrl2.cs0 = cs0; - return REG_TYPE_CONV(int, reg_ata_rw_ctrl2, ctrl2); -} - -static __init void -cris_ide_reset(unsigned val) -{ - reg_ata_rw_ctrl0 ctrl0 = {0}; - ctrl0.rst = val ? regk_ata_active : regk_ata_inactive; - REG_WR(ata, regi_ata, rw_ctrl0, ctrl0); -} - -static __init void -cris_ide_init(void) -{ - reg_ata_rw_ctrl0 ctrl0 = {0}; - reg_ata_rw_intr_mask intr_mask = {0}; - - ctrl0.en = regk_ata_yes; - REG_WR(ata, regi_ata, rw_ctrl0, ctrl0); - - intr_mask.bus0 = regk_ata_yes; - intr_mask.bus1 = regk_ata_yes; - intr_mask.bus2 = regk_ata_yes; - intr_mask.bus3 = regk_ata_yes; - - REG_WR(ata, regi_ata, rw_intr_mask, intr_mask); - - crisv32_request_dma(2, "ETRAX FS built-in ATA", DMA_VERBOSE_ON_ERROR, 0, dma_ata); - crisv32_request_dma(3, "ETRAX FS built-in ATA", DMA_VERBOSE_ON_ERROR, 0, dma_ata); - - crisv32_pinmux_alloc_fixed(pinmux_ata); - crisv32_pinmux_alloc_fixed(pinmux_ata0); - crisv32_pinmux_alloc_fixed(pinmux_ata1); - crisv32_pinmux_alloc_fixed(pinmux_ata2); - crisv32_pinmux_alloc_fixed(pinmux_ata3); - - DMA_RESET(regi_dma2); - DMA_ENABLE(regi_dma2); - DMA_RESET(regi_dma3); - DMA_ENABLE(regi_dma3); - - DMA_WR_CMD (regi_dma2, regk_dma_set_w_size2); - DMA_WR_CMD (regi_dma3, regk_dma_set_w_size2); -} - -static dma_descr_context mycontext __attribute__ ((__aligned__(32))); - -#define cris_dma_descr_type dma_descr_data -#define cris_pio_read regk_ata_rd -#define cris_ultra_mask 0x7 -#define MAX_DESCR_SIZE 0xffffffffUL - -static unsigned long -cris_ide_get_reg(unsigned long reg) -{ - return (reg & 0x0e000000) >> 25; -} - -static void -cris_ide_fill_descriptor(cris_dma_descr_type *d, void* buf, unsigned int len, int last) -{ - d->buf = (char*)virt_to_phys(buf); - d->after = d->buf + len; - d->eol = last; -} - -static void -cris_ide_start_dma(ide_drive_t *drive, cris_dma_descr_type *d, int dir,int type,int len) -{ - ide_hwif_t *hwif = drive->hwif; - - reg_ata_rw_ctrl2 ctrl2 = REG_TYPE_CONV(reg_ata_rw_ctrl2, int, - hwif->io_ports[IDE_DATA_OFFSET]); - reg_ata_rw_trf_cnt trf_cnt = {0}; - - mycontext.saved_data = (dma_descr_data*)virt_to_phys(d); - mycontext.saved_data_buf = d->buf; - /* start the dma channel */ - DMA_START_CONTEXT(dir ? regi_dma3 : regi_dma2, virt_to_phys(&mycontext)); - - /* initiate a multi word dma read using PIO handshaking */ - trf_cnt.cnt = len >> 1; - /* Due to a "feature" the transfer count has to be one extra word for UDMA. */ - if (type == TYPE_UDMA) - trf_cnt.cnt++; - REG_WR(ata, regi_ata, rw_trf_cnt, trf_cnt); - - ctrl2.rw = dir ? regk_ata_rd : regk_ata_wr; - ctrl2.trf_mode = regk_ata_dma; - ctrl2.hsh = type == TYPE_PIO ? regk_ata_pio : - type == TYPE_DMA ? regk_ata_dma : regk_ata_udma; - ctrl2.multi = regk_ata_yes; - ctrl2.dma_size = regk_ata_word; - REG_WR(ata, regi_ata, rw_ctrl2, ctrl2); -} - -static void -cris_ide_wait_dma(int dir) -{ - reg_dma_rw_stat status; - do - { - status = REG_RD(dma, dir ? regi_dma3 : regi_dma2, rw_stat); - } while(status.list_state != regk_dma_data_at_eol); -} - -static int cris_dma_test_irq(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - int intr = REG_RD_INT(ata, regi_ata, r_intr); - - reg_ata_rw_ctrl2 ctrl2 = REG_TYPE_CONV(reg_ata_rw_ctrl2, int, - hwif->io_ports[IDE_DATA_OFFSET]); - - return intr & (1 << ctrl2.sel) ? 1 : 0; -} - -static void cris_ide_initialize_dma(int dir) -{ -} - -#else -/* CRISv10 specifics */ -#include <asm/arch/svinto.h> -#include <asm/arch/io_interface_mux.h> - -/* PIO timing (in R_ATA_CONFIG) - * - * _____________________________ - * ADDRESS : ________/ - * - * _______________ - * DIOR : ____________/ \__________ - * - * _______________ - * DATA : XXXXXXXXXXXXXXXX_______________XXXXXXXX - * - * - * DIOR is unbuffered while address and data is buffered. - * This creates two problems: - * 1. The DIOR pulse is to early (because it is unbuffered) - * 2. The rise time of DIOR is long - * - * There are at least three different plausible solutions - * 1. Use a pad capable of larger currents in Etrax - * 2. Use an external buffer - * 3. Make the strobe pulse longer - * - * Some of the strobe timings below are modified to compensate - * for this. This implies a slight performance decrease. - * - * THIS SHOULD NEVER BE CHANGED! - * - * TODO: Is this true for the latest LX boards still ? - */ - -#define ATA_UDMA2_CYC 0 /* No UDMA supported, just to make it compile. */ -#define ATA_UDMA2_DVS 0 -#define ATA_UDMA1_CYC 0 -#define ATA_UDMA1_DVS 0 -#define ATA_UDMA0_CYC 0 -#define ATA_UDMA0_DVS 0 -#define ATA_DMA2_STROBE 4 -#define ATA_DMA2_HOLD 0 -#define ATA_DMA1_STROBE 4 -#define ATA_DMA1_HOLD 1 -#define ATA_DMA0_STROBE 12 -#define ATA_DMA0_HOLD 9 -#define ATA_PIO4_SETUP 1 -#define ATA_PIO4_STROBE 5 -#define ATA_PIO4_HOLD 0 -#define ATA_PIO3_SETUP 1 -#define ATA_PIO3_STROBE 5 -#define ATA_PIO3_HOLD 1 -#define ATA_PIO2_SETUP 1 -#define ATA_PIO2_STROBE 6 -#define ATA_PIO2_HOLD 2 -#define ATA_PIO1_SETUP 2 -#define ATA_PIO1_STROBE 11 -#define ATA_PIO1_HOLD 4 -#define ATA_PIO0_SETUP 4 -#define ATA_PIO0_STROBE 19 -#define ATA_PIO0_HOLD 4 - -int -cris_ide_ack_intr(ide_hwif_t* hwif) -{ - return 1; -} - -static inline int -cris_ide_busy(void) -{ - return *R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy) ; -} - -static inline int -cris_ide_ready(void) -{ - return *R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, tr_rdy) ; -} - -static inline int -cris_ide_data_available(unsigned short* data) -{ - unsigned long status = *R_ATA_STATUS_DATA; - *data = (unsigned short)status; - return status & IO_MASK(R_ATA_STATUS_DATA, dav); -} - -static void -cris_ide_write_command(unsigned long command) -{ - *R_ATA_CTRL_DATA = command; -} - -static void -cris_ide_set_speed(int type, int setup, int strobe, int hold) -{ - static int pio_setup = ATA_PIO4_SETUP; - static int pio_strobe = ATA_PIO4_STROBE; - static int pio_hold = ATA_PIO4_HOLD; - static int dma_strobe = ATA_DMA2_STROBE; - static int dma_hold = ATA_DMA2_HOLD; - - if (type == TYPE_PIO) { - pio_setup = setup; - pio_strobe = strobe; - pio_hold = hold; - } else if (type == TYPE_DMA) { - dma_strobe = strobe; - dma_hold = hold; - } - *R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable, 1 ) | - IO_FIELD( R_ATA_CONFIG, dma_strobe, dma_strobe ) | - IO_FIELD( R_ATA_CONFIG, dma_hold, dma_hold ) | - IO_FIELD( R_ATA_CONFIG, pio_setup, pio_setup ) | - IO_FIELD( R_ATA_CONFIG, pio_strobe, pio_strobe ) | - IO_FIELD( R_ATA_CONFIG, pio_hold, pio_hold ) ); -} - -static unsigned long -cris_ide_base_address(int bus) -{ - return IO_FIELD(R_ATA_CTRL_DATA, sel, bus); -} - -static unsigned long -cris_ide_reg_addr(unsigned long addr, int cs0, int cs1) -{ - return IO_FIELD(R_ATA_CTRL_DATA, addr, addr) | - IO_FIELD(R_ATA_CTRL_DATA, cs0, cs0) | - IO_FIELD(R_ATA_CTRL_DATA, cs1, cs1); -} - -static __init void -cris_ide_reset(unsigned val) -{ -#ifdef CONFIG_ETRAX_IDE_G27_RESET - REG_SHADOW_SET(R_PORT_G_DATA, port_g_data_shadow, 27, val); -#endif -#ifdef CONFIG_ETRAX_IDE_PB7_RESET - port_pb_dir_shadow = port_pb_dir_shadow | - IO_STATE(R_PORT_PB_DIR, dir7, output); - *R_PORT_PB_DIR = port_pb_dir_shadow; - REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, 7, val); -#endif -} - -static __init void -cris_ide_init(void) -{ - volatile unsigned int dummy; - - *R_ATA_CTRL_DATA = 0; - *R_ATA_TRANSFER_CNT = 0; - *R_ATA_CONFIG = 0; - - if (cris_request_io_interface(if_ata, "ETRAX100LX IDE")) { - printk(KERN_CRIT "ide: Failed to get IO interface\n"); - return; - } else if (cris_request_dma(ATA_TX_DMA_NBR, - "ETRAX100LX IDE TX", - DMA_VERBOSE_ON_ERROR, - dma_ata)) { - cris_free_io_interface(if_ata); - printk(KERN_CRIT "ide: Failed to get Tx DMA channel\n"); - return; - } else if (cris_request_dma(ATA_RX_DMA_NBR, - "ETRAX100LX IDE RX", - DMA_VERBOSE_ON_ERROR, - dma_ata)) { - cris_free_dma(ATA_TX_DMA_NBR, "ETRAX100LX IDE Tx"); - cris_free_io_interface(if_ata); - printk(KERN_CRIT "ide: Failed to get Rx DMA channel\n"); - return; - } - - /* make a dummy read to set the ata controller in a proper state */ - dummy = *R_ATA_STATUS_DATA; - - *R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable, 1 )); - *R_ATA_CTRL_DATA = ( IO_STATE( R_ATA_CTRL_DATA, rw, read) | - IO_FIELD( R_ATA_CTRL_DATA, addr, 1 ) ); - - while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)); /* wait for busy flag*/ - - *R_IRQ_MASK0_SET = ( IO_STATE( R_IRQ_MASK0_SET, ata_irq0, set ) | - IO_STATE( R_IRQ_MASK0_SET, ata_irq1, set ) | - IO_STATE( R_IRQ_MASK0_SET, ata_irq2, set ) | - IO_STATE( R_IRQ_MASK0_SET, ata_irq3, set ) ); - - /* reset the dma channels we will use */ - - RESET_DMA(ATA_TX_DMA_NBR); - RESET_DMA(ATA_RX_DMA_NBR); - WAIT_DMA(ATA_TX_DMA_NBR); - WAIT_DMA(ATA_RX_DMA_NBR); -} - -#define cris_dma_descr_type etrax_dma_descr -#define cris_pio_read IO_STATE(R_ATA_CTRL_DATA, rw, read) -#define cris_ultra_mask 0x0 -#define MAX_DESCR_SIZE 0x10000UL - -static unsigned long -cris_ide_get_reg(unsigned long reg) -{ - return (reg & 0x0e000000) >> 25; -} - -static void -cris_ide_fill_descriptor(cris_dma_descr_type *d, void* buf, unsigned int len, int last) -{ - d->buf = virt_to_phys(buf); - d->sw_len = len == MAX_DESCR_SIZE ? 0 : len; - if (last) - d->ctrl |= d_eol; -} - -static void cris_ide_start_dma(ide_drive_t *drive, cris_dma_descr_type *d, int dir, int type, int len) -{ - unsigned long cmd; - - if (dir) { - /* need to do this before RX DMA due to a chip bug - * it is enough to just flush the part of the cache that - * corresponds to the buffers we start, but since HD transfers - * usually are more than 8 kB, it is easier to optimize for the - * normal case and just flush the entire cache. its the only - * way to be sure! (OB movie quote) - */ - flush_etrax_cache(); - *R_DMA_CH3_FIRST = virt_to_phys(d); - *R_DMA_CH3_CMD = IO_STATE(R_DMA_CH3_CMD, cmd, start); - - } else { - *R_DMA_CH2_FIRST = virt_to_phys(d); - *R_DMA_CH2_CMD = IO_STATE(R_DMA_CH2_CMD, cmd, start); - } - - /* initiate a multi word dma read using DMA handshaking */ - - *R_ATA_TRANSFER_CNT = - IO_FIELD(R_ATA_TRANSFER_CNT, count, len >> 1); - - cmd = dir ? IO_STATE(R_ATA_CTRL_DATA, rw, read) : IO_STATE(R_ATA_CTRL_DATA, rw, write); - cmd |= type == TYPE_PIO ? IO_STATE(R_ATA_CTRL_DATA, handsh, pio) : - IO_STATE(R_ATA_CTRL_DATA, handsh, dma); - *R_ATA_CTRL_DATA = - cmd | - IO_FIELD(R_ATA_CTRL_DATA, data, - drive->hwif->io_ports[IDE_DATA_OFFSET]) | - IO_STATE(R_ATA_CTRL_DATA, src_dst, dma) | - IO_STATE(R_ATA_CTRL_DATA, multi, on) | - IO_STATE(R_ATA_CTRL_DATA, dma_size, word); -} - -static void -cris_ide_wait_dma(int dir) -{ - if (dir) - WAIT_DMA(ATA_RX_DMA_NBR); - else - WAIT_DMA(ATA_TX_DMA_NBR); -} - -static int cris_dma_test_irq(ide_drive_t *drive) -{ - int intr = *R_IRQ_MASK0_RD; - int bus = IO_EXTRACT(R_ATA_CTRL_DATA, sel, - drive->hwif->io_ports[IDE_DATA_OFFSET]); - - return intr & (1 << (bus + IO_BITNR(R_IRQ_MASK0_RD, ata_irq0))) ? 1 : 0; -} - - -static void cris_ide_initialize_dma(int dir) -{ - if (dir) - { - RESET_DMA(ATA_RX_DMA_NBR); /* sometimes the DMA channel get stuck so we need to do this */ - WAIT_DMA(ATA_RX_DMA_NBR); - } - else - { - RESET_DMA(ATA_TX_DMA_NBR); /* sometimes the DMA channel get stuck so we need to do this */ - WAIT_DMA(ATA_TX_DMA_NBR); - } -} - -#endif - -void -cris_ide_outw(unsigned short data, unsigned long reg) { - int timeleft; - - LOWDB(printk("ow: data 0x%x, reg 0x%x\n", data, reg)); - - /* note the lack of handling any timeouts. we stop waiting, but we don't - * really notify anybody. - */ - - timeleft = IDE_REGISTER_TIMEOUT; - /* wait for busy flag */ - do { - timeleft--; - } while(timeleft && cris_ide_busy()); - - /* - * Fall through at a timeout, so the ongoing command will be - * aborted by the write below, which is expected to be a dummy - * command to the command register. This happens when a faulty - * drive times out on a command. See comment on timeout in - * INB. - */ - if(!timeleft) - printk("ATA timeout reg 0x%lx := 0x%x\n", reg, data); - - cris_ide_write_command(reg|data); /* write data to the drive's register */ - - timeleft = IDE_REGISTER_TIMEOUT; - /* wait for transmitter ready */ - do { - timeleft--; - } while(timeleft && !cris_ide_ready()); -} - -void -cris_ide_outb(unsigned char data, unsigned long reg) -{ - cris_ide_outw(data, reg); -} - -void -cris_ide_outbsync(ide_drive_t *drive, u8 addr, unsigned long port) -{ - cris_ide_outw(addr, port); -} - -unsigned short -cris_ide_inw(unsigned long reg) { - int timeleft; - unsigned short val; - - timeleft = IDE_REGISTER_TIMEOUT; - /* wait for busy flag */ - do { - timeleft--; - } while(timeleft && cris_ide_busy()); - - if(!timeleft) { - /* - * If we're asked to read the status register, like for - * example when a command does not complete for an - * extended time, but the ATA interface is stuck in a - * busy state at the *ETRAX* ATA interface level (as has - * happened repeatedly with at least one bad disk), then - * the best thing to do is to pretend that we read - * "busy" in the status register, so the IDE driver will - * time-out, abort the ongoing command and perform a - * reset sequence. Note that the subsequent OUT_BYTE - * call will also timeout on busy, but as long as the - * write is still performed, everything will be fine. - */ - if (cris_ide_get_reg(reg) == IDE_STATUS_OFFSET) - return BUSY_STAT; - else - /* For other rare cases we assume 0 is good enough. */ - return 0; - } - - cris_ide_write_command(reg | cris_pio_read); - - timeleft = IDE_REGISTER_TIMEOUT; - /* wait for available */ - do { - timeleft--; - } while(timeleft && !cris_ide_data_available(&val)); - - if(!timeleft) - return 0; - - LOWDB(printk("inb: 0x%x from reg 0x%x\n", val & 0xff, reg)); - - return val; -} - -unsigned char -cris_ide_inb(unsigned long reg) -{ - return (unsigned char)cris_ide_inw(reg); -} - -static void cris_ide_input_data (ide_drive_t *drive, void *, unsigned int); -static void cris_ide_output_data (ide_drive_t *drive, void *, unsigned int); -static void cris_atapi_input_bytes(ide_drive_t *drive, void *, unsigned int); -static void cris_atapi_output_bytes(ide_drive_t *drive, void *, unsigned int); - -static void cris_dma_host_set(ide_drive_t *drive, int on) -{ -} - -static void cris_set_pio_mode(ide_drive_t *drive, const u8 pio) -{ - int setup, strobe, hold; - - switch(pio) - { - case 0: - setup = ATA_PIO0_SETUP; - strobe = ATA_PIO0_STROBE; - hold = ATA_PIO0_HOLD; - break; - case 1: - setup = ATA_PIO1_SETUP; - strobe = ATA_PIO1_STROBE; - hold = ATA_PIO1_HOLD; - break; - case 2: - setup = ATA_PIO2_SETUP; - strobe = ATA_PIO2_STROBE; - hold = ATA_PIO2_HOLD; - break; - case 3: - setup = ATA_PIO3_SETUP; - strobe = ATA_PIO3_STROBE; - hold = ATA_PIO3_HOLD; - break; - case 4: - setup = ATA_PIO4_SETUP; - strobe = ATA_PIO4_STROBE; - hold = ATA_PIO4_HOLD; - break; - default: - return; - } - - cris_ide_set_speed(TYPE_PIO, setup, strobe, hold); -} - -static void cris_set_dma_mode(ide_drive_t *drive, const u8 speed) -{ - int cyc = 0, dvs = 0, strobe = 0, hold = 0; - - switch(speed) - { - case XFER_UDMA_0: - cyc = ATA_UDMA0_CYC; - dvs = ATA_UDMA0_DVS; - break; - case XFER_UDMA_1: - cyc = ATA_UDMA1_CYC; - dvs = ATA_UDMA1_DVS; - break; - case XFER_UDMA_2: - cyc = ATA_UDMA2_CYC; - dvs = ATA_UDMA2_DVS; - break; - case XFER_MW_DMA_0: - strobe = ATA_DMA0_STROBE; - hold = ATA_DMA0_HOLD; - break; - case XFER_MW_DMA_1: - strobe = ATA_DMA1_STROBE; - hold = ATA_DMA1_HOLD; - break; - case XFER_MW_DMA_2: - strobe = ATA_DMA2_STROBE; - hold = ATA_DMA2_HOLD; - break; - } - - if (speed >= XFER_UDMA_0) - cris_ide_set_speed(TYPE_UDMA, cyc, dvs, 0); - else - cris_ide_set_speed(TYPE_DMA, 0, strobe, hold); -} - -static void __init cris_setup_ports(hw_regs_t *hw, unsigned long base) -{ - int i; - - memset(hw, 0, sizeof(*hw)); - - for (i = 0; i <= 7; i++) - hw->io_ports[i] = base + cris_ide_reg_addr(i, 0, 1); - - /* - * the IDE control register is at ATA address 6, - * with CS1 active instead of CS0 - */ - hw->io_ports[IDE_CONTROL_OFFSET] = base + cris_ide_reg_addr(6, 1, 0); - - hw->irq = ide_default_irq(0); - hw->ack_intr = cris_ide_ack_intr; -} - -static const struct ide_port_ops cris_port_ops = { - .set_pio_mode = cris_set_pio_mode, - .set_dma_mode = cris_set_dma_mode, -}; - -static const struct ide_dma_ops cris_dma_ops; - -static const struct ide_port_info cris_port_info __initdata = { - .chipset = ide_etrax100, - .port_ops = &cris_port_ops, - .dma_ops = &cris_dma_ops, - .host_flags = IDE_HFLAG_NO_ATAPI_DMA | - IDE_HFLAG_NO_DMA, /* no SFF-style DMA */ - .pio_mask = ATA_PIO4, - .udma_mask = cris_ultra_mask, - .mwdma_mask = ATA_MWDMA2, -}; - -static int __init init_e100_ide(void) -{ - hw_regs_t hw; - int h; - u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; - - printk("ide: ETRAX FS built-in ATA DMA controller\n"); - - for (h = 0; h < 4; h++) { - ide_hwif_t *hwif = NULL; - - cris_setup_ports(&hw, cris_ide_base_address(h)); - - hwif = ide_find_port(); - if (hwif == NULL) - continue; - ide_init_port_data(hwif, hwif->index); - ide_init_port_hw(hwif, &hw); - - hwif->ata_input_data = &cris_ide_input_data; - hwif->ata_output_data = &cris_ide_output_data; - hwif->atapi_input_bytes = &cris_atapi_input_bytes; - hwif->atapi_output_bytes = &cris_atapi_output_bytes; - hwif->OUTB = &cris_ide_outb; - hwif->OUTW = &cris_ide_outw; - hwif->OUTBSYNC = &cris_ide_outbsync; - hwif->INB = &cris_ide_inb; - hwif->INW = &cris_ide_inw; - hwif->cbl = ATA_CBL_PATA40; - - idx[h] = hwif->index; - } - - /* Reset pulse */ - cris_ide_reset(0); - udelay(25); - cris_ide_reset(1); - - cris_ide_init(); - - cris_ide_set_speed(TYPE_PIO, ATA_PIO4_SETUP, ATA_PIO4_STROBE, ATA_PIO4_HOLD); - cris_ide_set_speed(TYPE_DMA, 0, ATA_DMA2_STROBE, ATA_DMA2_HOLD); - cris_ide_set_speed(TYPE_UDMA, ATA_UDMA2_CYC, ATA_UDMA2_DVS, 0); - - ide_device_add(idx, &cris_port_info); - - return 0; -} - -static cris_dma_descr_type mydescr __attribute__ ((__aligned__(16))); - -/* - * 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 -cris_atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) -{ - D(printk("atapi_input_bytes, buffer 0x%x, count %d\n", - buffer, bytecount)); - - if(bytecount & 1) { - printk("warning, odd bytecount in cdrom_in_bytes = %d.\n", bytecount); - bytecount++; /* to round off */ - } - - /* setup DMA and start transfer */ - - cris_ide_fill_descriptor(&mydescr, buffer, bytecount, 1); - cris_ide_start_dma(drive, &mydescr, 1, TYPE_PIO, bytecount); - - /* wait for completion */ - LED_DISK_READ(1); - cris_ide_wait_dma(1); - LED_DISK_READ(0); -} - -static void -cris_atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) -{ - D(printk("atapi_output_bytes, buffer 0x%x, count %d\n", - buffer, bytecount)); - - if(bytecount & 1) { - printk("odd bytecount %d in atapi_out_bytes!\n", bytecount); - bytecount++; - } - - cris_ide_fill_descriptor(&mydescr, buffer, bytecount, 1); - cris_ide_start_dma(drive, &mydescr, 0, TYPE_PIO, bytecount); - - /* wait for completion */ - - LED_DISK_WRITE(1); - LED_DISK_READ(1); - cris_ide_wait_dma(0); - LED_DISK_WRITE(0); -} - -/* - * This is used for most PIO data transfers *from* the IDE interface - */ -static void -cris_ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) -{ - cris_atapi_input_bytes(drive, buffer, wcount << 2); -} - -/* - * This is used for most PIO data transfers *to* the IDE interface - */ -static void -cris_ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) -{ - cris_atapi_output_bytes(drive, buffer, wcount << 2); -} - -/* we only have one DMA channel on the chip for ATA, so we can keep these statically */ -static cris_dma_descr_type ata_descrs[MAX_DMA_DESCRS] __attribute__ ((__aligned__(16))); -static unsigned int ata_tot_size; - -/* - * cris_ide_build_dmatable() prepares a dma request. - * Returns 0 if all went okay, returns 1 otherwise. - */ -static int cris_ide_build_dmatable (ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - struct scatterlist* sg; - struct request *rq = drive->hwif->hwgroup->rq; - unsigned long size, addr; - unsigned int count = 0; - int i = 0; - - sg = hwif->sg_table; - - ata_tot_size = 0; - - ide_map_sg(drive, rq); - i = hwif->sg_nents; - - while(i) { - /* - * Determine addr and size of next buffer area. We assume that - * individual virtual buffers are always composed linearly in - * physical memory. For example, we assume that any 8kB buffer - * is always composed of two adjacent physical 4kB pages rather - * than two possibly non-adjacent physical 4kB pages. - */ - /* group sequential buffers into one large buffer */ - addr = sg_phys(sg); - size = sg_dma_len(sg); - while (--i) { - sg = sg_next(sg); - if ((addr + size) != sg_phys(sg)) - break; - size += sg_dma_len(sg); - } - - /* did we run out of descriptors? */ - - if(count >= MAX_DMA_DESCRS) { - printk("%s: too few DMA descriptors\n", drive->name); - return 1; - } - - /* however, this case is more difficult - rw_trf_cnt cannot be more - than 65536 words per transfer, so in that case we need to either - 1) use a DMA interrupt to re-trigger rw_trf_cnt and continue with - the descriptors, or - 2) simply do the request here, and get dma_intr to only ide_end_request on - those blocks that were actually set-up for transfer. - */ - - if(ata_tot_size + size > 131072) { - printk("too large total ATA DMA request, %d + %d!\n", ata_tot_size, (int)size); - return 1; - } - - /* If size > MAX_DESCR_SIZE it has to be splitted into new descriptors. Since we - don't handle size > 131072 only one split is necessary */ - - if(size > MAX_DESCR_SIZE) { - cris_ide_fill_descriptor(&ata_descrs[count], (void*)addr, MAX_DESCR_SIZE, 0); - count++; - ata_tot_size += MAX_DESCR_SIZE; - size -= MAX_DESCR_SIZE; - addr += MAX_DESCR_SIZE; - } - - cris_ide_fill_descriptor(&ata_descrs[count], (void*)addr, size,i ? 0 : 1); - count++; - ata_tot_size += size; - } - - if (count) { - /* return and say all is ok */ - return 0; - } - - printk("%s: empty DMA table?\n", drive->name); - return 1; /* let the PIO routines handle this weirdness */ -} - -/* - * cris_dma_intr() is the handler for disk read/write DMA interrupts - */ -static ide_startstop_t cris_dma_intr (ide_drive_t *drive) -{ - LED_DISK_READ(0); - LED_DISK_WRITE(0); - - return ide_dma_intr(drive); -} - -/* - * Functions below initiates/aborts DMA read/write operations on a drive. - * - * The caller is assumed to have selected the drive and programmed the drive's - * sector address using CHS or LBA. All that remains is to prepare for DMA - * and then issue the actual read/write DMA/PIO command to the drive. - * - * For ATAPI devices, we just prepare for DMA and return. The caller should - * then issue the packet command to the drive and call us again with - * cris_dma_start afterwards. - * - * Returns 0 if all went well. - * Returns 1 if DMA read/write could not be started, in which case - * the caller should revert to PIO for the current request. - */ - -static int cris_dma_end(ide_drive_t *drive) -{ - drive->waiting_for_dma = 0; - return 0; -} - -static int cris_dma_setup(ide_drive_t *drive) -{ - struct request *rq = drive->hwif->hwgroup->rq; - - cris_ide_initialize_dma(!rq_data_dir(rq)); - if (cris_ide_build_dmatable (drive)) { - ide_map_sg(drive, rq); - return 1; - } - - drive->waiting_for_dma = 1; - return 0; -} - -static void cris_dma_exec_cmd(ide_drive_t *drive, u8 command) -{ - ide_execute_command(drive, command, &cris_dma_intr, WAIT_CMD, NULL); -} - -static void cris_dma_start(ide_drive_t *drive) -{ - struct request *rq = drive->hwif->hwgroup->rq; - int writing = rq_data_dir(rq); - int type = TYPE_DMA; - - if (drive->current_speed >= XFER_UDMA_0) - type = TYPE_UDMA; - - cris_ide_start_dma(drive, &ata_descrs[0], writing ? 0 : 1, type, ata_tot_size); - - if (writing) { - LED_DISK_WRITE(1); - } else { - LED_DISK_READ(1); - } -} - -static const struct ide_dma_ops cris_dma_ops = { - .dma_host_set = cris_dma_host_set, - .dma_setup = cris_dma_setup, - .dma_exec_cmd = cris_dma_exec_cmd, - .dma_start = cris_dma_start, - .dma_end = cris_dma_end, - .dma_test_irq = cris_dma_test_irq, -}; - -module_init(init_e100_ide); - -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c index 0708b29cdb17..ecf53bb0d2aa 100644 --- a/drivers/ide/h8300/ide-h8300.c +++ b/drivers/ide/h8300/ide-h8300.c @@ -42,6 +42,91 @@ static u16 mm_inw(unsigned long a) return r; } +static void h8300_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; + u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; + + if (task->tf_flags & IDE_TFLAG_FLAGGED) + HIHI = 0xFF; + + ide_set_irq(drive, 1); + + if (task->tf_flags & IDE_TFLAG_OUT_DATA) + mm_outw((tf->hob_data << 8) | tf->data, io_ports->data_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) + outb(tf->hob_feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) + outb(tf->hob_nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) + outb(tf->hob_lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) + outb(tf->hob_lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) + outb(tf->hob_lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) + outb(tf->feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_NSECT) + outb(tf->nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAL) + outb(tf->lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAM) + outb(tf->lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAH) + outb(tf->lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) + outb((tf->device & HIHI) | drive->select.all, + io_ports->device_addr); +} + +static void h8300_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; + + if (task->tf_flags & IDE_TFLAG_IN_DATA) { + u16 data = mm_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 */ + outb(drive->ctl & ~0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_NSECT) + tf->nsect = inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAL) + tf->lbal = inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAM) + tf->lbam = inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAH) + tf->lbah = inb(io_ports->lbah_addr); + if (task->tf_flags & IDE_TFLAG_IN_DEVICE) + tf->device = inb(io_ports->device_addr); + + if (task->tf_flags & IDE_TFLAG_LBA48) { + outb(drive->ctl | 0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) + tf->hob_feature = inb(io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) + tf->hob_nsect = inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) + tf->hob_lbal = inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) + tf->hob_lbam = inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) + tf->hob_lbah = inb(io_ports->lbah_addr); + } +} + static void mm_outsw(unsigned long addr, void *buf, u32 len) { unsigned short *bp = (unsigned short *)buf; @@ -56,6 +141,18 @@ static void mm_insw(unsigned long addr, void *buf, u32 len) *bp = bswap(*(volatile u16 *)addr); } +static void h8300_input_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + mm_insw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2); +} + +static void h8300_output_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + mm_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2); +} + #define H8300_IDE_GAP (2) static inline void hw_setup(hw_regs_t *hw) @@ -63,9 +160,9 @@ static inline void hw_setup(hw_regs_t *hw) int i; memset(hw, 0, sizeof(hw_regs_t)); - for (i = 0; i <= IDE_STATUS_OFFSET; i++) - hw->io_ports[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i; - hw->io_ports[IDE_CONTROL_OFFSET] = CONFIG_H8300_IDE_ALT; + for (i = 0; i <= 7; i++) + hw->io_ports_array[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i; + hw->io_ports.ctl_addr = CONFIG_H8300_IDE_ALT; hw->irq = EXT_IRQ0 + CONFIG_H8300_IDE_IRQ; hw->chipset = ide_generic; } @@ -74,12 +171,11 @@ static inline void hwif_setup(ide_hwif_t *hwif) { default_hwif_iops(hwif); - hwif->OUTW = mm_outw; - hwif->OUTSW = mm_outsw; - hwif->INW = mm_inw; - hwif->INSW = mm_insw; - hwif->OUTSL = NULL; - hwif->INSL = NULL; + 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 int __init h8300_ide_init(void) diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index e4ad26e4fce7..9d3601fa5680 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -60,9 +60,17 @@ struct ide_acpi_hwif_link { #define DEBPRINT(fmt, args...) do {} while (0) #endif /* DEBUGGING */ -extern int ide_noacpi; -extern int ide_noacpitfs; -extern int ide_noacpionboot; +int ide_noacpi; +module_param_named(noacpi, ide_noacpi, bool, 0); +MODULE_PARM_DESC(noacpi, "disable IDE ACPI support"); + +int ide_acpigtf; +module_param_named(acpigtf, ide_acpigtf, bool, 0); +MODULE_PARM_DESC(acpigtf, "enable IDE ACPI _GTF support"); + +int ide_acpionboot; +module_param_named(acpionboot, ide_acpionboot, bool, 0); +MODULE_PARM_DESC(acpionboot, "call IDE ACPI methods on boot"); static bool ide_noacpi_psx; static int no_acpi_psx(const struct dmi_system_id *id) @@ -376,7 +384,7 @@ static int taskfile_load_raw(ide_drive_t *drive, memcpy(&args.tf_array[7], >f->tfa, 7); args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - if (ide_noacpitfs) { + if (!ide_acpigtf) { DEBPRINT("_GTF execution disabled\n"); return err; } @@ -721,7 +729,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif) drive->name, err); } - if (ide_noacpionboot) { + if (!ide_acpionboot) { DEBPRINT("ACPI methods disabled on boot\n"); return; } diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index ad984322da94..68e7f19dc036 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -142,7 +142,6 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive, { unsigned long sector; unsigned long bio_sectors; - unsigned long valid; struct cdrom_info *info = drive->driver_data; if (!cdrom_log_sense(drive, failed_command, sense)) @@ -173,17 +172,13 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive, (sense->information[2] << 8) | (sense->information[3]); - bio_sectors = bio_sectors(failed_command->bio); - if (bio_sectors < 4) - bio_sectors = 4; if (drive->queue->hardsect_size == 2048) /* device sector size is 2K */ sector <<= 2; + + bio_sectors = max(bio_sectors(failed_command->bio), 4U); sector &= ~(bio_sectors - 1); - valid = (sector - failed_command->sector) << 9; - if (valid < 0) - valid = 0; if (sector < get_capacity(info->disk) && drive->probed_capacity - sector < 4 * 75) set_capacity(info->disk, sector); @@ -555,14 +550,7 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, ATAPI_WAIT_PC, cdrom_timer_expiry); return ide_started; } else { - unsigned long flags; - - /* packet command */ - spin_lock_irqsave(&ide_lock, flags); - hwif->OUTBSYNC(drive, WIN_PACKETCMD, - hwif->io_ports[IDE_COMMAND_OFFSET]); - ndelay(400); - spin_unlock_irqrestore(&ide_lock, flags); + ide_execute_pkt_cmd(drive); return (*handler) (drive); } @@ -613,7 +601,7 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive, cmd_len = ATAPI_MIN_CDB_BYTES; /* send the command to the device */ - HWIF(drive)->atapi_output_bytes(drive, rq->cmd, cmd_len); + hwif->output_data(drive, NULL, rq->cmd, cmd_len); /* start the DMA if need be */ if (info->dma) @@ -629,7 +617,7 @@ static void ide_cd_pad_transfer(ide_drive_t *drive, xfer_func_t *xf, int len) { while (len > 0) { int dum = 0; - xf(drive, &dum, sizeof(dum)); + xf(drive, NULL, &dum, sizeof(dum)); len -= sizeof(dum); } } @@ -639,7 +627,7 @@ static void ide_cd_drain_data(ide_drive_t *drive, int nsects) while (nsects > 0) { static char dum[SECTOR_SIZE]; - drive->hwif->atapi_input_bytes(drive, dum, sizeof(dum)); + drive->hwif->input_data(drive, NULL, dum, sizeof(dum)); nsects--; } } @@ -666,7 +654,7 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq, printk(KERN_ERR "%s: %s: wrong transfer direction!\n", drive->name, __func__); - xf = rw ? hwif->atapi_output_bytes : hwif->atapi_input_bytes; + xf = rw ? hwif->output_data : hwif->input_data; ide_cd_pad_transfer(drive, xf, len); } else if (rw == 0 && ireason == 1) { /* @@ -794,7 +782,7 @@ static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive) sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS); - memset(rq->cmd, 0, sizeof(rq->cmd)); + memset(rq->cmd, 0, BLK_MAX_CDB); rq->cmd[0] = GPCMD_SEEK; put_unaligned(cpu_to_be32(frame), (unsigned int *) &rq->cmd[2]); @@ -952,9 +940,9 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) } /* ok we fall to pio :/ */ - ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]) & 0x3; - lowcyl = hwif->INB(hwif->io_ports[IDE_BCOUNTL_OFFSET]); - highcyl = hwif->INB(hwif->io_ports[IDE_BCOUNTH_OFFSET]); + ireason = hwif->INB(hwif->io_ports.nsect_addr) & 0x3; + lowcyl = hwif->INB(hwif->io_ports.lbam_addr); + highcyl = hwif->INB(hwif->io_ports.lbah_addr); len = lowcyl + (256 * highcyl); @@ -1019,10 +1007,10 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) if (ireason == 0) { write = 1; - xferfunc = HWIF(drive)->atapi_output_bytes; + xferfunc = hwif->output_data; } else { write = 0; - xferfunc = HWIF(drive)->atapi_input_bytes; + xferfunc = hwif->input_data; } /* transfer data */ @@ -1061,7 +1049,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) if (blen > thislen) blen = thislen; - xferfunc(drive, ptr, blen); + xferfunc(drive, NULL, ptr, blen); thislen -= blen; len -= blen; @@ -1706,7 +1694,7 @@ static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq) long block = (long)rq->hard_sector / (hard_sect >> 9); unsigned long blocks = rq->hard_nr_sectors / (hard_sect >> 9); - memset(rq->cmd, 0, sizeof(rq->cmd)); + memset(rq->cmd, 0, BLK_MAX_CDB); if (rq_data_dir(rq) == READ) rq->cmd[0] = GPCMD_READ_10; @@ -1909,9 +1897,7 @@ static int ide_cdrom_setup(ide_drive_t *drive) /* set correct block size */ blk_queue_hardsect_size(drive->queue, CD_FRAMESIZE); - if (drive->autotune == IDE_TUNE_DEFAULT || - drive->autotune == IDE_TUNE_AUTO) - drive->dsc_overlap = (drive->next != drive); + drive->dsc_overlap = (drive->next != drive); if (ide_cdrom_register(drive, nslots)) { printk(KERN_ERR "%s: %s failed to register device with the" diff --git a/drivers/ide/ide-cd_verbose.c b/drivers/ide/ide-cd_verbose.c index 6ed7ca071331..6490a2dea96b 100644 --- a/drivers/ide/ide-cd_verbose.c +++ b/drivers/ide/ide-cd_verbose.c @@ -326,7 +326,7 @@ void ide_cd_log_error(const char *name, struct request *failed_command, printk(KERN_ERR " The failed \"%s\" packet command " "was: \n \"", s); - for (i = 0; i < sizeof(failed_command->cmd); i++) + for (i = 0; i < BLK_MAX_CDB; i++) printk(KERN_CONT "%02x ", failed_command->cmd[i]); printk(KERN_CONT "\"\n"); } diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index c352cf27b6e7..653b1ade13d3 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -464,9 +464,10 @@ int ide_dma_setup(ide_drive_t *drive) /* PRD table */ if (hwif->mmio) - writel(hwif->dmatable_dma, (void __iomem *)hwif->dma_prdtable); + writel(hwif->dmatable_dma, + (void __iomem *)(hwif->dma_base + ATA_DMA_TABLE_OFS)); else - outl(hwif->dmatable_dma, hwif->dma_prdtable); + outl(hwif->dmatable_dma, hwif->dma_base + ATA_DMA_TABLE_OFS); /* specify r/w */ hwif->OUTB(reading, hwif->dma_command); @@ -858,14 +859,8 @@ void ide_setup_dma(ide_hwif_t *hwif, unsigned long base) if (!hwif->dma_command) hwif->dma_command = hwif->dma_base + 0; - if (!hwif->dma_vendor1) - hwif->dma_vendor1 = hwif->dma_base + 1; if (!hwif->dma_status) hwif->dma_status = hwif->dma_base + 2; - if (!hwif->dma_vendor3) - hwif->dma_vendor3 = hwif->dma_base + 3; - if (!hwif->dma_prdtable) - hwif->dma_prdtable = hwif->dma_base + 4; hwif->dma_ops = &sff_dma_ops; } diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 6e891bccd052..f05fbc2bd7a8 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -231,6 +231,7 @@ static int idefloppy_end_request(ide_drive_t *drive, int uptodate, int nsecs) static void ide_floppy_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, unsigned int bcount, int direction) { + ide_hwif_t *hwif = drive->hwif; struct request *rq = pc->rq; struct req_iterator iter; struct bio_vec *bvec; @@ -246,9 +247,9 @@ static void ide_floppy_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, data = bvec_kmap_irq(bvec, &flags); if (direction) - drive->hwif->atapi_output_bytes(drive, data, count); + hwif->output_data(drive, NULL, data, count); else - drive->hwif->atapi_input_bytes(drive, data, count); + hwif->input_data(drive, NULL, data, count); bvec_kunmap_irq(data, &flags); bcount -= count; @@ -261,10 +262,7 @@ static void ide_floppy_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, if (bcount) { printk(KERN_ERR "%s: leftover data in %s, bcount == %d\n", drive->name, __func__, bcount); - if (direction) - ide_atapi_write_zeros(drive, bcount); - else - ide_atapi_discard_data(drive, bcount); + ide_pad_transfer(drive, direction, bcount); } } @@ -465,10 +463,10 @@ static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive) } /* Get the number of bytes to transfer */ - bcount = (hwif->INB(hwif->io_ports[IDE_BCOUNTH_OFFSET]) << 8) | - hwif->INB(hwif->io_ports[IDE_BCOUNTL_OFFSET]); + bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) | + hwif->INB(hwif->io_ports.lbam_addr); /* on this interrupt */ - ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]); + ireason = hwif->INB(hwif->io_ports.nsect_addr); if (ireason & CD) { printk(KERN_ERR "ide-floppy: CoD != 0 in %s\n", __func__); @@ -490,7 +488,7 @@ static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive) printk(KERN_ERR "ide-floppy: The floppy wants " "to send us more data than expected " "- discarding data\n"); - ide_atapi_discard_data(drive, bcount); + ide_pad_transfer(drive, 0, bcount); ide_set_handler(drive, &idefloppy_pc_intr, @@ -503,12 +501,12 @@ static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive) } } if (pc->flags & PC_FLAG_WRITING) - xferfunc = hwif->atapi_output_bytes; + xferfunc = hwif->output_data; else - xferfunc = hwif->atapi_input_bytes; + xferfunc = hwif->input_data; if (pc->buf) - xferfunc(drive, pc->cur_pos, bcount); + xferfunc(drive, NULL, pc->cur_pos, bcount); else ide_floppy_io_buffers(drive, pc, bcount, !!(pc->flags & PC_FLAG_WRITING)); @@ -539,7 +537,7 @@ static ide_startstop_t idefloppy_transfer_pc(ide_drive_t *drive) "initiated yet DRQ isn't asserted\n"); return startstop; } - ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]); + ireason = hwif->INB(hwif->io_ports.nsect_addr); if ((ireason & CD) == 0 || (ireason & IO)) { printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while " "issuing a packet command\n"); @@ -548,8 +546,10 @@ static ide_startstop_t idefloppy_transfer_pc(ide_drive_t *drive) /* Set the interrupt routine */ ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); + /* Send the actual packet */ - HWIF(drive)->atapi_output_bytes(drive, floppy->pc->c, 12); + hwif->output_data(drive, NULL, floppy->pc->c, 12); + return ide_started; } @@ -569,7 +569,8 @@ static int idefloppy_transfer_pc2(ide_drive_t *drive) idefloppy_floppy_t *floppy = drive->driver_data; /* Send the actual packet */ - HWIF(drive)->atapi_output_bytes(drive, floppy->pc->c, 12); + drive->hwif->output_data(drive, NULL, floppy->pc->c, 12); + /* Timeout for the packet command */ return IDEFLOPPY_WAIT_CMD; } @@ -586,7 +587,7 @@ static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive) "initiated yet DRQ isn't asserted\n"); return startstop; } - ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]); + ireason = hwif->INB(hwif->io_ports.nsect_addr); if ((ireason & CD) == 0 || (ireason & IO)) { printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) " "while issuing a packet command\n"); @@ -692,7 +693,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive, return ide_started; } else { /* Issue the packet command */ - hwif->OUTB(WIN_PACKETCMD, hwif->io_ports[IDE_COMMAND_OFFSET]); + ide_execute_pkt_cmd(drive); return (*pkt_xfer_routine) (drive); } } diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 0fe89a599275..696525342e9a 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -295,54 +295,6 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq) spin_unlock_irqrestore(&ide_lock, flags); } -void ide_tf_read(ide_drive_t *drive, ide_task_t *task) -{ - ide_hwif_t *hwif = drive->hwif; - struct ide_taskfile *tf = &task->tf; - - if (task->tf_flags & IDE_TFLAG_IN_DATA) { - u16 data = hwif->INW(hwif->io_ports[IDE_DATA_OFFSET]); - - tf->data = data & 0xff; - tf->hob_data = (data >> 8) & 0xff; - } - - /* be sure we're looking at the low order bits */ - hwif->OUTB(drive->ctl & ~0x80, hwif->io_ports[IDE_CONTROL_OFFSET]); - - if (task->tf_flags & IDE_TFLAG_IN_NSECT) - tf->nsect = hwif->INB(hwif->io_ports[IDE_NSECTOR_OFFSET]); - if (task->tf_flags & IDE_TFLAG_IN_LBAL) - tf->lbal = hwif->INB(hwif->io_ports[IDE_SECTOR_OFFSET]); - if (task->tf_flags & IDE_TFLAG_IN_LBAM) - tf->lbam = hwif->INB(hwif->io_ports[IDE_LCYL_OFFSET]); - if (task->tf_flags & IDE_TFLAG_IN_LBAH) - tf->lbah = hwif->INB(hwif->io_ports[IDE_HCYL_OFFSET]); - if (task->tf_flags & IDE_TFLAG_IN_DEVICE) - tf->device = hwif->INB(hwif->io_ports[IDE_SELECT_OFFSET]); - - if (task->tf_flags & IDE_TFLAG_LBA48) { - hwif->OUTB(drive->ctl | 0x80, - hwif->io_ports[IDE_CONTROL_OFFSET]); - - if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) - tf->hob_feature = - hwif->INB(hwif->io_ports[IDE_FEATURE_OFFSET]); - if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) - tf->hob_nsect = - hwif->INB(hwif->io_ports[IDE_NSECTOR_OFFSET]); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) - tf->hob_lbal = - hwif->INB(hwif->io_ports[IDE_SECTOR_OFFSET]); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) - tf->hob_lbam = - hwif->INB(hwif->io_ports[IDE_LCYL_OFFSET]); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) - tf->hob_lbah = - hwif->INB(hwif->io_ports[IDE_HCYL_OFFSET]); - } -} - /** * ide_end_drive_cmd - end an explicit drive command * @drive: command @@ -378,7 +330,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) tf->error = err; tf->status = stat; - ide_tf_read(drive, task); + drive->hwif->tf_read(drive, task); if (task->tf_flags & IDE_TFLAG_DYN) kfree(task); @@ -427,7 +379,7 @@ static void try_to_flush_leftover_data (ide_drive_t *drive) u32 wcount = (i > 16) ? 16 : i; i -= wcount; - HWIF(drive)->ata_input_data(drive, buffer, wcount); + drive->hwif->input_data(drive, NULL, buffer, wcount * 4); } } @@ -454,7 +406,7 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 if (err == ABRT_ERR) { if (drive->select.b.lba && /* some newer drives don't support WIN_SPECIFY */ - hwif->INB(hwif->io_ports[IDE_COMMAND_OFFSET]) == + hwif->INB(hwif->io_ports.command_addr) == WIN_SPECIFY) return ide_stopped; } else if ((err & BAD_CRC) == BAD_CRC) { @@ -507,8 +459,8 @@ static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT)) /* force an abort */ - hwif->OUTB(WIN_IDLEIMMEDIATE, - hwif->io_ports[IDE_COMMAND_OFFSET]); + hwif->OUTBSYNC(drive, WIN_IDLEIMMEDIATE, + hwif->io_ports.command_addr); if (rq->errors >= ERROR_MAX) { ide_kill_rq(drive, rq); @@ -1421,7 +1373,7 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup) */ do { if (hwif->irq == irq) { - stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); + stat = hwif->INB(hwif->io_ports.status_addr); if (!OK_STAT(stat, READY_STAT, BAD_STAT)) { /* Try to not flood the console with msgs */ static unsigned long last_msgtime, count; @@ -1511,7 +1463,7 @@ irqreturn_t ide_intr (int irq, void *dev_id) * Whack the status register, just in case * we have a leftover pending IRQ. */ - (void) hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); + (void) hwif->INB(hwif->io_ports.status_addr); #endif /* CONFIG_BLK_DEV_IDEPCI */ } spin_unlock_irqrestore(&ide_lock, flags); @@ -1598,8 +1550,7 @@ irqreturn_t ide_intr (int irq, void *dev_id) void ide_init_drive_cmd (struct request *rq) { - memset(rq, 0, sizeof(*rq)); - rq->ref_count = 1; + blk_rq_init(NULL, rq); } EXPORT_SYMBOL(ide_init_drive_cmd); @@ -1685,7 +1636,23 @@ void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma) task.tf.lbam = bcount & 0xff; task.tf.lbah = (bcount >> 8) & 0xff; - ide_tf_load(drive, &task); + ide_tf_dump(drive->name, &task.tf); + drive->hwif->tf_load(drive, &task); } EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load); + +void ide_pad_transfer(ide_drive_t *drive, int write, int len) +{ + ide_hwif_t *hwif = drive->hwif; + u8 buf[4] = { 0 }; + + while (len > 0) { + if (write) + hwif->output_data(drive, NULL, buf, min(4, len)); + else + hwif->input_data(drive, NULL, buf, min(4, len)); + len -= 4; + } +} +EXPORT_SYMBOL_GPL(ide_pad_transfer); diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 9c646bd63549..57d9a9a79a6f 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); @@ -164,7 +92,7 @@ void SELECT_DRIVE (ide_drive_t *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) @@ -175,6 +103,123 @@ void SELECT_MASK (ide_drive_t *drive, int mask) 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); + } +} + /* * Some localbus EIDE interfaces require a special access sequence * when using 32-bit I/O instructions to transfer data. We call this @@ -182,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) @@ -445,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!! */ @@ -583,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 } }; @@ -647,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)) { @@ -674,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); @@ -696,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; @@ -734,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); @@ -845,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. @@ -855,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); @@ -1029,6 +1083,7 @@ 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; @@ -1036,6 +1091,8 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) hwif = HWIF(drive); hwgroup = HWGROUP(drive); + io_ports = &hwif->io_ports; + /* We must not reset with running handlers */ BUG_ON(hwgroup->handler != NULL); @@ -1045,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; @@ -1062,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; } @@ -1077,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; @@ -1129,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; /* diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 6f04ea3e93a8..47af80df6872 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -487,7 +487,7 @@ static void ide_dump_sector(ide_drive_t *drive) else task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE; - ide_tf_read(drive, &task); + drive->hwif->tf_read(drive, &task); if (lba48 || (tf->device & ATA_LBA)) printk(", LBAsect=%llu", diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c index 10c20e9a5785..6a8953f68e9f 100644 --- a/drivers/ide/ide-pnp.c +++ b/drivers/ide/ide-pnp.c @@ -82,10 +82,7 @@ static void idepnp_remove(struct pnp_dev *dev) { ide_hwif_t *hwif = pnp_get_drvdata(dev); - if (hwif) - ide_unregister(hwif->index); - else - printk(KERN_ERR "idepnp: Unable to remove device, please report.\n"); + ide_unregister(hwif); release_region(pnp_port_start(dev, 1), 1); release_region(pnp_port_start(dev, 0), 8); diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index a4b65b321f51..099a0fe1745b 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -124,7 +124,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) id = drive->id; /* read 512 bytes of id info */ - hwif->ata_input_data(drive, id, SECTOR_WORDS); + hwif->input_data(drive, NULL, id, SECTOR_SIZE); drive->id_read = 1; local_irq_enable(); @@ -264,6 +264,7 @@ err_misc: static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) { ide_hwif_t *hwif = HWIF(drive); + struct ide_io_ports *io_ports = &hwif->io_ports; int use_altstatus = 0, rc; unsigned long timeout; u8 s = 0, a = 0; @@ -271,7 +272,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) /* take a deep breath */ msleep(50); - if (hwif->io_ports[IDE_CONTROL_OFFSET]) { + if (io_ports->ctl_addr) { a = ide_read_altstatus(drive); s = ide_read_status(drive); if ((a ^ s) & ~INDEX_STAT) @@ -289,10 +290,10 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) */ if ((cmd == WIN_PIDENTIFY)) /* disable dma & overlap */ - hwif->OUTB(0, hwif->io_ports[IDE_FEATURE_OFFSET]); + hwif->OUTB(0, io_ports->feature_addr); /* ask drive for ID */ - hwif->OUTB(cmd, hwif->io_ports[IDE_COMMAND_OFFSET]); + hwif->OUTBSYNC(drive, cmd, io_ports->command_addr); timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2; timeout += jiffies; @@ -353,7 +354,7 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd) * interrupts during the identify-phase that * the irq handler isn't expecting. */ - if (hwif->io_ports[IDE_CONTROL_OFFSET]) { + if (hwif->io_ports.ctl_addr) { if (!hwif->irq) { autoprobe = 1; cookie = probe_irq_on(); @@ -393,7 +394,7 @@ static int ide_busy_sleep(ide_hwif_t *hwif) do { msleep(50); - stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); + stat = hwif->INB(hwif->io_ports.status_addr); if ((stat & BUSY_STAT) == 0) return 0; } while (time_before(jiffies, timeout)); @@ -425,6 +426,7 @@ static int ide_busy_sleep(ide_hwif_t *hwif) static int do_probe (ide_drive_t *drive, u8 cmd) { ide_hwif_t *hwif = HWIF(drive); + struct ide_io_ports *io_ports = &hwif->io_ports; int rc; u8 stat; @@ -445,7 +447,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd) msleep(50); SELECT_DRIVE(drive); msleep(50); - if (hwif->INB(hwif->io_ports[IDE_SELECT_OFFSET]) != drive->select.all && + if (hwif->INB(io_ports->device_addr) != drive->select.all && !drive->present) { if (drive->select.b.unit != 0) { /* exit with drive0 selected */ @@ -472,17 +474,13 @@ static int do_probe (ide_drive_t *drive, u8 cmd) if (stat == (BUSY_STAT | READY_STAT)) return 4; - if ((rc == 1 && cmd == WIN_PIDENTIFY) && - ((drive->autotune == IDE_TUNE_DEFAULT) || - (drive->autotune == IDE_TUNE_AUTO))) { + if (rc == 1 && cmd == WIN_PIDENTIFY) { printk(KERN_ERR "%s: no response (status = 0x%02x), " "resetting drive\n", drive->name, stat); msleep(50); - hwif->OUTB(drive->select.all, - hwif->io_ports[IDE_SELECT_OFFSET]); + hwif->OUTB(drive->select.all, io_ports->device_addr); msleep(50); - hwif->OUTB(WIN_SRST, - hwif->io_ports[IDE_COMMAND_OFFSET]); + hwif->OUTBSYNC(drive, WIN_SRST, io_ports->command_addr); (void)ide_busy_sleep(hwif); rc = try_to_identify(drive, cmd); } @@ -518,7 +516,7 @@ static void enable_nest (ide_drive_t *drive) printk("%s: enabling %s -- ", hwif->name, drive->id->model); SELECT_DRIVE(drive); msleep(50); - hwif->OUTB(EXABYTE_ENABLE_NEST, hwif->io_ports[IDE_COMMAND_OFFSET]); + hwif->OUTBSYNC(drive, EXABYTE_ENABLE_NEST, hwif->io_ports.command_addr); if (ide_busy_sleep(hwif)) { printk(KERN_CONT "failed (timeout)\n"); @@ -800,14 +798,9 @@ static int ide_probe_port(ide_hwif_t *hwif) if (drive->present) rc = 0; } - if (hwif->io_ports[IDE_CONTROL_OFFSET] && hwif->reset) { - printk(KERN_WARNING "%s: reset\n", hwif->name); - hwif->OUTB(12, hwif->io_ports[IDE_CONTROL_OFFSET]); - udelay(10); - hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]); - (void)ide_busy_sleep(hwif); - } + local_irq_restore(flags); + /* * Use cached IRQ number. It might be (and is...) changed by probe * code above @@ -834,12 +827,7 @@ static void ide_port_tune_devices(ide_hwif_t *hwif) ide_drive_t *drive = &hwif->drives[unit]; if (drive->present) { - if (drive->autotune == IDE_TUNE_AUTO) - ide_set_max_pio(drive); - - if (drive->autotune != IDE_TUNE_DEFAULT && - drive->autotune != IDE_TUNE_AUTO) - continue; + ide_set_max_pio(drive); drive->nice1 = 1; @@ -994,6 +982,7 @@ static void ide_port_setup_devices(ide_hwif_t *hwif) */ static int init_irq (ide_hwif_t *hwif) { + struct ide_io_ports *io_ports = &hwif->io_ports; unsigned int index; ide_hwgroup_t *hwgroup; ide_hwif_t *match = NULL; @@ -1077,9 +1066,9 @@ static int init_irq (ide_hwif_t *hwif) if (IDE_CHIPSET_IS_PCI(hwif->chipset)) sa = IRQF_SHARED; - if (hwif->io_ports[IDE_CONTROL_OFFSET]) + if (io_ports->ctl_addr) /* clear nIEN */ - hwif->OUTB(0x08, hwif->io_ports[IDE_CONTROL_OFFSET]); + hwif->OUTB(0x08, io_ports->ctl_addr); if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup)) goto out_unlink; @@ -1095,12 +1084,11 @@ static int init_irq (ide_hwif_t *hwif) #if !defined(__mc68000__) printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name, - hwif->io_ports[IDE_DATA_OFFSET], - hwif->io_ports[IDE_DATA_OFFSET]+7, - hwif->io_ports[IDE_CONTROL_OFFSET], hwif->irq); + io_ports->data_addr, io_ports->status_addr, + io_ports->ctl_addr, hwif->irq); #else printk("%s at 0x%08lx on irq %d", hwif->name, - hwif->io_ports[IDE_DATA_OFFSET], hwif->irq); + io_ports->data_addr, hwif->irq); #endif /* __mc68000__ */ if (match) printk(" (%sed with %s)", @@ -1242,8 +1230,8 @@ static int hwif_init(ide_hwif_t *hwif) int old_irq; if (!hwif->irq) { - if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) - { + hwif->irq = ide_default_irq(hwif->io_ports.data_addr); + if (!hwif->irq) { printk("%s: DISABLED, NO IRQ\n", hwif->name); return 0; } @@ -1272,7 +1260,8 @@ static int hwif_init(ide_hwif_t *hwif) * It failed to initialise. Find the default IRQ for * this port and try that. */ - if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) { + hwif->irq = ide_default_irq(hwif->io_ports.data_addr); + if (!hwif->irq) { printk("%s: Disabled unable to get IRQ %d.\n", hwif->name, old_irq); goto out; @@ -1336,8 +1325,6 @@ static void ide_port_init_devices(ide_hwif_t *hwif) drive->unmask = 1; if (hwif->host_flags & IDE_HFLAG_NO_UNMASK_IRQS) drive->no_unmask = 1; - if ((hwif->host_flags & IDE_HFLAG_NO_AUTOTUNE) == 0) - drive->autotune = 1; } if (port_ops && port_ops->port_init_devs) @@ -1518,13 +1505,20 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) int i, rc = 0; for (i = 0; i < MAX_HWIFS; i++) { - if (d == NULL || idx[i] == 0xff) { + if (idx[i] == 0xff) { mate = NULL; continue; } hwif = &ide_hwifs[idx[i]]; + ide_port_apply_params(hwif); + + if (d == NULL) { + mate = NULL; + continue; + } + if (d->chipset != ide_etrax100 && (i & 1) && mate) { hwif->mate = mate; mate->mate = hwif; @@ -1621,6 +1615,7 @@ EXPORT_SYMBOL_GPL(ide_device_add); void ide_port_scan(ide_hwif_t *hwif) { + ide_port_apply_params(hwif); ide_port_cable_detect(hwif); ide_port_init_devices(hwif); diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index d9d98ac85b29..8d6ad812a014 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -786,14 +786,6 @@ void ide_proc_register_port(ide_hwif_t *hwif) } } -#ifdef CONFIG_BLK_DEV_IDEPCI -void ide_pci_create_host_proc(const char *name, get_info_t *get_info) -{ - create_proc_info_entry(name, 0, proc_ide_root, get_info); -} -EXPORT_SYMBOL_GPL(ide_pci_create_host_proc); -#endif - void ide_proc_unregister_port(ide_hwif_t *hwif) { if (hwif->proc) { @@ -830,6 +822,7 @@ static int ide_drivers_open(struct inode *inode, struct file *file) } static const struct file_operations ide_drivers_operations = { + .owner = THIS_MODULE, .open = ide_drivers_open, .read = seq_read, .llseek = seq_lseek, @@ -838,16 +831,12 @@ static const struct file_operations ide_drivers_operations = { void proc_ide_create(void) { - struct proc_dir_entry *entry; - proc_ide_root = proc_mkdir("ide", NULL); if (!proc_ide_root) return; - entry = create_proc_entry("drivers", 0, proc_ide_root); - if (entry) - entry->proc_fops = &ide_drivers_operations; + proc_create("drivers", 0, proc_ide_root, &ide_drivers_operations); } void proc_ide_destroy(void) diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index d3d8b8d5157c..1e1f26331a24 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -72,26 +72,6 @@ enum { #endif /**************************** Tunable parameters *****************************/ - - -/* - * Pipelined mode parameters. - * - * We try to use the minimum number of stages which is enough to keep the tape - * constantly streaming. To accomplish that, we implement a feedback loop around - * the maximum number of stages: - * - * We start from MIN maximum stages (we will not even use MIN stages if we don't - * need them), increment it by RATE*(MAX-MIN) whenever we sense that the - * pipeline is empty, until we reach the optimum value or until we reach MAX. - * - * Setting the following parameter to 0 is illegal: the pipelined mode cannot be - * disabled (idetape_calculate_speeds() divides by tape->max_stages.) - */ -#define IDETAPE_MIN_PIPELINE_STAGES 1 -#define IDETAPE_MAX_PIPELINE_STAGES 400 -#define IDETAPE_INCREASE_STAGES_RATE 20 - /* * After each failed packet command we issue a request sense command and retry * the packet command IDETAPE_MAX_PC_RETRIES times. @@ -224,28 +204,17 @@ enum { /* 0 When the tape position is unknown */ IDETAPE_FLAG_ADDRESS_VALID = (1 << 1), /* Device already opened */ - IDETAPE_FLAG_BUSY = (1 << 2), - /* Error detected in a pipeline stage */ - IDETAPE_FLAG_PIPELINE_ERR = (1 << 3), + IDETAPE_FLAG_BUSY = (1 << 2), /* Attempt to auto-detect the current user block size */ - IDETAPE_FLAG_DETECT_BS = (1 << 4), + IDETAPE_FLAG_DETECT_BS = (1 << 3), /* Currently on a filemark */ - IDETAPE_FLAG_FILEMARK = (1 << 5), + IDETAPE_FLAG_FILEMARK = (1 << 4), /* DRQ interrupt device */ - IDETAPE_FLAG_DRQ_INTERRUPT = (1 << 6), - /* pipeline active */ - IDETAPE_FLAG_PIPELINE_ACTIVE = (1 << 7), + IDETAPE_FLAG_DRQ_INTERRUPT = (1 << 5), /* 0 = no tape is loaded, so we don't rewind after ejecting */ - IDETAPE_FLAG_MEDIUM_PRESENT = (1 << 8), + IDETAPE_FLAG_MEDIUM_PRESENT = (1 << 6), }; -/* A pipeline stage. */ -typedef struct idetape_stage_s { - struct request rq; /* The corresponding request */ - struct idetape_bh *bh; /* The data buffers */ - struct idetape_stage_s *next; /* Pointer to the next stage */ -} idetape_stage_t; - /* * Most of our global data which we need to save even as we leave the driver due * to an interrupt or a timer event is stored in the struct defined below. @@ -289,9 +258,7 @@ typedef struct ide_tape_obj { * While polling for DSC we use postponed_rq to postpone the current * request so that ide.c will be able to service pending requests on the * other device. Note that at most we will have only one DSC (usually - * data transfer) request in the device request queue. Additional - * requests can be queued in our internal pipeline, but they will be - * visible to ide.c only one at a time. + * data transfer) request in the device request queue. */ struct request *postponed_rq; /* The time in which we started polling for DSC */ @@ -331,43 +298,20 @@ typedef struct ide_tape_obj { * At most, there is only one ide-tape originated data transfer request * in the device request queue. This allows ide.c to easily service * requests from the other device when we postpone our active request. - * In the pipelined operation mode, we use our internal pipeline - * structure to hold more data requests. The data buffer size is chosen - * based on the tape's recommendation. */ - /* ptr to the request which is waiting in the device request queue */ - struct request *active_data_rq; + /* Data buffer size chosen based on the tape's recommendation */ - int stage_size; - idetape_stage_t *merge_stage; - int merge_stage_size; + int buffer_size; + /* merge buffer */ + struct idetape_bh *merge_bh; + /* size of the merge buffer */ + int merge_bh_size; + /* pointer to current buffer head within the merge buffer */ struct idetape_bh *bh; char *b_data; int b_count; - /* - * Pipeline parameters. - * - * To accomplish non-pipelined mode, we simply set the following - * variables to zero (or NULL, where appropriate). - */ - /* Number of currently used stages */ - int nr_stages; - /* Number of pending stages */ - int nr_pending_stages; - /* We will not allocate more than this number of stages */ - int max_stages, min_pipeline, max_pipeline; - /* The first stage which will be removed from the pipeline */ - idetape_stage_t *first_stage; - /* The currently active stage */ - idetape_stage_t *active_stage; - /* Will be serviced after the currently active request */ - idetape_stage_t *next_stage; - /* New requests will be added to the pipeline here */ - idetape_stage_t *last_stage; - /* Optional free stage which we can use */ - idetape_stage_t *cache_stage; - int pages_per_stage; + int pages_per_buffer; /* Wasted space in each stage */ int excess_bh_size; @@ -388,45 +332,6 @@ typedef struct ide_tape_obj { /* the tape is write protected (hardware or opened as read-only) */ char write_prot; - /* - * Limit the number of times a request can be postponed, to avoid an - * infinite postpone deadlock. - */ - int postpone_cnt; - - /* - * Measures number of frames: - * - * 1. written/read to/from the driver pipeline (pipeline_head). - * 2. written/read to/from the tape buffers (idetape_bh). - * 3. written/read by the tape to/from the media (tape_head). - */ - int pipeline_head; - int buffer_head; - int tape_head; - int last_tape_head; - - /* Speed control at the tape buffers input/output */ - unsigned long insert_time; - int insert_size; - int insert_speed; - int max_insert_speed; - int measure_insert_time; - - /* Speed regulation negative feedback loop */ - int speed_control; - int pipeline_head_speed; - int controlled_pipeline_head_speed; - int uncontrolled_pipeline_head_speed; - int controlled_last_pipeline_head; - unsigned long uncontrolled_pipeline_head_time; - unsigned long controlled_pipeline_head_time; - int controlled_previous_pipeline_head; - int uncontrolled_previous_pipeline_head; - unsigned long controlled_previous_head_time; - unsigned long uncontrolled_previous_head_time; - int restart_speed_control_req; - u32 debug_mask; } idetape_tape_t; @@ -490,13 +395,13 @@ static void idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, if (bh == NULL) { printk(KERN_ERR "ide-tape: bh == NULL in " "idetape_input_buffers\n"); - ide_atapi_discard_data(drive, bcount); + ide_pad_transfer(drive, 0, bcount); return; } count = min( (unsigned int)(bh->b_size - atomic_read(&bh->b_count)), bcount); - HWIF(drive)->atapi_input_bytes(drive, bh->b_data + + drive->hwif->input_data(drive, NULL, bh->b_data + atomic_read(&bh->b_count), count); bcount -= count; atomic_add(count, &bh->b_count); @@ -522,7 +427,7 @@ static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, return; } count = min((unsigned int)pc->b_count, (unsigned int)bcount); - HWIF(drive)->atapi_output_bytes(drive, pc->b_data, count); + drive->hwif->output_data(drive, NULL, pc->b_data, count); bcount -= count; pc->b_data += count; pc->b_count -= count; @@ -674,128 +579,36 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense) } } -static void idetape_activate_next_stage(ide_drive_t *drive) +/* Free data buffers completely. */ +static void ide_tape_kfree_buffer(idetape_tape_t *tape) { - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage = tape->next_stage; - struct request *rq = &stage->rq; + struct idetape_bh *prev_bh, *bh = tape->merge_bh; - debug_log(DBG_PROCS, "Enter %s\n", __func__); + while (bh) { + u32 size = bh->b_size; - if (stage == NULL) { - printk(KERN_ERR "ide-tape: bug: Trying to activate a non" - " existing stage\n"); - return; - } + while (size) { + unsigned int order = fls(size >> PAGE_SHIFT)-1; - rq->rq_disk = tape->disk; - rq->buffer = NULL; - rq->special = (void *)stage->bh; - tape->active_data_rq = rq; - tape->active_stage = stage; - tape->next_stage = stage->next; -} - -/* Free a stage along with its related buffers completely. */ -static void __idetape_kfree_stage(idetape_stage_t *stage) -{ - struct idetape_bh *prev_bh, *bh = stage->bh; - int size; - - while (bh != NULL) { - if (bh->b_data != NULL) { - size = (int) bh->b_size; - while (size > 0) { - free_page((unsigned long) bh->b_data); - size -= PAGE_SIZE; - bh->b_data += PAGE_SIZE; - } + if (bh->b_data) + free_pages((unsigned long)bh->b_data, order); + + size &= (order-1); + bh->b_data += (1 << order) * PAGE_SIZE; } prev_bh = bh; bh = bh->b_reqnext; kfree(prev_bh); } - kfree(stage); -} - -static void idetape_kfree_stage(idetape_tape_t *tape, idetape_stage_t *stage) -{ - __idetape_kfree_stage(stage); -} - -/* - * Remove tape->first_stage from the pipeline. The caller should avoid race - * conditions. - */ -static void idetape_remove_stage_head(ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage; - - debug_log(DBG_PROCS, "Enter %s\n", __func__); - - if (tape->first_stage == NULL) { - printk(KERN_ERR "ide-tape: bug: tape->first_stage is NULL\n"); - return; - } - if (tape->active_stage == tape->first_stage) { - printk(KERN_ERR "ide-tape: bug: Trying to free our active " - "pipeline stage\n"); - return; - } - stage = tape->first_stage; - tape->first_stage = stage->next; - idetape_kfree_stage(tape, stage); - tape->nr_stages--; - if (tape->first_stage == NULL) { - tape->last_stage = NULL; - if (tape->next_stage != NULL) - printk(KERN_ERR "ide-tape: bug: tape->next_stage !=" - " NULL\n"); - if (tape->nr_stages) - printk(KERN_ERR "ide-tape: bug: nr_stages should be 0 " - "now\n"); - } + kfree(tape->merge_bh); } -/* - * This will free all the pipeline stages starting from new_last_stage->next - * to the end of the list, and point tape->last_stage to new_last_stage. - */ -static void idetape_abort_pipeline(ide_drive_t *drive, - idetape_stage_t *new_last_stage) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage = new_last_stage->next; - idetape_stage_t *nstage; - - debug_log(DBG_PROCS, "%s: Enter %s\n", tape->name, __func__); - - while (stage) { - nstage = stage->next; - idetape_kfree_stage(tape, stage); - --tape->nr_stages; - --tape->nr_pending_stages; - stage = nstage; - } - if (new_last_stage) - new_last_stage->next = NULL; - tape->last_stage = new_last_stage; - tape->next_stage = NULL; -} - -/* - * Finish servicing a request and insert a pending pipeline request into the - * main device queue. - */ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects) { struct request *rq = HWGROUP(drive)->rq; idetape_tape_t *tape = drive->driver_data; unsigned long flags; int error; - int remove_stage = 0; - idetape_stage_t *active_stage; debug_log(DBG_PROCS, "Enter %s\n", __func__); @@ -815,58 +628,8 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects) spin_lock_irqsave(&tape->lock, flags); - /* The request was a pipelined data transfer request */ - if (tape->active_data_rq == rq) { - active_stage = tape->active_stage; - tape->active_stage = NULL; - tape->active_data_rq = NULL; - tape->nr_pending_stages--; - if (rq->cmd[0] & REQ_IDETAPE_WRITE) { - remove_stage = 1; - if (error) { - set_bit(IDETAPE_FLAG_PIPELINE_ERR, - &tape->flags); - if (error == IDETAPE_ERROR_EOD) - idetape_abort_pipeline(drive, - active_stage); - } - } else if (rq->cmd[0] & REQ_IDETAPE_READ) { - if (error == IDETAPE_ERROR_EOD) { - set_bit(IDETAPE_FLAG_PIPELINE_ERR, - &tape->flags); - idetape_abort_pipeline(drive, active_stage); - } - } - if (tape->next_stage != NULL) { - idetape_activate_next_stage(drive); - - /* Insert the next request into the request queue. */ - (void)ide_do_drive_cmd(drive, tape->active_data_rq, - ide_end); - } else if (!error) { - /* - * This is a part of the feedback loop which tries to - * find the optimum number of stages. We are starting - * from a minimum maximum number of stages, and if we - * sense that the pipeline is empty, we try to increase - * it, until we reach the user compile time memory - * limit. - */ - int i = (tape->max_pipeline - tape->min_pipeline) / 10; - - tape->max_stages += max(i, 1); - tape->max_stages = max(tape->max_stages, - tape->min_pipeline); - tape->max_stages = min(tape->max_stages, - tape->max_pipeline); - } - } ide_end_drive_cmd(drive, 0, 0); - if (remove_stage) - idetape_remove_stage_head(drive); - if (tape->active_data_rq == NULL) - clear_bit(IDETAPE_FLAG_PIPELINE_ACTIVE, &tape->flags); spin_unlock_irqrestore(&tape->lock, flags); return 0; } @@ -899,7 +662,7 @@ static void idetape_create_request_sense_cmd(struct ide_atapi_pc *pc) static void idetape_init_rq(struct request *rq, u8 cmd) { - memset(rq, 0, sizeof(*rq)); + blk_rq_init(NULL, rq); rq->cmd_type = REQ_TYPE_SPECIAL; rq->cmd[0] = cmd; } @@ -1083,10 +846,10 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive) return ide_do_reset(drive); } /* Get the number of bytes to transfer on this interrupt. */ - bcount = (hwif->INB(hwif->io_ports[IDE_BCOUNTH_OFFSET]) << 8) | - hwif->INB(hwif->io_ports[IDE_BCOUNTL_OFFSET]); + bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) | + hwif->INB(hwif->io_ports.lbam_addr); - ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]); + ireason = hwif->INB(hwif->io_ports.nsect_addr); if (ireason & CD) { printk(KERN_ERR "ide-tape: CoD != 0 in %s\n", __func__); @@ -1108,7 +871,7 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive) printk(KERN_ERR "ide-tape: The tape wants to " "send us more data than expected " "- discarding data\n"); - ide_atapi_discard_data(drive, bcount); + ide_pad_transfer(drive, 0, bcount); ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); return ide_started; @@ -1117,16 +880,16 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive) "data than expected - allowing transfer\n"); } iobuf = &idetape_input_buffers; - xferfunc = hwif->atapi_input_bytes; + xferfunc = hwif->input_data; } else { iobuf = &idetape_output_buffers; - xferfunc = hwif->atapi_output_bytes; + xferfunc = hwif->output_data; } if (pc->bh) iobuf(drive, pc, bcount); else - xferfunc(drive, pc->cur_pos, bcount); + xferfunc(drive, NULL, pc->cur_pos, bcount); /* Update the current position */ pc->xferred += bcount; @@ -1190,12 +953,12 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive) "yet DRQ isn't asserted\n"); return startstop; } - ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]); + ireason = hwif->INB(hwif->io_ports.nsect_addr); while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) { printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing " "a packet command, retrying\n"); udelay(100); - ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]); + ireason = hwif->INB(hwif->io_ports.nsect_addr); if (retries == 0) { printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while " "issuing a packet command, ignoring\n"); @@ -1216,7 +979,8 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive) hwif->dma_ops->dma_start(drive); #endif /* Send the actual packet */ - HWIF(drive)->atapi_output_bytes(drive, pc->c, 12); + hwif->output_data(drive, NULL, pc->c, 12); + return ide_started; } @@ -1292,7 +1056,7 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, IDETAPE_WAIT_CMD, NULL); return ide_started; } else { - hwif->OUTB(WIN_PACKETCMD, hwif->io_ports[IDE_COMMAND_OFFSET]); + ide_execute_pkt_cmd(drive); return idetape_transfer_pc(drive); } } @@ -1335,69 +1099,6 @@ static void idetape_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code) pc->idetape_callback = &idetape_pc_callback; } -static void idetape_calculate_speeds(ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - - if (time_after(jiffies, - tape->controlled_pipeline_head_time + 120 * HZ)) { - tape->controlled_previous_pipeline_head = - tape->controlled_last_pipeline_head; - tape->controlled_previous_head_time = - tape->controlled_pipeline_head_time; - tape->controlled_last_pipeline_head = tape->pipeline_head; - tape->controlled_pipeline_head_time = jiffies; - } - if (time_after(jiffies, tape->controlled_pipeline_head_time + 60 * HZ)) - tape->controlled_pipeline_head_speed = (tape->pipeline_head - - tape->controlled_last_pipeline_head) * 32 * HZ / - (jiffies - tape->controlled_pipeline_head_time); - else if (time_after(jiffies, tape->controlled_previous_head_time)) - tape->controlled_pipeline_head_speed = (tape->pipeline_head - - tape->controlled_previous_pipeline_head) * 32 * - HZ / (jiffies - tape->controlled_previous_head_time); - - if (tape->nr_pending_stages < tape->max_stages/*- 1 */) { - /* -1 for read mode error recovery */ - if (time_after(jiffies, tape->uncontrolled_previous_head_time + - 10 * HZ)) { - tape->uncontrolled_pipeline_head_time = jiffies; - tape->uncontrolled_pipeline_head_speed = - (tape->pipeline_head - - tape->uncontrolled_previous_pipeline_head) * - 32 * HZ / (jiffies - - tape->uncontrolled_previous_head_time); - } - } else { - tape->uncontrolled_previous_head_time = jiffies; - tape->uncontrolled_previous_pipeline_head = tape->pipeline_head; - if (time_after(jiffies, tape->uncontrolled_pipeline_head_time + - 30 * HZ)) - tape->uncontrolled_pipeline_head_time = jiffies; - - } - tape->pipeline_head_speed = max(tape->uncontrolled_pipeline_head_speed, - tape->controlled_pipeline_head_speed); - - if (tape->speed_control == 1) { - if (tape->nr_pending_stages >= tape->max_stages / 2) - tape->max_insert_speed = tape->pipeline_head_speed + - (1100 - tape->pipeline_head_speed) * 2 * - (tape->nr_pending_stages - tape->max_stages / 2) - / tape->max_stages; - else - tape->max_insert_speed = 500 + - (tape->pipeline_head_speed - 500) * 2 * - tape->nr_pending_stages / tape->max_stages; - - if (tape->nr_pending_stages >= tape->max_stages * 99 / 100) - tape->max_insert_speed = 5000; - } else - tape->max_insert_speed = tape->speed_control; - - tape->max_insert_speed = max(tape->max_insert_speed, 500); -} - static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; @@ -1432,17 +1133,7 @@ static ide_startstop_t idetape_rw_callback(ide_drive_t *drive) int blocks = tape->pc->xferred / tape->blk_size; tape->avg_size += blocks * tape->blk_size; - tape->insert_size += blocks * tape->blk_size; - if (tape->insert_size > 1024 * 1024) - tape->measure_insert_time = 1; - if (tape->measure_insert_time) { - tape->measure_insert_time = 0; - tape->insert_time = jiffies; - tape->insert_size = 0; - } - if (time_after(jiffies, tape->insert_time)) - tape->insert_speed = tape->insert_size / 1024 * HZ / - (jiffies - tape->insert_time); + if (time_after_eq(jiffies, tape->avg_time + HZ)) { tape->avg_speed = tape->avg_size * HZ / (jiffies - tape->avg_time) / 1024; @@ -1475,7 +1166,7 @@ static void idetape_create_read_cmd(idetape_tape_t *tape, pc->buf = NULL; pc->buf_size = length * tape->blk_size; pc->req_xfer = pc->buf_size; - if (pc->req_xfer == tape->stage_size) + if (pc->req_xfer == tape->buffer_size) pc->flags |= PC_FLAG_DMA_RECOMMENDED; } @@ -1495,7 +1186,7 @@ static void idetape_create_write_cmd(idetape_tape_t *tape, pc->buf = NULL; pc->buf_size = length * tape->blk_size; pc->req_xfer = pc->buf_size; - if (pc->req_xfer == tape->stage_size) + if (pc->req_xfer == tape->buffer_size) pc->flags |= PC_FLAG_DMA_RECOMMENDED; } @@ -1547,10 +1238,6 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, drive->post_reset = 0; } - if (time_after(jiffies, tape->insert_time)) - tape->insert_speed = tape->insert_size / 1024 * HZ / - (jiffies - tape->insert_time); - idetape_calculate_speeds(drive); if (!test_and_clear_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags) && (stat & SEEK_STAT) == 0) { if (postponed_rq == NULL) { @@ -1574,16 +1261,12 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, return ide_stopped; } if (rq->cmd[0] & REQ_IDETAPE_READ) { - tape->buffer_head++; - tape->postpone_cnt = 0; pc = idetape_next_pc_storage(drive); idetape_create_read_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special); goto out; } if (rq->cmd[0] & REQ_IDETAPE_WRITE) { - tape->buffer_head++; - tape->postpone_cnt = 0; pc = idetape_next_pc_storage(drive); idetape_create_write_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special); @@ -1604,103 +1287,91 @@ out: return idetape_issue_pc(drive, pc); } -/* Pipeline related functions */ - /* - * The function below uses __get_free_page to allocate a pipeline stage, along - * with all the necessary small buffers which together make a buffer of size - * tape->stage_size (or a bit more). We attempt to combine sequential pages as + * The function below uses __get_free_pages to allocate a data buffer of size + * tape->buffer_size (or a bit more). We attempt to combine sequential pages as * much as possible. * - * It returns a pointer to the new allocated stage, or NULL if we can't (or - * don't want to) allocate a stage. - * - * Pipeline stages are optional and are used to increase performance. If we - * can't allocate them, we'll manage without them. + * It returns a pointer to the newly allocated buffer, or NULL in case of + * failure. */ -static idetape_stage_t *__idetape_kmalloc_stage(idetape_tape_t *tape, int full, - int clear) +static struct idetape_bh *ide_tape_kmalloc_buffer(idetape_tape_t *tape, + int full, int clear) { - idetape_stage_t *stage; - struct idetape_bh *prev_bh, *bh; - int pages = tape->pages_per_stage; + struct idetape_bh *prev_bh, *bh, *merge_bh; + int pages = tape->pages_per_buffer; + unsigned int order, b_allocd; char *b_data = NULL; - stage = kmalloc(sizeof(idetape_stage_t), GFP_KERNEL); - if (!stage) - return NULL; - stage->next = NULL; - - stage->bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL); - bh = stage->bh; + merge_bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL); + bh = merge_bh; if (bh == NULL) goto abort; - bh->b_reqnext = NULL; - bh->b_data = (char *) __get_free_page(GFP_KERNEL); + + order = fls(pages) - 1; + bh->b_data = (char *) __get_free_pages(GFP_KERNEL, order); if (!bh->b_data) goto abort; + b_allocd = (1 << order) * PAGE_SIZE; + pages &= (order-1); + if (clear) - memset(bh->b_data, 0, PAGE_SIZE); - bh->b_size = PAGE_SIZE; + memset(bh->b_data, 0, b_allocd); + bh->b_reqnext = NULL; + bh->b_size = b_allocd; atomic_set(&bh->b_count, full ? bh->b_size : 0); - while (--pages) { - b_data = (char *) __get_free_page(GFP_KERNEL); + while (pages) { + order = fls(pages) - 1; + b_data = (char *) __get_free_pages(GFP_KERNEL, order); if (!b_data) goto abort; + b_allocd = (1 << order) * PAGE_SIZE; + if (clear) - memset(b_data, 0, PAGE_SIZE); - if (bh->b_data == b_data + PAGE_SIZE) { - bh->b_size += PAGE_SIZE; - bh->b_data -= PAGE_SIZE; + memset(b_data, 0, b_allocd); + + /* newly allocated page frames below buffer header or ...*/ + if (bh->b_data == b_data + b_allocd) { + bh->b_size += b_allocd; + bh->b_data -= b_allocd; if (full) - atomic_add(PAGE_SIZE, &bh->b_count); + atomic_add(b_allocd, &bh->b_count); continue; } + /* they are above the header */ if (b_data == bh->b_data + bh->b_size) { - bh->b_size += PAGE_SIZE; + bh->b_size += b_allocd; if (full) - atomic_add(PAGE_SIZE, &bh->b_count); + atomic_add(b_allocd, &bh->b_count); continue; } prev_bh = bh; bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL); if (!bh) { - free_page((unsigned long) b_data); + free_pages((unsigned long) b_data, order); goto abort; } bh->b_reqnext = NULL; bh->b_data = b_data; - bh->b_size = PAGE_SIZE; + bh->b_size = b_allocd; atomic_set(&bh->b_count, full ? bh->b_size : 0); prev_bh->b_reqnext = bh; + + pages &= (order-1); } + bh->b_size -= tape->excess_bh_size; if (full) atomic_sub(tape->excess_bh_size, &bh->b_count); - return stage; + return merge_bh; abort: - __idetape_kfree_stage(stage); + ide_tape_kfree_buffer(tape); return NULL; } -static idetape_stage_t *idetape_kmalloc_stage(idetape_tape_t *tape) -{ - idetape_stage_t *cache_stage = tape->cache_stage; - - debug_log(DBG_PROCS, "Enter %s\n", __func__); - - if (tape->nr_stages >= tape->max_stages) - return NULL; - if (cache_stage != NULL) { - tape->cache_stage = NULL; - return cache_stage; - } - return __idetape_kmalloc_stage(tape, 0, 0); -} - static int idetape_copy_stage_from_user(idetape_tape_t *tape, - idetape_stage_t *stage, const char __user *buf, int n) + const char __user *buf, int n) { struct idetape_bh *bh = tape->bh; int count; @@ -1732,7 +1403,7 @@ static int idetape_copy_stage_from_user(idetape_tape_t *tape, } static int idetape_copy_stage_to_user(idetape_tape_t *tape, char __user *buf, - idetape_stage_t *stage, int n) + int n) { struct idetape_bh *bh = tape->bh; int count; @@ -1763,11 +1434,11 @@ static int idetape_copy_stage_to_user(idetape_tape_t *tape, char __user *buf, return ret; } -static void idetape_init_merge_stage(idetape_tape_t *tape) +static void idetape_init_merge_buffer(idetape_tape_t *tape) { - struct idetape_bh *bh = tape->merge_stage->bh; + struct idetape_bh *bh = tape->merge_bh; + tape->bh = tape->merge_bh; - tape->bh = bh; if (tape->chrdev_dir == IDETAPE_DIR_WRITE) atomic_set(&bh->b_count, 0); else { @@ -1776,61 +1447,6 @@ static void idetape_init_merge_stage(idetape_tape_t *tape) } } -static void idetape_switch_buffers(idetape_tape_t *tape, idetape_stage_t *stage) -{ - struct idetape_bh *tmp; - - tmp = stage->bh; - stage->bh = tape->merge_stage->bh; - tape->merge_stage->bh = tmp; - idetape_init_merge_stage(tape); -} - -/* Add a new stage at the end of the pipeline. */ -static void idetape_add_stage_tail(ide_drive_t *drive, idetape_stage_t *stage) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned long flags; - - debug_log(DBG_PROCS, "Enter %s\n", __func__); - - spin_lock_irqsave(&tape->lock, flags); - stage->next = NULL; - if (tape->last_stage != NULL) - tape->last_stage->next = stage; - else - tape->first_stage = stage; - tape->next_stage = stage; - tape->last_stage = stage; - if (tape->next_stage == NULL) - tape->next_stage = tape->last_stage; - tape->nr_stages++; - tape->nr_pending_stages++; - spin_unlock_irqrestore(&tape->lock, flags); -} - -/* Install a completion in a pending request and sleep until it is serviced. The - * caller should ensure that the request will not be serviced before we install - * the completion (usually by disabling interrupts). - */ -static void idetape_wait_for_request(ide_drive_t *drive, struct request *rq) -{ - DECLARE_COMPLETION_ONSTACK(wait); - idetape_tape_t *tape = drive->driver_data; - - if (rq == NULL || !blk_special_request(rq)) { - printk(KERN_ERR "ide-tape: bug: Trying to sleep on non-valid" - " request\n"); - return; - } - rq->end_io_data = &wait; - rq->end_io = blk_end_sync_rq; - spin_unlock_irq(&tape->lock); - wait_for_completion(&wait); - /* The stage and its struct request have been deallocated */ - spin_lock_irq(&tape->lock); -} - static ide_startstop_t idetape_read_position_callback(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; @@ -1899,7 +1515,7 @@ static void idetape_create_test_unit_ready_cmd(struct ide_atapi_pc *pc) * to the request list without waiting for it to be serviced! In that case, we * usually use idetape_queue_pc_head(). */ -static int __idetape_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc) +static int idetape_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc) { struct ide_tape_obj *tape = drive->driver_data; struct request rq; @@ -1931,7 +1547,7 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout) timeout += jiffies; while (time_before(jiffies, timeout)) { idetape_create_test_unit_ready_cmd(&pc); - if (!__idetape_queue_pc_tail(drive, &pc)) + if (!idetape_queue_pc_tail(drive, &pc)) return 0; if ((tape->sense_key == 2 && tape->asc == 4 && tape->ascq == 2) || (tape->asc == 0x3A)) { @@ -1940,7 +1556,7 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout) return -ENOMEDIUM; idetape_create_load_unload_cmd(drive, &pc, IDETAPE_LU_LOAD_MASK); - __idetape_queue_pc_tail(drive, &pc); + idetape_queue_pc_tail(drive, &pc); load_attempted = 1; /* not about to be ready */ } else if (!(tape->sense_key == 2 && tape->asc == 4 && @@ -1951,11 +1567,6 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout) return -EIO; } -static int idetape_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc) -{ - return __idetape_queue_pc_tail(drive, pc); -} - static int idetape_flush_tape_buffers(ide_drive_t *drive) { struct ide_atapi_pc pc; @@ -2021,50 +1632,21 @@ static int idetape_create_prevent_cmd(ide_drive_t *drive, return 1; } -static int __idetape_discard_read_pipeline(ide_drive_t *drive) +static void __ide_tape_discard_merge_buffer(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; - unsigned long flags; - int cnt; if (tape->chrdev_dir != IDETAPE_DIR_READ) - return 0; + return; - /* Remove merge stage. */ - cnt = tape->merge_stage_size / tape->blk_size; - if (test_and_clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags)) - ++cnt; /* Filemarks count as 1 sector */ - tape->merge_stage_size = 0; - if (tape->merge_stage != NULL) { - __idetape_kfree_stage(tape->merge_stage); - tape->merge_stage = NULL; + clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags); + tape->merge_bh_size = 0; + if (tape->merge_bh != NULL) { + ide_tape_kfree_buffer(tape); + tape->merge_bh = NULL; } - /* Clear pipeline flags. */ - clear_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags); tape->chrdev_dir = IDETAPE_DIR_NONE; - - /* Remove pipeline stages. */ - if (tape->first_stage == NULL) - return 0; - - spin_lock_irqsave(&tape->lock, flags); - tape->next_stage = NULL; - if (test_bit(IDETAPE_FLAG_PIPELINE_ACTIVE, &tape->flags)) - idetape_wait_for_request(drive, tape->active_data_rq); - spin_unlock_irqrestore(&tape->lock, flags); - - while (tape->first_stage != NULL) { - struct request *rq_ptr = &tape->first_stage->rq; - - cnt += rq_ptr->nr_sectors - rq_ptr->current_nr_sectors; - if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK) - ++cnt; - idetape_remove_stage_head(drive); - } - tape->nr_pending_stages = 0; - tape->max_stages = tape->min_pipeline; - return cnt; } /* @@ -2081,7 +1663,7 @@ static int idetape_position_tape(ide_drive_t *drive, unsigned int block, struct ide_atapi_pc pc; if (tape->chrdev_dir == IDETAPE_DIR_READ) - __idetape_discard_read_pipeline(drive); + __ide_tape_discard_merge_buffer(drive); idetape_wait_ready(drive, 60 * 5 * HZ); idetape_create_locate_cmd(drive, &pc, block, partition, skip); retval = idetape_queue_pc_tail(drive, &pc); @@ -2092,20 +1674,19 @@ static int idetape_position_tape(ide_drive_t *drive, unsigned int block, return (idetape_queue_pc_tail(drive, &pc)); } -static void idetape_discard_read_pipeline(ide_drive_t *drive, +static void ide_tape_discard_merge_buffer(ide_drive_t *drive, int restore_position) { idetape_tape_t *tape = drive->driver_data; - int cnt; int seek, position; - cnt = __idetape_discard_read_pipeline(drive); + __ide_tape_discard_merge_buffer(drive); if (restore_position) { position = idetape_read_position(drive); - seek = position > cnt ? position - cnt : 0; + seek = position > 0 ? position : 0; if (idetape_position_tape(drive, seek, 0, 0)) { printk(KERN_INFO "ide-tape: %s: position_tape failed in" - " discard_pipeline()\n", tape->name); + " %s\n", tape->name, __func__); return; } } @@ -2123,12 +1704,6 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks, debug_log(DBG_SENSE, "%s: cmd=%d\n", __func__, cmd); - if (test_bit(IDETAPE_FLAG_PIPELINE_ACTIVE, &tape->flags)) { - printk(KERN_ERR "ide-tape: bug: the pipeline is active in %s\n", - __func__); - return (0); - } - idetape_init_rq(&rq, cmd); rq.rq_disk = tape->disk; rq.special = (void *)bh; @@ -2140,26 +1715,13 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks, if ((cmd & (REQ_IDETAPE_READ | REQ_IDETAPE_WRITE)) == 0) return 0; - if (tape->merge_stage) - idetape_init_merge_stage(tape); + if (tape->merge_bh) + idetape_init_merge_buffer(tape); if (rq.errors == IDETAPE_ERROR_GENERAL) return -EIO; return (tape->blk_size * (blocks-rq.current_nr_sectors)); } -/* start servicing the pipeline stages, starting from tape->next_stage. */ -static void idetape_plug_pipeline(ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - - if (tape->next_stage == NULL) - return; - if (!test_and_set_bit(IDETAPE_FLAG_PIPELINE_ACTIVE, &tape->flags)) { - idetape_activate_next_stage(drive); - (void) ide_do_drive_cmd(drive, tape->active_data_rq, ide_end); - } -} - static void idetape_create_inquiry_cmd(struct ide_atapi_pc *pc) { idetape_init_pc(pc); @@ -2197,137 +1759,39 @@ static void idetape_create_space_cmd(struct ide_atapi_pc *pc, int count, u8 cmd) pc->idetape_callback = &idetape_pc_callback; } -static void idetape_wait_first_stage(ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned long flags; - - if (tape->first_stage == NULL) - return; - spin_lock_irqsave(&tape->lock, flags); - if (tape->active_stage == tape->first_stage) - idetape_wait_for_request(drive, tape->active_data_rq); - spin_unlock_irqrestore(&tape->lock, flags); -} - -/* - * Try to add a character device originated write request to our pipeline. In - * case we don't succeed, we revert to non-pipelined operation mode for this - * request. In order to accomplish that, we - * - * 1. Try to allocate a new pipeline stage. - * 2. If we can't, wait for more and more requests to be serviced and try again - * each time. - * 3. If we still can't allocate a stage, fallback to non-pipelined operation - * mode for this request. - */ +/* Queue up a character device originated write request. */ static int idetape_add_chrdev_write_request(ide_drive_t *drive, int blocks) { idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *new_stage; - unsigned long flags; - struct request *rq; debug_log(DBG_CHRDEV, "Enter %s\n", __func__); - /* Attempt to allocate a new stage. Beware possible race conditions. */ - while ((new_stage = idetape_kmalloc_stage(tape)) == NULL) { - spin_lock_irqsave(&tape->lock, flags); - if (test_bit(IDETAPE_FLAG_PIPELINE_ACTIVE, &tape->flags)) { - idetape_wait_for_request(drive, tape->active_data_rq); - spin_unlock_irqrestore(&tape->lock, flags); - } else { - spin_unlock_irqrestore(&tape->lock, flags); - idetape_plug_pipeline(drive); - if (test_bit(IDETAPE_FLAG_PIPELINE_ACTIVE, - &tape->flags)) - continue; - /* - * The machine is short on memory. Fallback to non- - * pipelined operation mode for this request. - */ - return idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, - blocks, tape->merge_stage->bh); - } - } - rq = &new_stage->rq; - idetape_init_rq(rq, REQ_IDETAPE_WRITE); - /* Doesn't actually matter - We always assume sequential access */ - rq->sector = tape->first_frame; - rq->current_nr_sectors = blocks; - rq->nr_sectors = blocks; - - idetape_switch_buffers(tape, new_stage); - idetape_add_stage_tail(drive, new_stage); - tape->pipeline_head++; - idetape_calculate_speeds(drive); - - /* - * Estimate whether the tape has stopped writing by checking if our - * write pipeline is currently empty. If we are not writing anymore, - * wait for the pipeline to be almost completely full (90%) before - * starting to service requests, so that we will be able to keep up with - * the higher speeds of the tape. - */ - if (!test_bit(IDETAPE_FLAG_PIPELINE_ACTIVE, &tape->flags)) { - if (tape->nr_stages >= tape->max_stages * 9 / 10 || - tape->nr_stages >= tape->max_stages - - tape->uncontrolled_pipeline_head_speed * 3 * 1024 / - tape->blk_size) { - tape->measure_insert_time = 1; - tape->insert_time = jiffies; - tape->insert_size = 0; - tape->insert_speed = 0; - idetape_plug_pipeline(drive); - } - } - if (test_and_clear_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags)) - /* Return a deferred error */ - return -EIO; - return blocks; + return idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, + blocks, tape->merge_bh); } -/* - * Wait until all pending pipeline requests are serviced. Typically called on - * device close. - */ -static void idetape_wait_for_pipeline(ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned long flags; - - while (tape->next_stage || test_bit(IDETAPE_FLAG_PIPELINE_ACTIVE, - &tape->flags)) { - idetape_plug_pipeline(drive); - spin_lock_irqsave(&tape->lock, flags); - if (test_bit(IDETAPE_FLAG_PIPELINE_ACTIVE, &tape->flags)) - idetape_wait_for_request(drive, tape->active_data_rq); - spin_unlock_irqrestore(&tape->lock, flags); - } -} - -static void idetape_empty_write_pipeline(ide_drive_t *drive) +static void ide_tape_flush_merge_buffer(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; int blocks, min; struct idetape_bh *bh; if (tape->chrdev_dir != IDETAPE_DIR_WRITE) { - printk(KERN_ERR "ide-tape: bug: Trying to empty write pipeline," + printk(KERN_ERR "ide-tape: bug: Trying to empty merge buffer" " but we are not writing.\n"); return; } - if (tape->merge_stage_size > tape->stage_size) { + if (tape->merge_bh_size > tape->buffer_size) { printk(KERN_ERR "ide-tape: bug: merge_buffer too big\n"); - tape->merge_stage_size = tape->stage_size; + tape->merge_bh_size = tape->buffer_size; } - if (tape->merge_stage_size) { - blocks = tape->merge_stage_size / tape->blk_size; - if (tape->merge_stage_size % tape->blk_size) { + if (tape->merge_bh_size) { + blocks = tape->merge_bh_size / tape->blk_size; + if (tape->merge_bh_size % tape->blk_size) { unsigned int i; blocks++; - i = tape->blk_size - tape->merge_stage_size % + i = tape->blk_size - tape->merge_bh_size % tape->blk_size; bh = tape->bh->b_reqnext; while (bh) { @@ -2351,74 +1815,33 @@ static void idetape_empty_write_pipeline(ide_drive_t *drive) } } (void) idetape_add_chrdev_write_request(drive, blocks); - tape->merge_stage_size = 0; + tape->merge_bh_size = 0; } - idetape_wait_for_pipeline(drive); - if (tape->merge_stage != NULL) { - __idetape_kfree_stage(tape->merge_stage); - tape->merge_stage = NULL; + if (tape->merge_bh != NULL) { + ide_tape_kfree_buffer(tape); + tape->merge_bh = NULL; } - clear_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags); tape->chrdev_dir = IDETAPE_DIR_NONE; - - /* - * On the next backup, perform the feedback loop again. (I don't want to - * keep sense information between backups, as some systems are - * constantly on, and the system load can be totally different on the - * next backup). - */ - tape->max_stages = tape->min_pipeline; - if (tape->first_stage != NULL || - tape->next_stage != NULL || - tape->last_stage != NULL || - tape->nr_stages != 0) { - printk(KERN_ERR "ide-tape: ide-tape pipeline bug, " - "first_stage %p, next_stage %p, " - "last_stage %p, nr_stages %d\n", - tape->first_stage, tape->next_stage, - tape->last_stage, tape->nr_stages); - } } -static void idetape_restart_speed_control(ide_drive_t *drive) +static int idetape_init_read(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; - - tape->restart_speed_control_req = 0; - tape->pipeline_head = 0; - tape->controlled_last_pipeline_head = 0; - tape->controlled_previous_pipeline_head = 0; - tape->uncontrolled_previous_pipeline_head = 0; - tape->controlled_pipeline_head_speed = 5000; - tape->pipeline_head_speed = 5000; - tape->uncontrolled_pipeline_head_speed = 0; - tape->controlled_pipeline_head_time = - tape->uncontrolled_pipeline_head_time = jiffies; - tape->controlled_previous_head_time = - tape->uncontrolled_previous_head_time = jiffies; -} - -static int idetape_init_read(ide_drive_t *drive, int max_stages) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *new_stage; - struct request rq; int bytes_read; - u16 blocks = *(u16 *)&tape->caps[12]; /* Initialize read operation */ if (tape->chrdev_dir != IDETAPE_DIR_READ) { if (tape->chrdev_dir == IDETAPE_DIR_WRITE) { - idetape_empty_write_pipeline(drive); + ide_tape_flush_merge_buffer(drive); idetape_flush_tape_buffers(drive); } - if (tape->merge_stage || tape->merge_stage_size) { - printk(KERN_ERR "ide-tape: merge_stage_size should be" + if (tape->merge_bh || tape->merge_bh_size) { + printk(KERN_ERR "ide-tape: merge_bh_size should be" " 0 now\n"); - tape->merge_stage_size = 0; + tape->merge_bh_size = 0; } - tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0); - if (!tape->merge_stage) + tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0); + if (!tape->merge_bh) return -ENOMEM; tape->chrdev_dir = IDETAPE_DIR_READ; @@ -2431,54 +1854,23 @@ static int idetape_init_read(ide_drive_t *drive, int max_stages) if (drive->dsc_overlap) { bytes_read = idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, 0, - tape->merge_stage->bh); + tape->merge_bh); if (bytes_read < 0) { - __idetape_kfree_stage(tape->merge_stage); - tape->merge_stage = NULL; + ide_tape_kfree_buffer(tape); + tape->merge_bh = NULL; tape->chrdev_dir = IDETAPE_DIR_NONE; return bytes_read; } } } - if (tape->restart_speed_control_req) - idetape_restart_speed_control(drive); - idetape_init_rq(&rq, REQ_IDETAPE_READ); - rq.sector = tape->first_frame; - rq.nr_sectors = blocks; - rq.current_nr_sectors = blocks; - if (!test_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags) && - tape->nr_stages < max_stages) { - new_stage = idetape_kmalloc_stage(tape); - while (new_stage != NULL) { - new_stage->rq = rq; - idetape_add_stage_tail(drive, new_stage); - if (tape->nr_stages >= max_stages) - break; - new_stage = idetape_kmalloc_stage(tape); - } - } - if (!test_bit(IDETAPE_FLAG_PIPELINE_ACTIVE, &tape->flags)) { - if (tape->nr_pending_stages >= 3 * max_stages / 4) { - tape->measure_insert_time = 1; - tape->insert_time = jiffies; - tape->insert_size = 0; - tape->insert_speed = 0; - idetape_plug_pipeline(drive); - } - } + return 0; } -/* - * Called from idetape_chrdev_read() to service a character device read request - * and add read-ahead requests to our pipeline. - */ +/* called from idetape_chrdev_read() to service a chrdev read request. */ static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks) { idetape_tape_t *tape = drive->driver_data; - unsigned long flags; - struct request *rq_ptr; - int bytes_read; debug_log(DBG_PROCS, "Enter %s, %d blocks\n", __func__, blocks); @@ -2486,39 +1878,10 @@ static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks) if (test_bit(IDETAPE_FLAG_FILEMARK, &tape->flags)) return 0; - /* Wait for the next block to reach the head of the pipeline. */ - idetape_init_read(drive, tape->max_stages); - if (tape->first_stage == NULL) { - if (test_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags)) - return 0; - return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks, - tape->merge_stage->bh); - } - idetape_wait_first_stage(drive); - rq_ptr = &tape->first_stage->rq; - bytes_read = tape->blk_size * (rq_ptr->nr_sectors - - rq_ptr->current_nr_sectors); - rq_ptr->nr_sectors = 0; - rq_ptr->current_nr_sectors = 0; + idetape_init_read(drive); - if (rq_ptr->errors == IDETAPE_ERROR_EOD) - return 0; - else { - idetape_switch_buffers(tape, tape->first_stage); - if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK) - set_bit(IDETAPE_FLAG_FILEMARK, &tape->flags); - spin_lock_irqsave(&tape->lock, flags); - idetape_remove_stage_head(drive); - spin_unlock_irqrestore(&tape->lock, flags); - tape->pipeline_head++; - idetape_calculate_speeds(drive); - } - if (bytes_read > blocks * tape->blk_size) { - printk(KERN_ERR "ide-tape: bug: trying to return more bytes" - " than requested\n"); - bytes_read = blocks * tape->blk_size; - } - return (bytes_read); + return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks, + tape->merge_bh); } static void idetape_pad_zeros(ide_drive_t *drive, int bcount) @@ -2530,8 +1893,8 @@ static void idetape_pad_zeros(ide_drive_t *drive, int bcount) while (bcount) { unsigned int count; - bh = tape->merge_stage->bh; - count = min(tape->stage_size, bcount); + bh = tape->merge_bh; + count = min(tape->buffer_size, bcount); bcount -= count; blocks = count / tape->blk_size; while (count) { @@ -2542,29 +1905,8 @@ static void idetape_pad_zeros(ide_drive_t *drive, int bcount) bh = bh->b_reqnext; } idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, blocks, - tape->merge_stage->bh); - } -} - -static int idetape_pipeline_size(ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage; - struct request *rq; - int size = 0; - - idetape_wait_for_pipeline(drive); - stage = tape->first_stage; - while (stage != NULL) { - rq = &stage->rq; - size += tape->blk_size * (rq->nr_sectors - - rq->current_nr_sectors); - if (rq->errors == IDETAPE_ERROR_FILEMARK) - size += tape->blk_size; - stage = stage->next; + tape->merge_bh); } - size += tape->merge_stage_size; - return size; } /* @@ -2612,11 +1954,10 @@ static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd, if (copy_from_user(&config, argp, sizeof(config))) return -EFAULT; tape->best_dsc_rw_freq = config.dsc_rw_frequency; - tape->max_stages = config.nr_stages; break; case 0x0350: config.dsc_rw_frequency = (int) tape->best_dsc_rw_freq; - config.nr_stages = tape->max_stages; + config.nr_stages = 1; if (copy_to_user(argp, &config, sizeof(config))) return -EFAULT; break; @@ -2626,19 +1967,11 @@ static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd, return 0; } -/* - * The function below is now a bit more complicated than just passing the - * command to the tape since we may have crossed some filemarks during our - * pipelined read-ahead mode. As a minor side effect, the pipeline enables us to - * support MTFSFM when the filemark is in our internal pipeline even if the tape - * doesn't support spacing over filemarks in the reverse direction. - */ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op, int mt_count) { idetape_tape_t *tape = drive->driver_data; struct ide_atapi_pc pc; - unsigned long flags; int retval, count = 0; int sprev = !!(tape->caps[4] & 0x20); @@ -2651,48 +1984,12 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op, } if (tape->chrdev_dir == IDETAPE_DIR_READ) { - /* its a read-ahead buffer, scan it for crossed filemarks. */ - tape->merge_stage_size = 0; + tape->merge_bh_size = 0; if (test_and_clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags)) ++count; - while (tape->first_stage != NULL) { - if (count == mt_count) { - if (mt_op == MTFSFM) - set_bit(IDETAPE_FLAG_FILEMARK, - &tape->flags); - return 0; - } - spin_lock_irqsave(&tape->lock, flags); - if (tape->first_stage == tape->active_stage) { - /* - * We have reached the active stage in the read - * pipeline. There is no point in allowing the - * drive to continue reading any farther, so we - * stop the pipeline. - * - * This section should be moved to a separate - * subroutine because similar operations are - * done in __idetape_discard_read_pipeline(), - * for example. - */ - tape->next_stage = NULL; - spin_unlock_irqrestore(&tape->lock, flags); - idetape_wait_first_stage(drive); - tape->next_stage = tape->first_stage->next; - } else - spin_unlock_irqrestore(&tape->lock, flags); - if (tape->first_stage->rq.errors == - IDETAPE_ERROR_FILEMARK) - ++count; - idetape_remove_stage_head(drive); - } - idetape_discard_read_pipeline(drive, 0); + ide_tape_discard_merge_buffer(drive, 0); } - /* - * The filemark was not found in our internal pipeline; now we can issue - * the space command. - */ switch (mt_op) { case MTFSF: case MTBSF: @@ -2748,27 +2045,25 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf, (count % tape->blk_size) == 0) tape->user_bs_factor = count / tape->blk_size; } - rc = idetape_init_read(drive, tape->max_stages); + rc = idetape_init_read(drive); if (rc < 0) return rc; if (count == 0) return (0); - if (tape->merge_stage_size) { - actually_read = min((unsigned int)(tape->merge_stage_size), + if (tape->merge_bh_size) { + actually_read = min((unsigned int)(tape->merge_bh_size), (unsigned int)count); - if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, - actually_read)) + if (idetape_copy_stage_to_user(tape, buf, actually_read)) ret = -EFAULT; buf += actually_read; - tape->merge_stage_size -= actually_read; + tape->merge_bh_size -= actually_read; count -= actually_read; } - while (count >= tape->stage_size) { + while (count >= tape->buffer_size) { 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)) + if (idetape_copy_stage_to_user(tape, buf, bytes_read)) ret = -EFAULT; buf += bytes_read; count -= bytes_read; @@ -2779,11 +2074,10 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf, if (bytes_read <= 0) goto finish; temp = min((unsigned long)count, (unsigned long)bytes_read); - if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, - temp)) + if (idetape_copy_stage_to_user(tape, buf, temp)) ret = -EFAULT; actually_read += temp; - tape->merge_stage_size = bytes_read-temp; + tape->merge_bh_size = bytes_read-temp; } finish: if (!actually_read && test_bit(IDETAPE_FLAG_FILEMARK, &tape->flags)) { @@ -2814,17 +2108,17 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, /* Initialize write operation */ if (tape->chrdev_dir != IDETAPE_DIR_WRITE) { if (tape->chrdev_dir == IDETAPE_DIR_READ) - idetape_discard_read_pipeline(drive, 1); - if (tape->merge_stage || tape->merge_stage_size) { - printk(KERN_ERR "ide-tape: merge_stage_size " + ide_tape_discard_merge_buffer(drive, 1); + if (tape->merge_bh || tape->merge_bh_size) { + printk(KERN_ERR "ide-tape: merge_bh_size " "should be 0 now\n"); - tape->merge_stage_size = 0; + tape->merge_bh_size = 0; } - tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0); - if (!tape->merge_stage) + tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0); + if (!tape->merge_bh) return -ENOMEM; tape->chrdev_dir = IDETAPE_DIR_WRITE; - idetape_init_merge_stage(tape); + idetape_init_merge_buffer(tape); /* * Issue a write 0 command to ensure that DSC handshake is @@ -2835,10 +2129,10 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, if (drive->dsc_overlap) { ssize_t retval = idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 0, - tape->merge_stage->bh); + tape->merge_bh); if (retval < 0) { - __idetape_kfree_stage(tape->merge_stage); - tape->merge_stage = NULL; + ide_tape_kfree_buffer(tape); + tape->merge_bh = NULL; tape->chrdev_dir = IDETAPE_DIR_NONE; return retval; } @@ -2846,49 +2140,44 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, } if (count == 0) return (0); - if (tape->restart_speed_control_req) - idetape_restart_speed_control(drive); - if (tape->merge_stage_size) { - if (tape->merge_stage_size >= tape->stage_size) { + if (tape->merge_bh_size) { + if (tape->merge_bh_size >= tape->buffer_size) { printk(KERN_ERR "ide-tape: bug: merge buf too big\n"); - tape->merge_stage_size = 0; + tape->merge_bh_size = 0; } actually_written = min((unsigned int) - (tape->stage_size - tape->merge_stage_size), + (tape->buffer_size - tape->merge_bh_size), (unsigned int)count); - if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, - actually_written)) + if (idetape_copy_stage_from_user(tape, buf, actually_written)) ret = -EFAULT; buf += actually_written; - tape->merge_stage_size += actually_written; + tape->merge_bh_size += actually_written; count -= actually_written; - if (tape->merge_stage_size == tape->stage_size) { + if (tape->merge_bh_size == tape->buffer_size) { ssize_t retval; - tape->merge_stage_size = 0; + tape->merge_bh_size = 0; retval = idetape_add_chrdev_write_request(drive, ctl); if (retval <= 0) return (retval); } } - while (count >= tape->stage_size) { + while (count >= tape->buffer_size) { ssize_t retval; - if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, - tape->stage_size)) + if (idetape_copy_stage_from_user(tape, buf, tape->buffer_size)) ret = -EFAULT; - buf += tape->stage_size; - count -= tape->stage_size; + buf += tape->buffer_size; + count -= tape->buffer_size; retval = idetape_add_chrdev_write_request(drive, ctl); - actually_written += tape->stage_size; + actually_written += tape->buffer_size; if (retval <= 0) return (retval); } if (count) { actually_written += count; - if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, - count)) + if (idetape_copy_stage_from_user(tape, buf, count)) ret = -EFAULT; - tape->merge_stage_size += count; + tape->merge_bh_size += count; } return ret ? ret : actually_written; } @@ -2912,8 +2201,7 @@ static int idetape_write_filemark(ide_drive_t *drive) * * Note: MTBSF and MTBSFM are not supported when the tape doesn't support * spacing over filemarks in the reverse direction. In this case, MTFSFM is also - * usually not supported (it is supported in the rare case in which we crossed - * the filemark during our read-ahead pipelined operation mode). + * usually not supported. * * The following commands are currently not supported: * @@ -2929,7 +2217,6 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) debug_log(DBG_ERR, "Handling MTIOCTOP ioctl: mt_op=%d, mt_count=%d\n", mt_op, mt_count); - /* Commands which need our pipelined read-ahead stages. */ switch (mt_op) { case MTFSF: case MTFSFM: @@ -2946,7 +2233,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) case MTWEOF: if (tape->write_prot) return -EACCES; - idetape_discard_read_pipeline(drive, 1); + ide_tape_discard_merge_buffer(drive, 1); for (i = 0; i < mt_count; i++) { retval = idetape_write_filemark(drive); if (retval) @@ -2954,12 +2241,12 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) } return 0; case MTREW: - idetape_discard_read_pipeline(drive, 0); + ide_tape_discard_merge_buffer(drive, 0); if (idetape_rewind_tape(drive)) return -EIO; return 0; case MTLOAD: - idetape_discard_read_pipeline(drive, 0); + ide_tape_discard_merge_buffer(drive, 0); idetape_create_load_unload_cmd(drive, &pc, IDETAPE_LU_LOAD_MASK); return idetape_queue_pc_tail(drive, &pc); @@ -2974,7 +2261,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) if (!idetape_queue_pc_tail(drive, &pc)) tape->door_locked = DOOR_UNLOCKED; } - idetape_discard_read_pipeline(drive, 0); + ide_tape_discard_merge_buffer(drive, 0); idetape_create_load_unload_cmd(drive, &pc, !IDETAPE_LU_LOAD_MASK); retval = idetape_queue_pc_tail(drive, &pc); @@ -2982,10 +2269,10 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) clear_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags); return retval; case MTNOP: - idetape_discard_read_pipeline(drive, 0); + ide_tape_discard_merge_buffer(drive, 0); return idetape_flush_tape_buffers(drive); case MTRETEN: - idetape_discard_read_pipeline(drive, 0); + ide_tape_discard_merge_buffer(drive, 0); idetape_create_load_unload_cmd(drive, &pc, IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK); return idetape_queue_pc_tail(drive, &pc); @@ -3007,11 +2294,11 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) set_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags); return 0; case MTSEEK: - idetape_discard_read_pipeline(drive, 0); + ide_tape_discard_merge_buffer(drive, 0); return idetape_position_tape(drive, mt_count * tape->user_bs_factor, tape->partition, 0); case MTSETPART: - idetape_discard_read_pipeline(drive, 0); + ide_tape_discard_merge_buffer(drive, 0); return idetape_position_tape(drive, 0, mt_count, 0); case MTFSR: case MTBSR: @@ -3056,13 +2343,12 @@ static int idetape_chrdev_ioctl(struct inode *inode, struct file *file, debug_log(DBG_CHRDEV, "Enter %s, cmd=%u\n", __func__, cmd); - tape->restart_speed_control_req = 1; if (tape->chrdev_dir == IDETAPE_DIR_WRITE) { - idetape_empty_write_pipeline(drive); + ide_tape_flush_merge_buffer(drive); idetape_flush_tape_buffers(drive); } if (cmd == MTIOCGET || cmd == MTIOCPOS) { - block_offset = idetape_pipeline_size(drive) / + block_offset = tape->merge_bh_size / (tape->blk_size * tape->user_bs_factor); position = idetape_read_position(drive); if (position < 0) @@ -3094,7 +2380,7 @@ static int idetape_chrdev_ioctl(struct inode *inode, struct file *file, return 0; default: if (tape->chrdev_dir == IDETAPE_DIR_READ) - idetape_discard_read_pipeline(drive, 1); + ide_tape_discard_merge_buffer(drive, 1); return idetape_blkdev_ioctl(drive, cmd, arg); } } @@ -3168,9 +2454,6 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp) if (!test_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags)) (void)idetape_rewind_tape(drive); - if (tape->chrdev_dir != IDETAPE_DIR_READ) - clear_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags); - /* Read block size and write protect status from drive. */ ide_tape_get_bsize_from_bdesc(drive); @@ -3199,8 +2482,6 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp) } } } - idetape_restart_speed_control(drive); - tape->restart_speed_control_req = 0; return 0; out_put_tape: @@ -3212,13 +2493,13 @@ static void idetape_write_release(ide_drive_t *drive, unsigned int minor) { idetape_tape_t *tape = drive->driver_data; - idetape_empty_write_pipeline(drive); - tape->merge_stage = __idetape_kmalloc_stage(tape, 1, 0); - if (tape->merge_stage != NULL) { + ide_tape_flush_merge_buffer(drive); + tape->merge_bh = ide_tape_kmalloc_buffer(tape, 1, 0); + if (tape->merge_bh != NULL) { idetape_pad_zeros(drive, tape->blk_size * (tape->user_bs_factor - 1)); - __idetape_kfree_stage(tape->merge_stage); - tape->merge_stage = NULL; + ide_tape_kfree_buffer(tape); + tape->merge_bh = NULL; } idetape_write_filemark(drive); idetape_flush_tape_buffers(drive); @@ -3241,14 +2522,9 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp) idetape_write_release(drive, minor); if (tape->chrdev_dir == IDETAPE_DIR_READ) { if (minor < 128) - idetape_discard_read_pipeline(drive, 1); - else - idetape_wait_for_pipeline(drive); - } - if (tape->cache_stage != NULL) { - __idetape_kfree_stage(tape->cache_stage); - tape->cache_stage = NULL; + ide_tape_discard_merge_buffer(drive, 1); } + if (minor < 128 && test_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags)) (void) idetape_rewind_tape(drive); if (tape->chrdev_dir == IDETAPE_DIR_NONE) { @@ -3385,33 +2661,15 @@ static void idetape_add_settings(ide_drive_t *drive) 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, (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, "buffer_size", SETTING_READ, TYPE_INT, 0, 0xffff, + 1, 1024, &tape->buffer_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_freq, NULL); ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); - ide_add_setting(drive, "pipeline_head_speed_c", SETTING_READ, TYPE_INT, - 0, 0xffff, 1, 1, &tape->controlled_pipeline_head_speed, - NULL); - ide_add_setting(drive, "pipeline_head_speed_u", SETTING_READ, TYPE_INT, - 0, 0xffff, 1, 1, - &tape->uncontrolled_pipeline_head_speed, NULL); ide_add_setting(drive, "avg_speed", SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1, &tape->avg_speed, NULL); ide_add_setting(drive, "debug_mask", SETTING_RW, TYPE_INT, 0, 0xffff, 1, @@ -3434,11 +2692,10 @@ static inline void idetape_add_settings(ide_drive_t *drive) { ; } */ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor) { - unsigned long t1, tmid, tn, t; + unsigned long t; int speed; - int stage_size; + int buffer_size; u8 gcw[2]; - struct sysinfo si; u16 *ctl = (u16 *)&tape->caps[12]; spin_lock_init(&tape->lock); @@ -3457,65 +2714,33 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor) tape->name[2] = '0' + minor; tape->chrdev_dir = IDETAPE_DIR_NONE; tape->pc = tape->pc_stack; - tape->max_insert_speed = 10000; - tape->speed_control = 1; *((unsigned short *) &gcw) = drive->id->config; /* Command packet DRQ type */ if (((gcw[0] & 0x60) >> 5) == 1) set_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags); - tape->min_pipeline = 10; - tape->max_pipeline = 10; - tape->max_stages = 10; - idetape_get_inquiry_results(drive); idetape_get_mode_sense_results(drive); ide_tape_get_bsize_from_bdesc(drive); tape->user_bs_factor = 1; - tape->stage_size = *ctl * tape->blk_size; - while (tape->stage_size > 0xffff) { + tape->buffer_size = *ctl * tape->blk_size; + while (tape->buffer_size > 0xffff) { printk(KERN_NOTICE "ide-tape: decreasing stage size\n"); *ctl /= 2; - tape->stage_size = *ctl * tape->blk_size; + tape->buffer_size = *ctl * tape->blk_size; } - stage_size = tape->stage_size; - tape->pages_per_stage = stage_size / PAGE_SIZE; - if (stage_size % PAGE_SIZE) { - tape->pages_per_stage++; - tape->excess_bh_size = PAGE_SIZE - stage_size % PAGE_SIZE; + buffer_size = tape->buffer_size; + tape->pages_per_buffer = buffer_size / PAGE_SIZE; + if (buffer_size % PAGE_SIZE) { + tape->pages_per_buffer++; + tape->excess_bh_size = PAGE_SIZE - buffer_size % PAGE_SIZE; } - /* Select the "best" DSC read/write polling freq and pipeline size. */ + /* select the "best" DSC read/write polling freq */ speed = max(*(u16 *)&tape->caps[14], *(u16 *)&tape->caps[8]); - tape->max_stages = speed * 1000 * 10 / tape->stage_size; - - /* Limit memory use for pipeline to 10% of physical memory */ - si_meminfo(&si); - if (tape->max_stages * tape->stage_size > - si.totalram * si.mem_unit / 10) - tape->max_stages = - si.totalram * si.mem_unit / (10 * tape->stage_size); - - tape->max_stages = min(tape->max_stages, IDETAPE_MAX_PIPELINE_STAGES); - tape->min_pipeline = min(tape->max_stages, IDETAPE_MIN_PIPELINE_STAGES); - tape->max_pipeline = - min(tape->max_stages * 2, IDETAPE_MAX_PIPELINE_STAGES); - if (tape->max_stages == 0) { - tape->max_stages = 1; - tape->min_pipeline = 1; - tape->max_pipeline = 1; - } - - t1 = (tape->stage_size * HZ) / (speed * 1000); - tmid = (*(u16 *)&tape->caps[16] * 32 * HZ) / (speed * 125); - tn = (IDETAPE_FIFO_THRESHOLD * tape->stage_size * HZ) / (speed * 1000); - - if (tape->max_stages) - t = tn; - else - t = t1; + t = (IDETAPE_FIFO_THRESHOLD * tape->buffer_size * HZ) / (speed * 1000); /* * Ensure that the number we got makes sense; limit it within @@ -3525,11 +2750,10 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor) 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", + "%lums tDSC%s\n", 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, + (*(u16 *)&tape->caps[16] * 512) / tape->buffer_size, + tape->buffer_size / 1024, tape->best_dsc_rw_freq * 1000 / HZ, drive->using_dma ? ", DMA":""); @@ -3553,7 +2777,7 @@ static void ide_tape_release(struct kref *kref) ide_drive_t *drive = tape->drive; struct gendisk *g = tape->disk; - BUG_ON(tape->first_stage != NULL || tape->merge_stage_size); + BUG_ON(tape->merge_bh_size); drive->dsc_overlap = 0; drive->driver_data = NULL; diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index a317ca9c46e5..0c908ca3ff79 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -33,60 +33,18 @@ #include <asm/uaccess.h> #include <asm/io.h> -void ide_tf_load(ide_drive_t *drive, ide_task_t *task) +void ide_tf_dump(const char *s, struct ide_taskfile *tf) { - ide_hwif_t *hwif = drive->hwif; - struct ide_taskfile *tf = &task->tf; - u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; - - if (task->tf_flags & IDE_TFLAG_FLAGGED) - HIHI = 0xFF; - #ifdef DEBUG printk("%s: tf: feat 0x%02x nsect 0x%02x lbal 0x%02x " "lbam 0x%02x lbah 0x%02x dev 0x%02x cmd 0x%02x\n", - drive->name, tf->feature, tf->nsect, tf->lbal, + s, tf->feature, tf->nsect, tf->lbal, tf->lbam, tf->lbah, tf->device, tf->command); printk("%s: hob: nsect 0x%02x lbal 0x%02x " "lbam 0x%02x lbah 0x%02x\n", - drive->name, tf->hob_nsect, tf->hob_lbal, + s, tf->hob_nsect, tf->hob_lbal, tf->hob_lbam, tf->hob_lbah); #endif - - 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) - hwif->OUTW((tf->hob_data << 8) | tf->data, - hwif->io_ports[IDE_DATA_OFFSET]); - - if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) - hwif->OUTB(tf->hob_feature, hwif->io_ports[IDE_FEATURE_OFFSET]); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) - hwif->OUTB(tf->hob_nsect, hwif->io_ports[IDE_NSECTOR_OFFSET]); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) - hwif->OUTB(tf->hob_lbal, hwif->io_ports[IDE_SECTOR_OFFSET]); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) - hwif->OUTB(tf->hob_lbam, hwif->io_ports[IDE_LCYL_OFFSET]); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) - hwif->OUTB(tf->hob_lbah, hwif->io_ports[IDE_HCYL_OFFSET]); - - if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) - hwif->OUTB(tf->feature, hwif->io_ports[IDE_FEATURE_OFFSET]); - if (task->tf_flags & IDE_TFLAG_OUT_NSECT) - hwif->OUTB(tf->nsect, hwif->io_ports[IDE_NSECTOR_OFFSET]); - if (task->tf_flags & IDE_TFLAG_OUT_LBAL) - hwif->OUTB(tf->lbal, hwif->io_ports[IDE_SECTOR_OFFSET]); - if (task->tf_flags & IDE_TFLAG_OUT_LBAM) - hwif->OUTB(tf->lbam, hwif->io_ports[IDE_LCYL_OFFSET]); - if (task->tf_flags & IDE_TFLAG_OUT_LBAH) - hwif->OUTB(tf->lbah, hwif->io_ports[IDE_HCYL_OFFSET]); - - if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) - hwif->OUTB((tf->device & HIHI) | drive->select.all, - hwif->io_ports[IDE_SELECT_OFFSET]); } int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf) @@ -149,14 +107,15 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) if (task->tf_flags & IDE_TFLAG_FLAGGED) task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS; - if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) - ide_tf_load(drive, task); + if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) { + ide_tf_dump(drive->name, tf); + hwif->tf_load(drive, task); + } switch (task->data_phase) { case TASKFILE_MULTI_OUT: case TASKFILE_OUT: - hwif->OUTBSYNC(drive, tf->command, - hwif->io_ports[IDE_COMMAND_OFFSET]); + hwif->OUTBSYNC(drive, tf->command, hwif->io_ports.command_addr); ndelay(400); /* FIXME */ return pre_task_out_intr(drive, task->rq); case TASKFILE_MULTI_IN: @@ -284,7 +243,8 @@ static u8 wait_drive_not_busy(ide_drive_t *drive) return stat; } -static void ide_pio_sector(ide_drive_t *drive, unsigned int write) +static void ide_pio_sector(ide_drive_t *drive, struct request *rq, + unsigned int write) { ide_hwif_t *hwif = drive->hwif; struct scatterlist *sg = hwif->sg_table; @@ -324,9 +284,9 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write) /* do the actual data transfer */ if (write) - hwif->ata_output_data(drive, buf, SECTOR_WORDS); + hwif->output_data(drive, rq, buf, SECTOR_SIZE); else - hwif->ata_input_data(drive, buf, SECTOR_WORDS); + hwif->input_data(drive, rq, buf, SECTOR_SIZE); kunmap_atomic(buf, KM_BIO_SRC_IRQ); #ifdef CONFIG_HIGHMEM @@ -334,13 +294,14 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write) #endif } -static void ide_pio_multi(ide_drive_t *drive, unsigned int write) +static void ide_pio_multi(ide_drive_t *drive, struct request *rq, + unsigned int write) { unsigned int nsect; nsect = min_t(unsigned int, drive->hwif->nleft, drive->mult_count); while (nsect--) - ide_pio_sector(drive, write); + ide_pio_sector(drive, rq, write); } static void ide_pio_datablock(ide_drive_t *drive, struct request *rq, @@ -363,10 +324,10 @@ static void ide_pio_datablock(ide_drive_t *drive, struct request *rq, switch (drive->hwif->data_phase) { case TASKFILE_MULTI_IN: case TASKFILE_MULTI_OUT: - ide_pio_multi(drive, write); + ide_pio_multi(drive, rq, write); break; default: - ide_pio_sector(drive, write); + ide_pio_sector(drive, rq, write); break; } @@ -533,8 +494,7 @@ int ide_raw_taskfile(ide_drive_t *drive, ide_task_t *task, u8 *buf, u16 nsect) { struct request rq; - memset(&rq, 0, sizeof(rq)); - rq.ref_count = 1; + blk_rq_init(NULL, &rq); rq.cmd_type = REQ_TYPE_ATA_TASKFILE; rq.buffer = buf; diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index bced02f9f2c3..c758dcb13b14 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -94,12 +94,6 @@ DEFINE_MUTEX(ide_cfg_mtx); int noautodma = 0; -#ifdef CONFIG_BLK_DEV_IDEACPI -int ide_noacpi = 0; -int ide_noacpitfs = 1; -int ide_noacpionboot = 1; -#endif - ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */ static void ide_port_init_devices_data(ide_hwif_t *); @@ -293,7 +287,7 @@ EXPORT_SYMBOL_GPL(ide_port_unregister_devices); /** * ide_unregister - free an IDE interface - * @index: index of interface (will change soon to a pointer) + * @hwif: IDE interface * * Perform the final unregister of an IDE interface. At the moment * we don't refcount interfaces so this will also get split up. @@ -313,19 +307,16 @@ EXPORT_SYMBOL_GPL(ide_port_unregister_devices); * This is raving bonkers. */ -void ide_unregister(unsigned int index) +void ide_unregister(ide_hwif_t *hwif) { - ide_hwif_t *hwif, *g; + ide_hwif_t *g; ide_hwgroup_t *hwgroup; int irq_count = 0; - BUG_ON(index >= MAX_HWIFS); - BUG_ON(in_interrupt()); BUG_ON(irqs_disabled()); mutex_lock(&ide_cfg_mtx); spin_lock_irq(&ide_lock); - hwif = &ide_hwifs[index]; if (!hwif->present) goto abort; __ide_port_unregister_devices(hwif); @@ -366,7 +357,7 @@ void ide_unregister(unsigned int index) ide_release_dma_engine(hwif); /* restore hwif data to pristine status */ - ide_init_port_data(hwif, index); + ide_init_port_data(hwif, hwif->index); abort: spin_unlock_irq(&ide_lock); @@ -377,7 +368,7 @@ EXPORT_SYMBOL(ide_unregister); void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw) { - memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports)); + memcpy(&hwif->io_ports, &hw->io_ports, sizeof(hwif->io_ports)); hwif->irq = hw->irq; hwif->chipset = hw->chipset; hwif->gendev.parent = hw->dev; @@ -573,7 +564,7 @@ static int generic_ide_suspend(struct device *dev, pm_message_t mesg) if (!(drive->dn % 2)) ide_acpi_get_timing(hwif); - memset(&rq, 0, sizeof(rq)); + blk_rq_init(NULL, &rq); memset(&rqpm, 0, sizeof(rqpm)); memset(&args, 0, sizeof(args)); rq.cmd_type = REQ_TYPE_PM_SUSPEND; @@ -611,7 +602,7 @@ static int generic_ide_resume(struct device *dev) ide_acpi_exec_tfs(drive); - memset(&rq, 0, sizeof(rq)); + blk_rq_init(NULL, &rq); memset(&rqpm, 0, sizeof(rqpm)); memset(&args, 0, sizeof(args)); rq.cmd_type = REQ_TYPE_PM_RESUME; @@ -837,16 +828,6 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m return 0; /* zero = nothing matched */ } -extern int probe_ali14xx; -extern int probe_umc8672; -extern int probe_dtc2278; -extern int probe_ht6560b; -extern int probe_qd65xx; -extern int cmd640_vlb; -extern int probe_4drives; - -static int __initdata is_chipset_set; - /* * ide_setup() gets called VERY EARLY during initialization, * to handle kernel "command line" strings beginning with "hdx=" or "ide". @@ -855,14 +836,12 @@ static int __initdata is_chipset_set; */ static int __init ide_setup(char *s) { - int i, vals[3]; ide_hwif_t *hwif; ide_drive_t *drive; unsigned int hw, unit; + int vals[3]; const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1); - const char max_hwif = '0' + (MAX_HWIFS - 1); - if (strncmp(s,"hd",2) == 0 && s[2] == '=') /* hd= is for hd.c */ return 0; /* driver and not us */ @@ -878,7 +857,7 @@ static int __init ide_setup(char *s) printk(" : Enabled support for IDE doublers\n"); ide_doubler = 1; - return 1; + goto obsolete_option; } #endif /* CONFIG_BLK_DEV_IDEDOUBLER */ @@ -892,17 +871,17 @@ static int __init ide_setup(char *s) if (!strcmp(s, "ide=noacpi")) { //printk(" : Disable IDE ACPI support.\n"); ide_noacpi = 1; - return 1; + goto obsolete_option; } if (!strcmp(s, "ide=acpigtf")) { //printk(" : Enable IDE ACPI _GTF support.\n"); - ide_noacpitfs = 0; - return 1; + ide_acpigtf = 1; + goto obsolete_option; } if (!strcmp(s, "ide=acpionboot")) { //printk(" : Call IDE ACPI methods on boot.\n"); - ide_noacpionboot = 0; - return 1; + ide_acpionboot = 1; + goto obsolete_option; } #endif /* CONFIG_BLK_DEV_IDEACPI */ @@ -912,7 +891,7 @@ static int __init ide_setup(char *s) if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) { const char *hd_words[] = { "none", "noprobe", "nowerr", "cdrom", "nodma", - "autotune", "noautotune", "-8", "-9", "-10", + "-6", "-7", "-8", "-9", "-10", "noflush", "remap", "remap63", "scsi", NULL }; unit = s[2] - 'a'; hw = unit / MAX_DRIVES; @@ -927,28 +906,22 @@ static int __init ide_setup(char *s) case -1: /* "none" */ case -2: /* "noprobe" */ drive->noprobe = 1; - goto done; + goto obsolete_option; case -3: /* "nowerr" */ drive->bad_wstat = BAD_R_STAT; - goto done; + goto obsolete_option; case -4: /* "cdrom" */ drive->present = 1; drive->media = ide_cdrom; /* an ATAPI device ignores DRDY */ drive->ready_stat = 0; - goto done; + goto obsolete_option; case -5: /* nodma */ drive->nodma = 1; - goto done; - case -6: /* "autotune" */ - drive->autotune = IDE_TUNE_AUTO; - goto obsolete_option; - case -7: /* "noautotune" */ - drive->autotune = IDE_TUNE_NOAUTO; goto obsolete_option; case -11: /* noflush */ drive->noflush = 1; - goto done; + goto obsolete_option; case -12: /* "remap" */ drive->remap_0_to_1 = 1; goto obsolete_option; @@ -966,7 +939,7 @@ static int __init ide_setup(char *s) drive->sect = drive->bios_sect = vals[2]; drive->present = 1; drive->forced_geom = 1; - goto done; + goto obsolete_option; default: goto bad_option; } @@ -984,126 +957,15 @@ static int __init ide_setup(char *s) idebus_parameter = vals[0]; } else printk(" -- BAD BUS SPEED! Expected value from 20 to 66"); - goto done; + goto obsolete_option; } - /* - * Look for interface options: "idex=" - */ - if (s[3] >= '0' && s[3] <= max_hwif) { - /* - * Be VERY CAREFUL changing this: note hardcoded indexes below - * (-8, -9, -10) are reserved to ease the hardcoding. - */ - static const char *ide_words[] = { - "minus1", "serialize", "minus3", "minus4", - "reset", "minus6", "ata66", "minus8", "minus9", - "minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb", - "dtc2278", "umc8672", "ali14xx", NULL }; - - hw = s[3] - '0'; - hwif = &ide_hwifs[hw]; - i = match_parm(&s[4], ide_words, vals, 3); - - /* - * Cryptic check to ensure chipset not already set for hwif. - * Note: we can't depend on hwif->chipset here. - */ - if (i >= -18 && i <= -11) { - /* chipset already specified */ - if (is_chipset_set) - goto bad_option; - /* these drivers are for "ide0=" only */ - if (hw != 0) - goto bad_hwif; - is_chipset_set = 1; - printk("\n"); - } - - switch (i) { -#ifdef CONFIG_BLK_DEV_ALI14XX - case -17: /* "ali14xx" */ - probe_ali14xx = 1; - goto obsolete_option; -#endif -#ifdef CONFIG_BLK_DEV_UMC8672 - case -16: /* "umc8672" */ - probe_umc8672 = 1; - goto obsolete_option; -#endif -#ifdef CONFIG_BLK_DEV_DTC2278 - case -15: /* "dtc2278" */ - probe_dtc2278 = 1; - goto obsolete_option; -#endif -#ifdef CONFIG_BLK_DEV_CMD640 - case -14: /* "cmd640_vlb" */ - cmd640_vlb = 1; - goto obsolete_option; -#endif -#ifdef CONFIG_BLK_DEV_HT6560B - case -13: /* "ht6560b" */ - probe_ht6560b = 1; - goto obsolete_option; -#endif -#ifdef CONFIG_BLK_DEV_QD65XX - case -12: /* "qd65xx" */ - probe_qd65xx = 1; - goto obsolete_option; -#endif -#ifdef CONFIG_BLK_DEV_4DRIVES - case -11: /* "four" drives on one set of ports */ - probe_4drives = 1; - goto obsolete_option; -#endif - case -10: /* minus10 */ - case -9: /* minus9 */ - case -8: /* minus8 */ - case -6: - case -4: - case -3: - goto bad_option; - case -7: /* ata66 */ -#ifdef CONFIG_BLK_DEV_IDEPCI - /* - * Use ATA_CBL_PATA40_SHORT so drive side - * cable detection is also overriden. - */ - hwif->cbl = ATA_CBL_PATA40_SHORT; - goto obsolete_option; -#else - goto bad_hwif; -#endif - case -5: /* "reset" */ - hwif->reset = 1; - goto obsolete_option; - case -2: /* "serialize" */ - hwif->mate = &ide_hwifs[hw^1]; - hwif->mate->mate = hwif; - hwif->serialized = hwif->mate->serialized = 1; - goto obsolete_option; - case -1: - case 0: - case 1: - case 2: - case 3: - goto bad_option; - default: - printk(" -- SUPPORT NOT CONFIGURED IN THIS KERNEL\n"); - return 1; - } - } bad_option: printk(" -- BAD OPTION\n"); return 1; obsolete_option: printk(" -- OBSOLETE OPTION, WILL BE REMOVED SOON!\n"); return 1; -bad_hwif: - printk("-- NOT SUPPORTED ON ide%d", hw); -done: - printk("\n"); - return 1; } EXPORT_SYMBOL(ide_lock); @@ -1239,6 +1101,185 @@ static void ide_port_class_release(struct device *portdev) put_device(&hwif->gendev); } +int ide_vlb_clk; +EXPORT_SYMBOL_GPL(ide_vlb_clk); + +module_param_named(vlb_clock, ide_vlb_clk, int, 0); +MODULE_PARM_DESC(vlb_clock, "VLB clock frequency (in MHz)"); + +int ide_pci_clk; +EXPORT_SYMBOL_GPL(ide_pci_clk); + +module_param_named(pci_clock, ide_pci_clk, int, 0); +MODULE_PARM_DESC(pci_clock, "PCI bus clock frequency (in MHz)"); + +static int ide_set_dev_param_mask(const char *s, struct kernel_param *kp) +{ + int a, b, i, j = 1; + unsigned int *dev_param_mask = (unsigned int *)kp->arg; + + if (sscanf(s, "%d.%d:%d", &a, &b, &j) != 3 && + sscanf(s, "%d.%d", &a, &b) != 2) + return -EINVAL; + + i = a * MAX_DRIVES + b; + + if (i >= MAX_HWIFS * MAX_DRIVES || j < 0 || j > 1) + return -EINVAL; + + if (j) + *dev_param_mask |= (1 << i); + else + *dev_param_mask &= (1 << i); + + return 0; +} + +static unsigned int ide_nodma; + +module_param_call(nodma, ide_set_dev_param_mask, NULL, &ide_nodma, 0); +MODULE_PARM_DESC(nodma, "disallow DMA for a device"); + +static unsigned int ide_noflush; + +module_param_call(noflush, ide_set_dev_param_mask, NULL, &ide_noflush, 0); +MODULE_PARM_DESC(noflush, "disable flush requests for a device"); + +static unsigned int ide_noprobe; + +module_param_call(noprobe, ide_set_dev_param_mask, NULL, &ide_noprobe, 0); +MODULE_PARM_DESC(noprobe, "skip probing for a device"); + +static unsigned int ide_nowerr; + +module_param_call(nowerr, ide_set_dev_param_mask, NULL, &ide_nowerr, 0); +MODULE_PARM_DESC(nowerr, "ignore the WRERR_STAT bit for a device"); + +static unsigned int ide_cdroms; + +module_param_call(cdrom, ide_set_dev_param_mask, NULL, &ide_cdroms, 0); +MODULE_PARM_DESC(cdrom, "force device as a CD-ROM"); + +struct chs_geom { + unsigned int cyl; + u8 head; + u8 sect; +}; + +static unsigned int ide_disks; +static struct chs_geom ide_disks_chs[MAX_HWIFS * MAX_DRIVES]; + +static int ide_set_disk_chs(const char *str, struct kernel_param *kp) +{ + int a, b, c = 0, h = 0, s = 0, i, j = 1; + + if (sscanf(str, "%d.%d:%d,%d,%d", &a, &b, &c, &h, &s) != 5 && + sscanf(str, "%d.%d:%d", &a, &b, &j) != 3) + return -EINVAL; + + i = a * MAX_DRIVES + b; + + if (i >= MAX_HWIFS * MAX_DRIVES || j < 0 || j > 1) + return -EINVAL; + + if (c > INT_MAX || h > 255 || s > 255) + return -EINVAL; + + if (j) + ide_disks |= (1 << i); + else + ide_disks &= (1 << i); + + ide_disks_chs[i].cyl = c; + ide_disks_chs[i].head = h; + ide_disks_chs[i].sect = s; + + return 0; +} + +module_param_call(chs, ide_set_disk_chs, NULL, NULL, 0); +MODULE_PARM_DESC(chs, "force device as a disk (using CHS)"); + +static void ide_dev_apply_params(ide_drive_t *drive) +{ + int i = drive->hwif->index * MAX_DRIVES + drive->select.b.unit; + + if (ide_nodma & (1 << i)) { + printk(KERN_INFO "ide: disallowing DMA for %s\n", drive->name); + drive->nodma = 1; + } + if (ide_noflush & (1 << i)) { + printk(KERN_INFO "ide: disabling flush requests for %s\n", + drive->name); + drive->noflush = 1; + } + if (ide_noprobe & (1 << i)) { + printk(KERN_INFO "ide: skipping probe for %s\n", drive->name); + drive->noprobe = 1; + } + if (ide_nowerr & (1 << i)) { + printk(KERN_INFO "ide: ignoring the WRERR_STAT bit for %s\n", + drive->name); + drive->bad_wstat = BAD_R_STAT; + } + if (ide_cdroms & (1 << i)) { + printk(KERN_INFO "ide: forcing %s as a CD-ROM\n", drive->name); + drive->present = 1; + drive->media = ide_cdrom; + /* an ATAPI device ignores DRDY */ + drive->ready_stat = 0; + } + if (ide_disks & (1 << i)) { + drive->cyl = drive->bios_cyl = ide_disks_chs[i].cyl; + drive->head = drive->bios_head = ide_disks_chs[i].head; + drive->sect = drive->bios_sect = ide_disks_chs[i].sect; + drive->forced_geom = 1; + printk(KERN_INFO "ide: forcing %s as a disk (%d/%d/%d)\n", + drive->name, + drive->cyl, drive->head, drive->sect); + drive->present = 1; + drive->media = ide_disk; + drive->ready_stat = READY_STAT; + } +} + +static unsigned int ide_ignore_cable; + +static int ide_set_ignore_cable(const char *s, struct kernel_param *kp) +{ + int i, j = 1; + + if (sscanf(s, "%d:%d", &i, &j) != 2 && sscanf(s, "%d", &i) != 1) + return -EINVAL; + + if (i >= MAX_HWIFS || j < 0 || j > 1) + return -EINVAL; + + if (j) + ide_ignore_cable |= (1 << i); + else + ide_ignore_cable &= (1 << i); + + return 0; +} + +module_param_call(ignore_cable, ide_set_ignore_cable, NULL, NULL, 0); +MODULE_PARM_DESC(ignore_cable, "ignore cable detection"); + +void ide_port_apply_params(ide_hwif_t *hwif) +{ + int i; + + if (ide_ignore_cable & (1 << hwif->index)) { + printk(KERN_INFO "ide: ignoring cable detection for %s\n", + hwif->name); + hwif->cbl = ATA_CBL_PATA40_SHORT; + } + + for (i = 0; i < MAX_DRIVES; i++) + ide_dev_apply_params(&hwif->drives[i]); +} + /* * This is gets invoked once during initialization, to set *everything* up */ @@ -1305,11 +1346,6 @@ int __init init_module (void) void __exit cleanup_module (void) { - int index; - - for (index = 0; index < MAX_HWIFS; ++index) - ide_unregister(index); - proc_ide_destroy(); class_destroy(ide_port_class); diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c index 6efbf947c6db..90c65cf97448 100644 --- a/drivers/ide/legacy/ali14xx.c +++ b/drivers/ide/legacy/ali14xx.c @@ -116,7 +116,7 @@ static void ali14xx_set_pio_mode(ide_drive_t *drive, const u8 pio) int time1, time2; u8 param1, param2, param3, param4; unsigned long flags; - int bus_speed = system_bus_clock(); + int bus_speed = ide_vlb_clk ? ide_vlb_clk : system_bus_clock(); /* calculate timing, according to PIO mode */ time1 = ide_pio_cycle_time(drive, pio); @@ -202,7 +202,7 @@ static const struct ide_port_info ali14xx_port_info = { .name = DRV_NAME, .chipset = ide_ali14xx, .port_ops = &ali14xx_port_ops, - .host_flags = IDE_HFLAG_NO_DMA | IDE_HFLAG_NO_AUTOTUNE, + .host_flags = IDE_HFLAG_NO_DMA, .pio_mask = ATA_PIO4, }; @@ -220,7 +220,7 @@ static int __init ali14xx_probe(void) return ide_legacy_device_add(&ali14xx_port_info, 0); } -int probe_ali14xx; +static int probe_ali14xx; module_param_named(probe, probe_ali14xx, bool, 0); MODULE_PARM_DESC(probe, "probe for ALI M14xx chipsets"); diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c index f51433bce8e4..5c730e4dd735 100644 --- a/drivers/ide/legacy/buddha.c +++ b/drivers/ide/legacy/buddha.c @@ -102,7 +102,7 @@ static int buddha_ack_intr(ide_hwif_t *hwif) { unsigned char ch; - ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]); + ch = z_readb(hwif->io_ports.irq_addr); if (!(ch & 0x80)) return 0; return 1; @@ -112,9 +112,9 @@ static int xsurf_ack_intr(ide_hwif_t *hwif) { unsigned char ch; - ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]); + ch = z_readb(hwif->io_ports.irq_addr); /* X-Surf needs a 0 written to IRQ register to ensure ISA bit A11 stays at 0 */ - z_writeb(0, hwif->io_ports[IDE_IRQ_OFFSET]); + z_writeb(0, hwif->io_ports.irq_addr); if (!(ch & 0x80)) return 0; return 1; @@ -128,13 +128,13 @@ static void __init buddha_setup_ports(hw_regs_t *hw, unsigned long base, memset(hw, 0, sizeof(*hw)); - hw->io_ports[IDE_DATA_OFFSET] = base; + hw->io_ports.data_addr = base; for (i = 1; i < 8; i++) - hw->io_ports[i] = base + 2 + i * 4; + hw->io_ports_array[i] = base + 2 + i * 4; - hw->io_ports[IDE_CONTROL_OFFSET] = ctl; - hw->io_ports[IDE_IRQ_OFFSET] = irq_port; + hw->io_ports.ctl_addr = ctl; + hw->io_ports.irq_addr = irq_port; hw->irq = IRQ_AMIGA_PORTS; hw->ack_intr = ack_intr; diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c index f7c4ad1c57c0..af791a02a120 100644 --- a/drivers/ide/legacy/dtc2278.c +++ b/drivers/ide/legacy/dtc2278.c @@ -101,8 +101,7 @@ static const struct ide_port_info dtc2278_port_info __initdata = { IDE_HFLAG_IO_32BIT | /* disallow ->io_32bit changes */ IDE_HFLAG_NO_IO_32BIT | - IDE_HFLAG_NO_DMA | - IDE_HFLAG_NO_AUTOTUNE, + IDE_HFLAG_NO_DMA, .pio_mask = ATA_PIO4, }; @@ -131,7 +130,7 @@ static int __init dtc2278_probe(void) return ide_legacy_device_add(&dtc2278_port_info, 0); } -int probe_dtc2278 = 0; +static int probe_dtc2278; module_param_named(probe, probe_dtc2278, bool, 0); MODULE_PARM_DESC(probe, "probe for DTC2278xx chipsets"); diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c index 5c19c422c5cc..83555ca513b5 100644 --- a/drivers/ide/legacy/falconide.c +++ b/drivers/ide/legacy/falconide.c @@ -44,18 +44,40 @@ int falconide_intr_lock; EXPORT_SYMBOL(falconide_intr_lock); +static void falconide_input_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + unsigned long data_addr = drive->hwif->io_ports.data_addr; + + if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS) + return insw(data_addr, buf, (len + 1) / 2); + + insw_swapw(data_addr, buf, (len + 1) / 2); +} + +static void falconide_output_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + unsigned long data_addr = drive->hwif->io_ports.data_addr; + + if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS) + return outsw(data_adr, buf, (len + 1) / 2); + + outsw_swapw(data_addr, buf, (len + 1) / 2); +} + static void __init falconide_setup_ports(hw_regs_t *hw) { int i; memset(hw, 0, sizeof(*hw)); - hw->io_ports[IDE_DATA_OFFSET] = ATA_HD_BASE; + hw->io_ports.data_addr = ATA_HD_BASE; for (i = 1; i < 8; i++) - hw->io_ports[i] = ATA_HD_BASE + 1 + i * 4; + hw->io_ports_array[i] = ATA_HD_BASE + 1 + i * 4; - hw->io_ports[IDE_CONTROL_OFFSET] = ATA_HD_BASE + ATA_HD_CONTROL; + hw->io_ports.ctl_addr = ATA_HD_BASE + ATA_HD_CONTROL; hw->irq = IRQ_MFP_IDE; hw->ack_intr = NULL; @@ -90,6 +112,10 @@ static int __init falconide_init(void) ide_init_port_data(hwif, index); ide_init_port_hw(hwif, &hw); + /* 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); ide_release_lock(); diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c index a0c9601bdaf0..a9c2593a898c 100644 --- a/drivers/ide/legacy/gayle.c +++ b/drivers/ide/legacy/gayle.c @@ -63,6 +63,8 @@ #define GAYLE_HAS_CONTROL_REG (!ide_doubler) #define GAYLE_IDEREG_SIZE (ide_doubler ? 0x1000 : 0x2000) int ide_doubler = 0; /* support IDE doublers? */ +module_param_named(doubler, ide_doubler, bool, 0); +MODULE_PARM_DESC(doubler, "enable support for IDE doublers"); #endif /* CONFIG_BLK_DEV_IDEDOUBLER */ @@ -74,7 +76,7 @@ static int gayle_ack_intr_a4000(ide_hwif_t *hwif) { unsigned char ch; - ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]); + ch = z_readb(hwif->io_ports.irq_addr); if (!(ch & GAYLE_IRQ_IDE)) return 0; return 1; @@ -84,11 +86,11 @@ static int gayle_ack_intr_a1200(ide_hwif_t *hwif) { unsigned char ch; - ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]); + ch = z_readb(hwif->io_ports.irq_addr); if (!(ch & GAYLE_IRQ_IDE)) return 0; - (void)z_readb(hwif->io_ports[IDE_STATUS_OFFSET]); - z_writeb(0x7c, hwif->io_ports[IDE_IRQ_OFFSET]); + (void)z_readb(hwif->io_ports.status_addr); + z_writeb(0x7c, hwif->io_ports.irq_addr); return 1; } @@ -100,13 +102,13 @@ static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base, memset(hw, 0, sizeof(*hw)); - hw->io_ports[IDE_DATA_OFFSET] = base; + hw->io_ports.data_addr = base; for (i = 1; i < 8; i++) - hw->io_ports[i] = base + 2 + i * 4; + hw->io_ports_array[i] = base + 2 + i * 4; - hw->io_ports[IDE_CONTROL_OFFSET] = ctl; - hw->io_ports[IDE_IRQ_OFFSET] = irq_port; + hw->io_ports.ctl_addr = ctl; + hw->io_ports.irq_addr = irq_port; hw->irq = IRQ_AMIGA_PORTS; hw->ack_intr = ack_intr; diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c index 702d8deb5780..4fe516df9f74 100644 --- a/drivers/ide/legacy/ht6560b.c +++ b/drivers/ide/legacy/ht6560b.c @@ -157,8 +157,8 @@ static void ht6560b_selectproc (ide_drive_t *drive) /* * Set timing for this drive: */ - outb(timing, hwif->io_ports[IDE_SELECT_OFFSET]); - (void)inb(hwif->io_ports[IDE_STATUS_OFFSET]); + outb(timing, hwif->io_ports.device_addr); + (void)inb(hwif->io_ports.status_addr); #ifdef DEBUG printk("ht6560b: %s: select=%#x timing=%#x\n", drive->name, select, timing); @@ -212,8 +212,8 @@ static u8 ht_pio2timings(ide_drive_t *drive, const u8 pio) { int active_time, recovery_time; int active_cycles, recovery_cycles; - int bus_speed = system_bus_clock(); - + int bus_speed = ide_vlb_clk ? ide_vlb_clk : system_bus_clock(); + if (pio) { unsigned int cycle_time; @@ -323,7 +323,7 @@ static void __init ht6560b_port_init_devs(ide_hwif_t *hwif) hwif->drives[1].drive_data = t; } -int probe_ht6560b = 0; +static int probe_ht6560b; module_param_named(probe, probe_ht6560b, bool, 0); MODULE_PARM_DESC(probe, "probe for HT6560B chipset"); @@ -340,7 +340,6 @@ static const struct ide_port_info ht6560b_port_info __initdata = { .port_ops = &ht6560b_port_ops, .host_flags = IDE_HFLAG_SERIALIZE | /* is this needed? */ IDE_HFLAG_NO_DMA | - IDE_HFLAG_NO_AUTOTUNE | IDE_HFLAG_ABUSE_PREFETCH, .pio_mask = ATA_PIO4, }; diff --git a/drivers/ide/legacy/ide-4drives.c b/drivers/ide/legacy/ide-4drives.c index 17f94d0cb539..ecae916a3385 100644 --- a/drivers/ide/legacy/ide-4drives.c +++ b/drivers/ide/legacy/ide-4drives.c @@ -6,7 +6,7 @@ #define DRV_NAME "ide-4drives" -int probe_4drives; +static int probe_4drives; module_param_named(probe, probe_4drives, bool, 0); MODULE_PARM_DESC(probe, "probe for generic IDE chipset with 4 drives/port"); diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 855e157b18d3..aa2ea3deac85 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -140,8 +140,8 @@ static void ide_detach(struct pcmcia_device *link) ide_release(link); - release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1); - release_region(hwif->io_ports[IDE_DATA_OFFSET], 8); + release_region(hwif->io_ports.ctl_addr, 1); + release_region(hwif->io_ports.data_addr, 8); kfree(info); } /* ide_detach */ @@ -183,11 +183,7 @@ static ide_hwif_t *idecs_register(unsigned long io, unsigned long ctl, i = hwif->index; - if (hwif->present) - ide_unregister(i); - else - ide_init_port_data(hwif, i); - + ide_init_port_data(hwif, i); ide_init_port_hw(hwif, &hw); hwif->port_ops = &idecs_port_ops; @@ -390,7 +386,7 @@ void ide_release(struct pcmcia_device *link) if (info->ndev) { /* FIXME: if this fails we need to queue the cleanup somehow -- need to investigate the required PCMCIA magic */ - ide_unregister(hwif->index); + ide_unregister(hwif); } info->ndev = 0; diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/legacy/ide_platform.c index 822f48b05c70..d3bc3f24e05d 100644 --- a/drivers/ide/legacy/ide_platform.c +++ b/drivers/ide/legacy/ide_platform.c @@ -30,14 +30,14 @@ static void __devinit plat_ide_setup_ports(hw_regs_t *hw, unsigned long port = (unsigned long)base; int i; - hw->io_ports[IDE_DATA_OFFSET] = port; + hw->io_ports.data_addr = port; port += (1 << pdata->ioport_shift); - for (i = IDE_ERROR_OFFSET; i <= IDE_STATUS_OFFSET; + for (i = 1; i <= 7; i++, port += (1 << pdata->ioport_shift)) - hw->io_ports[i] = port; + hw->io_ports_array[i] = port; - hw->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl; + hw->io_ports.ctl_addr = (unsigned long)ctrl; hw->irq = irq; @@ -101,8 +101,10 @@ static int __devinit plat_ide_probe(struct platform_device *pdev) ide_init_port_hw(hwif, &hw); - if (mmio) + if (mmio) { + hwif->host_flags = IDE_HFLAG_MMIO; default_hwif_mmiops(hwif); + } idx[0] = hwif->index; @@ -120,7 +122,7 @@ static int __devexit plat_ide_remove(struct platform_device *pdev) { ide_hwif_t *hwif = pdev->dev.driver_data; - ide_unregister(hwif->index); + ide_unregister(hwif); return 0; } diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c index 26546d0afc7f..1f527bbf8d96 100644 --- a/drivers/ide/legacy/macide.c +++ b/drivers/ide/legacy/macide.c @@ -72,9 +72,9 @@ static void __init macide_setup_ports(hw_regs_t *hw, unsigned long base, memset(hw, 0, sizeof(*hw)); for (i = 0; i < 8; i++) - hw->io_ports[i] = base + i * 4; + hw->io_ports_array[i] = base + i * 4; - hw->io_ports[IDE_CONTROL_OFFSET] = base + IDE_CONTROL; + hw->io_ports.ctl_addr = base + IDE_CONTROL; hw->irq = irq; hw->ack_intr = ack_intr; diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c index f23999dd3d46..6f535d00e638 100644 --- a/drivers/ide/legacy/q40ide.c +++ b/drivers/ide/legacy/q40ide.c @@ -36,23 +36,6 @@ static const unsigned long pcide_bases[Q40IDE_NUM_HWIFS] = { PCIDE_BASE6 */ }; - - /* - * Offsets from one of the above bases - */ - -/* used to do addr translation here but it is easier to do in setup ports */ -/*#define IDE_OFF_B(x) ((unsigned long)Q40_ISA_IO_B((IDE_##x##_OFFSET)))*/ - -#define IDE_OFF_B(x) ((unsigned long)((IDE_##x##_OFFSET))) -#define IDE_OFF_W(x) ((unsigned long)((IDE_##x##_OFFSET))) - -static const int pcide_offsets[IDE_NR_PORTS] = { - IDE_OFF_W(DATA), IDE_OFF_B(ERROR), IDE_OFF_B(NSECTOR), IDE_OFF_B(SECTOR), - IDE_OFF_B(LCYL), IDE_OFF_B(HCYL), 6 /*IDE_OFF_B(CURRENT)*/, IDE_OFF_B(STATUS), - 518/*IDE_OFF(CMD)*/ -}; - static int q40ide_default_irq(unsigned long base) { switch (base) { @@ -68,29 +51,48 @@ static int q40ide_default_irq(unsigned long base) /* * Addresses are pretranslated for Q40 ISA access. */ -void q40_ide_setup_ports ( hw_regs_t *hw, - unsigned long base, int *offsets, - unsigned long ctrl, unsigned long intr, +static void q40_ide_setup_ports(hw_regs_t *hw, unsigned long base, ide_ack_intr_t *ack_intr, int irq) { - int i; - memset(hw, 0, sizeof(hw_regs_t)); - for (i = 0; i < IDE_NR_PORTS; i++) { - /* BIG FAT WARNING: - assumption: only DATA port is ever used in 16 bit mode */ - if ( i==0 ) - hw->io_ports[i] = Q40_ISA_IO_W(base + offsets[i]); - else - hw->io_ports[i] = Q40_ISA_IO_B(base + offsets[i]); - } + /* BIG FAT WARNING: + assumption: only DATA port is ever used in 16 bit mode */ + hw->io_ports.data_addr = Q40_ISA_IO_W(base); + hw->io_ports.error_addr = Q40_ISA_IO_B(base + 1); + hw->io_ports.nsect_addr = Q40_ISA_IO_B(base + 2); + hw->io_ports.lbal_addr = Q40_ISA_IO_B(base + 3); + hw->io_ports.lbam_addr = Q40_ISA_IO_B(base + 4); + hw->io_ports.lbah_addr = Q40_ISA_IO_B(base + 5); + hw->io_ports.device_addr = Q40_ISA_IO_B(base + 6); + hw->io_ports.status_addr = Q40_ISA_IO_B(base + 7); + hw->io_ports.ctl_addr = Q40_ISA_IO_B(base + 0x206); hw->irq = irq; hw->ack_intr = ack_intr; } +static void q40ide_input_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + unsigned long data_addr = drive->hwif->io_ports.data_addr; + + if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS) + return insw(data_addr, buf, (len + 1) / 2); + insw_swapw(data_addr, buf, (len + 1) / 2); +} + +static void q40ide_output_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + unsigned long data_addr = drive->hwif->io_ports.data_addr; + + if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS) + return outsw(data_addr, buf, (len + 1) / 2); + + outsw_swapw(data_addr, buf, (len + 1) / 2); +} /* * the static array is needed to have the name reported in /proc/ioports, @@ -131,9 +133,8 @@ static int __init q40ide_init(void) release_region(pcide_bases[i], 8); continue; } - q40_ide_setup_ports(&hw,(unsigned long) pcide_bases[i], (int *)pcide_offsets, - pcide_bases[i]+0x206, - 0, NULL, + q40_ide_setup_ports(&hw, pcide_bases[i], + NULL, // m68kide_iops, q40ide_default_irq(pcide_bases[i])); @@ -142,6 +143,10 @@ static int __init q40ide_init(void) ide_init_port_data(hwif, hwif->index); ide_init_port_hw(hwif, &hw); + /* Q40 has a byte-swapped IDE interface */ + hwif->input_data = q40ide_input_data; + hwif->output_data = q40ide_output_data; + idx[i] = hwif->index; } } diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c index 15a99aae0cf9..6424af154325 100644 --- a/drivers/ide/legacy/qd65xx.c +++ b/drivers/ide/legacy/qd65xx.c @@ -11,11 +11,7 @@ * * QDI QD6500/QD6580 EIDE controller fast support * - * Please set local bus speed using kernel parameter idebus - * for example, "idebus=33" stands for 33Mhz VLbus * To activate controller support, use "ide0=qd65xx" - * To enable tuning, use "hda=autotune hdb=autotune" - * To enable 2nd channel tuning (qd6580 only), use "hdc=autotune hdd=autotune" */ /* @@ -114,17 +110,18 @@ static void qd65xx_select(ide_drive_t *drive) static u8 qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery_time) { - u8 active_cycle,recovery_cycle; + int clk = ide_vlb_clk ? ide_vlb_clk : system_bus_clock(); + u8 act_cyc, rec_cyc; - if (system_bus_clock()<=33) { - active_cycle = 9 - IDE_IN(active_time * system_bus_clock() / 1000 + 1, 2, 9); - recovery_cycle = 15 - IDE_IN(recovery_time * system_bus_clock() / 1000 + 1, 0, 15); + if (clk <= 33) { + act_cyc = 9 - IDE_IN(active_time * clk / 1000 + 1, 2, 9); + rec_cyc = 15 - IDE_IN(recovery_time * clk / 1000 + 1, 0, 15); } else { - active_cycle = 8 - IDE_IN(active_time * system_bus_clock() / 1000 + 1, 1, 8); - recovery_cycle = 18 - IDE_IN(recovery_time * system_bus_clock() / 1000 + 1, 3, 18); + act_cyc = 8 - IDE_IN(active_time * clk / 1000 + 1, 1, 8); + rec_cyc = 18 - IDE_IN(recovery_time * clk / 1000 + 1, 3, 18); } - return((recovery_cycle<<4) | 0x08 | active_cycle); + return (rec_cyc << 4) | 0x08 | act_cyc; } /* @@ -135,10 +132,13 @@ static u8 qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery static u8 qd6580_compute_timing (int active_time, int recovery_time) { - u8 active_cycle = 17 - IDE_IN(active_time * system_bus_clock() / 1000 + 1, 2, 17); - u8 recovery_cycle = 15 - IDE_IN(recovery_time * system_bus_clock() / 1000 + 1, 2, 15); + int clk = ide_vlb_clk ? ide_vlb_clk : system_bus_clock(); + u8 act_cyc, rec_cyc; - return((recovery_cycle<<4) | active_cycle); + act_cyc = 17 - IDE_IN(active_time * clk / 1000 + 1, 2, 17); + rec_cyc = 15 - IDE_IN(recovery_time * clk / 1000 + 1, 2, 15); + + return (rec_cyc << 4) | act_cyc; } /* @@ -322,8 +322,7 @@ static const struct ide_port_info qd65xx_port_info __initdata = { .name = DRV_NAME, .chipset = ide_qd65xx, .host_flags = IDE_HFLAG_IO_32BIT | - IDE_HFLAG_NO_DMA | - IDE_HFLAG_NO_AUTOTUNE, + IDE_HFLAG_NO_DMA, .pio_mask = ATA_PIO4, }; @@ -399,7 +398,7 @@ static int __init qd_probe(int base) return rc; } -int probe_qd65xx = 0; +static int probe_qd65xx; module_param_named(probe, probe_qd65xx, bool, 0); MODULE_PARM_DESC(probe, "probe for QD65xx chipsets"); diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c index 17d515329fe0..b54a14a57755 100644 --- a/drivers/ide/legacy/umc8672.c +++ b/drivers/ide/legacy/umc8672.c @@ -130,7 +130,7 @@ static const struct ide_port_info umc8672_port_info __initdata = { .name = DRV_NAME, .chipset = ide_umc8672, .port_ops = &umc8672_port_ops, - .host_flags = IDE_HFLAG_NO_DMA | IDE_HFLAG_NO_AUTOTUNE, + .host_flags = IDE_HFLAG_NO_DMA, .pio_mask = ATA_PIO4, }; @@ -158,7 +158,7 @@ static int __init umc8672_probe(void) return ide_legacy_device_add(&umc8672_port_info, 0); } -int probe_umc8672; +static int probe_umc8672; module_param_named(probe, probe_umc8672, bool, 0); MODULE_PARM_DESC(probe, "probe for UMC8672 chipset"); diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c index 3485a310c95b..1a6c27b32498 100644 --- a/drivers/ide/mips/au1xxx-ide.c +++ b/drivers/ide/mips/au1xxx-ide.c @@ -48,8 +48,6 @@ static _auide_hwif auide_hwif; -static int auide_ddma_init(_auide_hwif *auide); - #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA) void auide_insw(unsigned long port, void *addr, u32 count) @@ -88,6 +86,17 @@ void auide_outsw(unsigned long port, void *addr, u32 count) ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp); } +static void au1xxx_input_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + auide_insw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2); +} + +static void au1xxx_output_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + auide_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2); +} #endif static void au1xxx_set_pio_mode(ide_drive_t *drive, const u8 pio) @@ -359,7 +368,7 @@ static void auide_ddma_rx_callback(int irq, void *param) static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize, u32 devwidth, u32 flags) { dev->dev_id = dev_id; - dev->dev_physaddr = (u32)AU1XXX_ATA_PHYS_ADDR; + dev->dev_physaddr = (u32)IDE_PHYS_ADDR; dev->dev_intlevel = 0; dev->dev_intpolarity = 0; dev->dev_tsize = tsize; @@ -397,7 +406,7 @@ static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d) dbdev_tab_t source_dev_tab, target_dev_tab; u32 dev_id, tsize, devwidth, flags; - dev_id = AU1XXX_ATA_DDMA_REQ; + dev_id = IDE_DDMA_REQ; tsize = 8; /* 1 */ devwidth = 32; /* 16 */ @@ -502,15 +511,14 @@ static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d) static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif) { int i; - unsigned long *ata_regs = hw->io_ports; + unsigned long *ata_regs = hw->io_ports_array; /* FIXME? */ - for (i = 0; i < IDE_CONTROL_OFFSET; i++) { - *ata_regs++ = ahwif->regbase + (i << AU1XXX_ATA_REG_OFFSET); - } + for (i = 0; i < 8; i++) + *ata_regs++ = ahwif->regbase + (i << IDE_REG_SHIFT); /* set the Alternative Status register */ - *ata_regs = ahwif->regbase + (14 << AU1XXX_ATA_REG_OFFSET); + *ata_regs = ahwif->regbase + (14 << IDE_REG_SHIFT); } static const struct ide_port_ops au1xxx_port_ops = { @@ -599,8 +607,8 @@ static int au_ide_probe(struct device *dev) */ #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA - hwif->INSW = auide_insw; - hwif->OUTSW = auide_outsw; + hwif->input_data = au1xxx_input_data; + hwif->output_data = au1xxx_output_data; #endif hwif->select_data = 0; /* no chipset-specific code */ hwif->config_data = 0; /* no chipset-specific code */ @@ -627,7 +635,7 @@ static int au_ide_remove(struct device *dev) ide_hwif_t *hwif = dev_get_drvdata(dev); _auide_hwif *ahwif = &auide_hwif; - ide_unregister(hwif->index); + ide_unregister(hwif); iounmap((void *)ahwif->regbase); diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c index 112fe566bb93..712d17bdd470 100644 --- a/drivers/ide/mips/swarm.c +++ b/drivers/ide/mips/swarm.c @@ -109,14 +109,15 @@ static int __devinit swarm_ide_probe(struct device *dev) base = ioremap(offset, size); /* Setup MMIO ops. */ + hwif->host_flags = IDE_HFLAG_MMIO; default_hwif_mmiops(hwif); hwif->chipset = ide_generic; - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) - hwif->io_ports[i] = + for (i = 0; i <= 7; i++) + hwif->io_ports_array[i] = (unsigned long)(base + ((0x1f0 + i) << 5)); - hwif->io_ports[IDE_CONTROL_OFFSET] = + hwif->io_ports.ctl_addr = (unsigned long)(base + (0x3f6 << 5)); hwif->irq = K_INT_GB_IDE; diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c index ca16f37f9486..7f46c224b7c4 100644 --- a/drivers/ide/pci/aec62xx.c +++ b/drivers/ide/pci/aec62xx.c @@ -140,7 +140,7 @@ static void aec_set_pio_mode(ide_drive_t *drive, const u8 pio) static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const char *name) { - int bus_speed = system_bus_clock(); + int bus_speed = ide_pci_clk ? ide_pci_clk : system_bus_clock(); if (bus_speed <= 33) pci_set_drvdata(dev, (void *) aec6xxx_33_base); diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index b5a3bc33e167..c1922f9cfe80 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -38,8 +38,6 @@ #include <asm/io.h> -#define DISPLAY_ALI_TIMINGS - /* * ALi devices are not plug in. Otherwise these static values would * need to go. They ought to go away anyway @@ -49,236 +47,6 @@ static u8 m5229_revision; static u8 chip_is_1543c_e; static struct pci_dev *isa_dev; -#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) -#include <linux/stat.h> -#include <linux/proc_fs.h> - -static u8 ali_proc = 0; - -static struct pci_dev *bmide_dev; - -static char *fifo[4] = { - "FIFO Off", - "FIFO On ", - "DMA mode", - "PIO mode" }; - -static char *udmaT[8] = { - "1.5T", - " 2T", - "2.5T", - " 3T", - "3.5T", - " 4T", - " 6T", - " 8T" -}; - -static char *channel_status[8] = { - "OK ", - "busy ", - "DRQ ", - "DRQ busy ", - "error ", - "error busy ", - "error DRQ ", - "error DRQ busy" -}; - -/** - * ali_get_info - generate proc file for ALi IDE - * @buffer: buffer to fill - * @addr: address of user start in buffer - * @offset: offset into 'file' - * @count: buffer count - * - * Walks the Ali devices and outputs summary data on the tuning and - * anything else that will help with debugging - */ - -static int ali_get_info (char *buffer, char **addr, off_t offset, int count) -{ - unsigned long bibma; - u8 reg53h, reg5xh, reg5yh, reg5xh1, reg5yh1, c0, c1, rev, tmp; - char *q, *p = buffer; - - /* fetch rev. */ - pci_read_config_byte(bmide_dev, 0x08, &rev); - if (rev >= 0xc1) /* M1543C or newer */ - udmaT[7] = " ???"; - else - fifo[3] = " ??? "; - - /* first fetch bibma: */ - - bibma = pci_resource_start(bmide_dev, 4); - - /* - * at that point bibma+0x2 et bibma+0xa are byte - * registers to investigate: - */ - c0 = inb(bibma + 0x02); - c1 = inb(bibma + 0x0a); - - p += sprintf(p, - "\n Ali M15x3 Chipset.\n"); - p += sprintf(p, - " ------------------\n"); - pci_read_config_byte(bmide_dev, 0x78, ®53h); - p += sprintf(p, "PCI Clock: %d.\n", reg53h); - - pci_read_config_byte(bmide_dev, 0x53, ®53h); - p += sprintf(p, - "CD_ROM FIFO:%s, CD_ROM DMA:%s\n", - (reg53h & 0x02) ? "Yes" : "No ", - (reg53h & 0x01) ? "Yes" : "No " ); - pci_read_config_byte(bmide_dev, 0x74, ®53h); - p += sprintf(p, - "FIFO Status: contains %d Words, runs%s%s\n\n", - (reg53h & 0x3f), - (reg53h & 0x40) ? " OVERWR" : "", - (reg53h & 0x80) ? " OVERRD." : "." ); - - p += sprintf(p, - "-------------------primary channel" - "-------------------secondary channel" - "---------\n\n"); - - pci_read_config_byte(bmide_dev, 0x09, ®53h); - p += sprintf(p, - "channel status: %s" - " %s\n", - (reg53h & 0x20) ? "On " : "Off", - (reg53h & 0x10) ? "On " : "Off" ); - - p += sprintf(p, - "both channels togth: %s" - " %s\n", - (c0&0x80) ? "No " : "Yes", - (c1&0x80) ? "No " : "Yes" ); - - pci_read_config_byte(bmide_dev, 0x76, ®53h); - p += sprintf(p, - "Channel state: %s %s\n", - channel_status[reg53h & 0x07], - channel_status[(reg53h & 0x70) >> 4] ); - - pci_read_config_byte(bmide_dev, 0x58, ®5xh); - pci_read_config_byte(bmide_dev, 0x5c, ®5yh); - p += sprintf(p, - "Add. Setup Timing: %dT" - " %dT\n", - (reg5xh & 0x07) ? (reg5xh & 0x07) : 8, - (reg5yh & 0x07) ? (reg5yh & 0x07) : 8 ); - - pci_read_config_byte(bmide_dev, 0x59, ®5xh); - pci_read_config_byte(bmide_dev, 0x5d, ®5yh); - p += sprintf(p, - "Command Act. Count: %dT" - " %dT\n" - "Command Rec. Count: %dT" - " %dT\n\n", - (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8, - (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8, - (reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16, - (reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16 ); - - p += sprintf(p, - "----------------drive0-----------drive1" - "------------drive0-----------drive1------\n\n"); - p += sprintf(p, - "DMA enabled: %s %s" - " %s %s\n", - (c0&0x20) ? "Yes" : "No ", - (c0&0x40) ? "Yes" : "No ", - (c1&0x20) ? "Yes" : "No ", - (c1&0x40) ? "Yes" : "No " ); - - pci_read_config_byte(bmide_dev, 0x54, ®5xh); - pci_read_config_byte(bmide_dev, 0x55, ®5yh); - q = "FIFO threshold: %2d Words %2d Words" - " %2d Words %2d Words\n"; - if (rev < 0xc1) { - if ((rev == 0x20) && - (pci_read_config_byte(bmide_dev, 0x4f, &tmp), (tmp &= 0x20))) { - p += sprintf(p, q, 8, 8, 8, 8); - } else { - p += sprintf(p, q, - (reg5xh & 0x03) + 12, - ((reg5xh & 0x30)>>4) + 12, - (reg5yh & 0x03) + 12, - ((reg5yh & 0x30)>>4) + 12 ); - } - } else { - int t1 = (tmp = (reg5xh & 0x03)) ? (tmp << 3) : 4; - int t2 = (tmp = ((reg5xh & 0x30)>>4)) ? (tmp << 3) : 4; - int t3 = (tmp = (reg5yh & 0x03)) ? (tmp << 3) : 4; - int t4 = (tmp = ((reg5yh & 0x30)>>4)) ? (tmp << 3) : 4; - p += sprintf(p, q, t1, t2, t3, t4); - } - -#if 0 - p += sprintf(p, - "FIFO threshold: %2d Words %2d Words" - " %2d Words %2d Words\n", - (reg5xh & 0x03) + 12, - ((reg5xh & 0x30)>>4) + 12, - (reg5yh & 0x03) + 12, - ((reg5yh & 0x30)>>4) + 12 ); -#endif - - p += sprintf(p, - "FIFO mode: %s %s %s %s\n", - fifo[((reg5xh & 0x0c) >> 2)], - fifo[((reg5xh & 0xc0) >> 6)], - fifo[((reg5yh & 0x0c) >> 2)], - fifo[((reg5yh & 0xc0) >> 6)] ); - - pci_read_config_byte(bmide_dev, 0x5a, ®5xh); - pci_read_config_byte(bmide_dev, 0x5b, ®5xh1); - pci_read_config_byte(bmide_dev, 0x5e, ®5yh); - pci_read_config_byte(bmide_dev, 0x5f, ®5yh1); - - p += sprintf(p,/* - "------------------drive0-----------drive1" - "------------drive0-----------drive1------\n")*/ - "Dt RW act. Cnt %2dT %2dT" - " %2dT %2dT\n" - "Dt RW rec. Cnt %2dT %2dT" - " %2dT %2dT\n\n", - (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8, - (reg5xh1 & 0x70) ? ((reg5xh1 & 0x70) >> 4) : 8, - (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8, - (reg5yh1 & 0x70) ? ((reg5yh1 & 0x70) >> 4) : 8, - (reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16, - (reg5xh1 & 0x0f) ? (reg5xh1 & 0x0f) : 16, - (reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16, - (reg5yh1 & 0x0f) ? (reg5yh1 & 0x0f) : 16 ); - - p += sprintf(p, - "-----------------------------------UDMA Timings" - "--------------------------------\n\n"); - - pci_read_config_byte(bmide_dev, 0x56, ®5xh); - pci_read_config_byte(bmide_dev, 0x57, ®5yh); - p += sprintf(p, - "UDMA: %s %s" - " %s %s\n" - "UDMA timings: %s %s" - " %s %s\n\n", - (reg5xh & 0x08) ? "OK" : "No", - (reg5xh & 0x80) ? "OK" : "No", - (reg5yh & 0x08) ? "OK" : "No", - (reg5yh & 0x80) ? "OK" : "No", - udmaT[(reg5xh & 0x07)], - udmaT[(reg5xh & 0x70) >> 4], - udmaT[reg5yh & 0x07], - udmaT[(reg5yh & 0x70) >> 4] ); - - return p-buffer; /* => must be less than 4k! */ -} -#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */ - /** * ali_set_pio_mode - set host controller for PIO mode * @drive: drive @@ -294,7 +62,7 @@ static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio) int s_time, a_time, c_time; u8 s_clc, a_clc, r_clc; unsigned long flags; - int bus_speed = system_bus_clock(); + int bus_speed = ide_pci_clk ? ide_pci_clk : system_bus_clock(); int port = hwif->channel ? 0x5c : 0x58; int portFIFO = hwif->channel ? 0x55 : 0x54; u8 cd_dma_fifo = 0; @@ -465,14 +233,6 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); -#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) - if (!ali_proc) { - ali_proc = 1; - bmide_dev = dev; - ide_pci_create_host_proc("ali", ali_get_info); - } -#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */ - local_irq_save(flags); if (m5229_revision < 0xC2) { @@ -652,14 +412,14 @@ static u8 __devinit ali_cable_detect(ide_hwif_t *hwif) return cbl; } -#ifndef CONFIG_SPARC64 +#if !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC) /** * init_hwif_ali15x3 - Initialize the ALI IDE x86 stuff * @hwif: interface to configure * * Obtain the IRQ tables for an ALi based IDE solution on the PC * class platforms. This part of the code isn't applicable to the - * Sparc systems + * Sparc and PowerPC systems. */ static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif) @@ -703,7 +463,9 @@ static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif) hwif->irq = irq; } } -#endif +#else +#define init_hwif_ali15x3 NULL +#endif /* !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC) */ /** * init_dma_ali15x3 - set up DMA on ALi15x3 @@ -757,9 +519,7 @@ static const struct ide_dma_ops ali_dma_ops = { static const struct ide_port_info ali15x3_chipset __devinitdata = { .name = "ALI15X3", .init_chipset = init_chipset_ali15x3, -#ifndef CONFIG_SPARC64 .init_hwif = init_hwif_ali15x3, -#endif .init_dma = init_dma_ali15x3, .port_ops = &ali_port_ops, .pio_mask = ATA_PIO5, diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c index f7c883808b02..efcf54338be7 100644 --- a/drivers/ide/pci/amd74xx.c +++ b/drivers/ide/pci/amd74xx.c @@ -179,7 +179,7 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, * Determine the system bus clock. */ - amd_clock = system_bus_clock() * 1000; + amd_clock = (ide_pci_clk ? ide_pci_clk : system_bus_clock()) * 1000; switch (amd_clock) { case 33000: amd_clock = 33333; break; diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c index 25c2f1bd175f..aaf38109eaec 100644 --- a/drivers/ide/pci/cmd640.c +++ b/drivers/ide/pci/cmd640.c @@ -111,10 +111,7 @@ #define DRV_NAME "cmd640" -/* - * This flag is set in ide.c by the parameter: ide0=cmd640_vlb - */ -int cmd640_vlb; +static int cmd640_vlb; /* * CMD640 specific registers definition. @@ -350,12 +347,12 @@ static int __init secondary_port_responding(void) spin_lock_irqsave(&cmd640_lock, flags); - outb_p(0x0a, 0x170 + IDE_SELECT_OFFSET); /* select drive0 */ + outb_p(0x0a, 0x176); /* select drive0 */ udelay(100); - if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x0a) { - outb_p(0x1a, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */ + if ((inb_p(0x176) & 0x1f) != 0x0a) { + outb_p(0x1a, 0x176); /* select drive1 */ udelay(100); - if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x1a) { + if ((inb_p(0x176) & 0x1f) != 0x1a) { spin_unlock_irqrestore(&cmd640_lock, flags); return 0; /* nothing responded */ } @@ -383,6 +380,7 @@ static void cmd640_dump_regs(void) } #endif +#ifndef CONFIG_BLK_DEV_CMD640_ENHANCED /* * Check whether prefetch is on for a drive, * and initialize the unmask flags for safe operation. @@ -403,9 +401,7 @@ static void __init check_prefetch(ide_drive_t *drive, unsigned int index) drive->no_io_32bit = 0; } } - -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - +#else /* * Sets prefetch mode for a drive. */ @@ -462,34 +458,6 @@ static inline u8 pack_nibbles(u8 upper, u8 lower) } /* - * This routine retrieves the initial drive timings from the chipset. - */ -static void __init retrieve_drive_counts(unsigned int index) -{ - u8 b; - - /* - * Get the internal setup timing, and convert to clock count - */ - b = get_cmd640_reg(arttim_regs[index]) & ~0x3f; - switch (b) { - case 0x00: b = 4; break; - case 0x80: b = 3; break; - case 0x40: b = 2; break; - default: b = 5; break; - } - setup_counts[index] = b; - - /* - * Get the active/recovery counts - */ - b = get_cmd640_reg(drwtim_regs[index]); - active_counts[index] = (b >> 4) ? (b >> 4) : 0x10; - recovery_counts[index] = (b & 0x0f) ? (b & 0x0f) : 0x10; -} - - -/* * This routine writes the prepared setup/active/recovery counts * for a drive into the cmd640 chipset registers to active them. */ @@ -555,7 +523,14 @@ static void cmd640_set_mode(ide_drive_t *drive, unsigned int index, { int setup_time, active_time, recovery_time, clock_time; u8 setup_count, active_count, recovery_count, recovery_count2, cycle_count; - int bus_speed = system_bus_clock(); + int bus_speed; + + if (cmd640_vlb && ide_vlb_clk) + bus_speed = ide_vlb_clk; + else if (!cmd640_vlb && ide_pci_clk) + bus_speed = ide_pci_clk; + else + bus_speed = system_bus_clock(); if (pio_mode > 5) pio_mode = 5; @@ -679,7 +654,6 @@ static const struct ide_port_info cmd640_port_info __initdata = { .chipset = ide_cmd640, .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA | - IDE_HFLAG_NO_AUTOTUNE | IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_ABUSE_FAST_DEVSEL, #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED @@ -862,29 +836,16 @@ static int __init cmd640x_init(void) } #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - if (drive->autotune || ((index > 1) && second_port_toggled)) { - /* - * Reset timing to the slowest speed and turn off - * prefetch. This way, the drive identify code has - * a better chance. - */ - setup_counts [index] = 4; /* max possible */ - active_counts [index] = 16; /* max possible */ - recovery_counts [index] = 16; /* max possible */ - program_drive_counts(drive, index); - set_prefetch_mode(drive, index, 0); - printk("cmd640: drive%d timings/prefetch cleared\n", index); - } else { - /* - * Record timings/prefetch without changing them. - * This preserves any prior BIOS setup. - */ - retrieve_drive_counts (index); - check_prefetch(drive, index); - printk("cmd640: drive%d timings/prefetch(%s) preserved", - index, drive->no_io_32bit ? "off" : "on"); - display_clocks(index); - } + /* + * Reset timing to the slowest speed and turn off prefetch. + * This way, the drive identify code has a better chance. + */ + setup_counts [index] = 4; /* max possible */ + active_counts [index] = 16; /* max possible */ + recovery_counts [index] = 16; /* max possible */ + program_drive_counts(drive, index); + set_prefetch_mode(drive, index, 0); + printk("cmd640: drive%d timings/prefetch cleared\n", index); #else /* * Set the drive unmask flags to match the prefetch setting diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c index 006fb62656bc..08674711d089 100644 --- a/drivers/ide/pci/cmd64x.c +++ b/drivers/ide/pci/cmd64x.c @@ -68,8 +68,8 @@ static u8 quantize_timing(int timing, int quant) */ static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_time) { - struct pci_dev *dev = to_pci_dev(drive->hwif->dev); - int clock_time = 1000 / system_bus_clock(); + struct pci_dev *dev = to_pci_dev(drive->hwif->dev); + int clock_time = 1000 / (ide_pci_clk ? ide_pci_clk : system_bus_clock()); u8 cycle_count, active_count, recovery_count, drwtim; static const u8 recovery_values[] = {15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0}; @@ -128,7 +128,7 @@ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio) ide_pio_timings[pio].active_time); setup_count = quantize_timing(ide_pio_timings[pio].setup_time, - 1000 / system_bus_clock()); + 1000 / (ide_pci_clk ? ide_pci_clk : system_bus_clock())); /* * The primary channel has individual address setup timing registers diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c index e30eae5a01b6..77cc22c2ad45 100644 --- a/drivers/ide/pci/cy82c693.c +++ b/drivers/ide/pci/cy82c693.c @@ -18,8 +18,6 @@ * hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA * - this is my first linux driver, so there's probably a lot of room * for optimizations and bug fixing, so feel free to do it. - * - use idebus=xx parameter to set PCI bus speed - needed to calc - * timings for PIO modes (default will be 40) * - if using PIO mode it's a good idea to set the PIO mode and * 32-bit I/O support (if possible), e.g. hdparm -p2 -c1 /dev/hda * - I had some problems with my IBM DHEA with PIO modes < 2 @@ -136,7 +134,7 @@ static int calc_clk(int time, int bus_speed) static void compute_clocks(u8 pio, pio_clocks_t *p_pclk) { int clk1, clk2; - int bus_speed = system_bus_clock(); /* get speed of PCI bus */ + int bus_speed = ide_pci_clk ? ide_pci_clk : system_bus_clock(); /* we don't check against CY82C693's min and max speed, * so you can play with the idebus=xx parameter diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c index c7b7e0483287..b9e457996d0e 100644 --- a/drivers/ide/pci/delkin_cb.c +++ b/drivers/ide/pci/delkin_cb.c @@ -87,11 +87,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) i = hwif->index; - if (hwif->present) - ide_unregister(i); - else - ide_init_port_data(hwif, i); - + ide_init_port_data(hwif, i); ide_init_port_hw(hwif, &hw); hwif->port_ops = &delkin_cb_port_ops; @@ -123,8 +119,7 @@ delkin_cb_remove (struct pci_dev *dev) { ide_hwif_t *hwif = pci_get_drvdata(dev); - if (hwif) - ide_unregister(hwif->index); + ide_unregister(hwif); pci_release_regions(dev); pci_disable_device(dev); diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 8c02961d0188..c929dadaaaff 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -760,7 +760,7 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask) } } else outb(mask ? (drive->ctl | 2) : (drive->ctl & ~2), - hwif->io_ports[IDE_CONTROL_OFFSET]); + hwif->io_ports.ctl_addr); } /* diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c index e1b0c9a9ab9c..fec4955f449b 100644 --- a/drivers/ide/pci/ns87415.c +++ b/drivers/ide/pci/ns87415.c @@ -63,6 +63,48 @@ static u8 superio_ide_inb (unsigned long port) return inb(port); } +static void superio_tf_read(ide_drive_t *drive, ide_task_t *task) +{ + struct ide_io_ports *io_ports = &drive->hwif->io_ports; + struct ide_taskfile *tf = &task->tf; + + if (task->tf_flags & IDE_TFLAG_IN_DATA) { + u16 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 */ + outb(drive->ctl & ~0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_NSECT) + tf->nsect = inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAL) + tf->lbal = inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAM) + tf->lbam = inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAH) + tf->lbah = inb(io_ports->lbah_addr); + if (task->tf_flags & IDE_TFLAG_IN_DEVICE) + tf->device = superio_ide_inb(io_ports->device_addr); + + if (task->tf_flags & IDE_TFLAG_LBA48) { + outb(drive->ctl | 0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) + tf->hob_feature = inb(io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) + tf->hob_nsect = inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) + tf->hob_lbal = inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) + tf->hob_lbam = inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) + tf->hob_lbah = inb(io_ports->lbah_addr); + } +} + static void __devinit superio_ide_init_iops (struct hwif_s *hwif) { struct pci_dev *pdev = to_pci_dev(hwif->dev); @@ -72,14 +114,16 @@ static void __devinit superio_ide_init_iops (struct hwif_s *hwif) base = pci_resource_start(pdev, port * 2) & ~3; dmabase = pci_resource_start(pdev, 4) & ~3; - superio_ide_status[port] = base + IDE_STATUS_OFFSET; - superio_ide_select[port] = base + IDE_SELECT_OFFSET; + superio_ide_status[port] = base + 7; + superio_ide_select[port] = base + 6; superio_ide_dma_status[port] = dmabase + (!port ? 2 : 0xa); /* Clear error/interrupt, enable dma */ tmp = superio_ide_inb(superio_ide_dma_status[port]); outb(tmp | 0x66, superio_ide_dma_status[port]); + hwif->tf_read = superio_tf_read; + /* We need to override inb to workaround a SuperIO errata */ hwif->INB = superio_ide_inb; } @@ -231,12 +275,12 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) * SELECT_DRIVE() properly during first ide_probe_port(). */ timeout = 10000; - outb(12, hwif->io_ports[IDE_CONTROL_OFFSET]); + outb(12, hwif->io_ports.ctl_addr); udelay(10); - outb(8, hwif->io_ports[IDE_CONTROL_OFFSET]); + outb(8, hwif->io_ports.ctl_addr); do { udelay(50); - stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); + stat = hwif->INB(hwif->io_ports.status_addr); if (stat == 0xff) break; } while ((stat & BUSY_STAT) && --timeout); @@ -244,7 +288,7 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) } if (!using_inta) - hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]); + hwif->irq = ide_default_irq(hwif->io_ports.data_addr); else if (!hwif->irq && hwif->mate && hwif->mate->irq) hwif->irq = hwif->mate->irq; /* share IRQ with mate */ diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c index 9edacba20ffb..6e99080497bf 100644 --- a/drivers/ide/pci/opti621.c +++ b/drivers/ide/pci/opti621.c @@ -53,8 +53,7 @@ * If you then set the second drive to another PIO, the old value * (automatically selected) will be overrided by yours. * There is a 25/33MHz switch in configuration - * register, but driver is written for use at any frequency which get - * (use idebus=xx to select PCI bus speed). + * register, but driver is written for use at any frequency. * * Version 0.1, Nov 8, 1996 * by Jaromir Koutek, for 2.1.8. @@ -210,7 +209,7 @@ static void compute_clocks(int pio, pio_clocks_t *clks) { if (pio != PIO_NOT_EXIST) { int adr_setup, data_pls; - int bus_speed = system_bus_clock(); + int bus_speed = ide_pci_clk ? ide_pci_clk : system_bus_clock(); adr_setup = ide_pio_timings[pio].setup_time; data_pls = ide_pio_timings[pio].active_time; @@ -280,7 +279,7 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) spin_lock_irqsave(&opti621_lock, flags); - reg_base = hwif->io_ports[IDE_DATA_OFFSET]; + reg_base = hwif->io_ports.data_addr; /* allow Register-B */ outb(0xc0, reg_base + CNTRL_REG); diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index ec9bd7b352fc..070df8ab3b21 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -83,8 +83,8 @@ static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index) { u8 value; - outb(index, hwif->dma_vendor1); - value = inb(hwif->dma_vendor3); + outb(index, hwif->dma_base + 1); + value = inb(hwif->dma_base + 3); DBG("index[%02X] value[%02X]\n", index, value); return value; @@ -97,8 +97,8 @@ static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index) */ static void set_indexed_reg(ide_hwif_t *hwif, u8 index, u8 value) { - outb(index, hwif->dma_vendor1); - outb(value, hwif->dma_vendor3); + outb(index, hwif->dma_base + 1); + outb(value, hwif->dma_base + 3); DBG("index[%02X] value[%02X]\n", index, value); } diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index 21c5dd23f928..f04738d14a6f 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -250,6 +250,7 @@ static const struct ich_laptop ich_laptop[] = { { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */ { 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */ { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on Acer Aspire 2023WLMi */ + { 0x2653, 0x1043, 0x82D8 }, /* ICH6M on Asus Eee 701 */ /* end marker */ { 0, } }; diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c index 17cf86490d59..910fb00deb71 100644 --- a/drivers/ide/pci/scc_pata.c +++ b/drivers/ide/pci/scc_pata.c @@ -126,12 +126,6 @@ static u8 scc_ide_inb(unsigned long port) return (u8)data; } -static u16 scc_ide_inw(unsigned long port) -{ - u32 data = in_be32((void*)port); - return (u16)data; -} - static void scc_ide_insw(unsigned long port, void *addr, u32 count) { u16 *ptr = (u16 *)addr; @@ -154,11 +148,6 @@ static void scc_ide_outb(u8 addr, unsigned long port) out_be32((void*)port, addr); } -static void scc_ide_outw(u16 addr, unsigned long port) -{ - out_be32((void*)port, addr); -} - static void scc_ide_outbsync(ide_drive_t * drive, u8 addr, unsigned long port) { @@ -271,6 +260,20 @@ static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed) out_be32((void __iomem *)udenvt_port, reg); } +static void scc_dma_host_set(ide_drive_t *drive, int on) +{ + ide_hwif_t *hwif = drive->hwif; + u8 unit = (drive->select.b.unit & 0x01); + u8 dma_stat = scc_ide_inb(hwif->dma_status); + + if (on) + dma_stat |= (1 << (5 + unit)); + else + dma_stat &= ~(1 << (5 + unit)); + + scc_ide_outb(dma_stat, hwif->dma_status); +} + /** * scc_ide_dma_setup - begin a DMA phase * @drive: target device @@ -301,7 +304,7 @@ static int scc_dma_setup(ide_drive_t *drive) } /* PRD table */ - out_be32((void __iomem *)hwif->dma_prdtable, hwif->dmatable_dma); + out_be32((void __iomem *)(hwif->dma_base + 8), hwif->dmatable_dma); /* specify r/w */ out_be32((void __iomem *)hwif->dma_command, reading); @@ -315,13 +318,45 @@ static int scc_dma_setup(ide_drive_t *drive) return 0; } +static void scc_dma_start(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + u8 dma_cmd = scc_ide_inb(hwif->dma_command); + + /* start DMA */ + scc_ide_outb(dma_cmd | 1, hwif->dma_command); + hwif->dma = 1; + wmb(); +} + +static int __scc_dma_end(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + u8 dma_stat, dma_cmd; + + drive->waiting_for_dma = 0; + /* get DMA command mode */ + dma_cmd = scc_ide_inb(hwif->dma_command); + /* stop DMA */ + scc_ide_outb(dma_cmd & ~1, hwif->dma_command); + /* get DMA status */ + dma_stat = scc_ide_inb(hwif->dma_status); + /* clear the INTR & ERROR bits */ + scc_ide_outb(dma_stat | 6, hwif->dma_status); + /* purge DMA mappings */ + ide_destroy_dmatable(drive); + /* verify good DMA status */ + hwif->dma = 0; + wmb(); + return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; +} /** * scc_dma_end - Stop DMA * @drive: IDE drive * * Check and clear INT Status register. - * Then call __ide_dma_end(). + * Then call __scc_dma_end(). */ static int scc_dma_end(ide_drive_t *drive) @@ -334,7 +369,7 @@ static int scc_dma_end(ide_drive_t *drive) /* errata A308 workaround: Step5 (check data loss) */ /* We don't check non ide_disk because it is limited to UDMA4 */ - if (!(in_be32((void __iomem *)hwif->io_ports[IDE_ALTSTATUS_OFFSET]) + if (!(in_be32((void __iomem *)hwif->io_ports.ctl_addr) & ERR_STAT) && drive->media == ide_disk && drive->current_speed > XFER_UDMA_4) { reg = in_be32((void __iomem *)intsts_port); @@ -425,7 +460,7 @@ static int scc_dma_end(ide_drive_t *drive) break; } - dma_stat = __ide_dma_end(drive); + dma_stat = __scc_dma_end(drive); if (data_loss) dma_stat |= 2; /* emulate DMA error (to retry command) */ return dma_stat; @@ -438,7 +473,7 @@ static int scc_dma_test_irq(ide_drive_t *drive) u32 int_stat = in_be32((void __iomem *)hwif->dma_base + 0x014); /* SCC errata A252,A308 workaround: Step4 */ - if ((in_be32((void __iomem *)hwif->io_ports[IDE_ALTSTATUS_OFFSET]) + if ((in_be32((void __iomem *)hwif->io_ports.ctl_addr) & ERR_STAT) && (int_stat & INTSTS_INTRQ)) return 1; @@ -534,8 +569,8 @@ static int scc_ide_setup_pci_device(struct pci_dev *dev, } memset(&hw, 0, sizeof(hw)); - for (i = IDE_DATA_OFFSET; i <= IDE_CONTROL_OFFSET; i++) - hw.io_ports[i] = ports->dma + 0x20 + i * 4; + for (i = 0; i <= 8; i++) + hw.io_ports_array[i] = ports->dma + 0x20 + i * 4; hw.irq = dev->irq; hw.dev = &dev->dev; hw.chipset = ide_pci; @@ -618,6 +653,122 @@ static int __devinit init_setup_scc(struct pci_dev *dev, return rc; } +static void scc_tf_load(ide_drive_t *drive, ide_task_t *task) +{ + struct ide_io_ports *io_ports = &drive->hwif->io_ports; + struct ide_taskfile *tf = &task->tf; + u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; + + if (task->tf_flags & IDE_TFLAG_FLAGGED) + HIHI = 0xFF; + + ide_set_irq(drive, 1); + + if (task->tf_flags & IDE_TFLAG_OUT_DATA) + out_be32((void *)io_ports->data_addr, + (tf->hob_data << 8) | tf->data); + + if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) + scc_ide_outb(tf->hob_feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) + scc_ide_outb(tf->hob_nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) + scc_ide_outb(tf->hob_lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) + scc_ide_outb(tf->hob_lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) + scc_ide_outb(tf->hob_lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) + scc_ide_outb(tf->feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_NSECT) + scc_ide_outb(tf->nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAL) + scc_ide_outb(tf->lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAM) + scc_ide_outb(tf->lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAH) + scc_ide_outb(tf->lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) + scc_ide_outb((tf->device & HIHI) | drive->select.all, + io_ports->device_addr); +} + +static void scc_tf_read(ide_drive_t *drive, ide_task_t *task) +{ + struct ide_io_ports *io_ports = &drive->hwif->io_ports; + struct ide_taskfile *tf = &task->tf; + + if (task->tf_flags & IDE_TFLAG_IN_DATA) { + u16 data = (u16)in_be32((void *)io_ports->data_addr); + + tf->data = data & 0xff; + tf->hob_data = (data >> 8) & 0xff; + } + + /* be sure we're looking at the low order bits */ + scc_ide_outb(drive->ctl & ~0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_NSECT) + tf->nsect = scc_ide_inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAL) + tf->lbal = scc_ide_inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAM) + tf->lbam = scc_ide_inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAH) + tf->lbah = scc_ide_inb(io_ports->lbah_addr); + if (task->tf_flags & IDE_TFLAG_IN_DEVICE) + tf->device = scc_ide_inb(io_ports->device_addr); + + if (task->tf_flags & IDE_TFLAG_LBA48) { + scc_ide_outb(drive->ctl | 0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) + tf->hob_feature = scc_ide_inb(io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) + tf->hob_nsect = scc_ide_inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) + tf->hob_lbal = scc_ide_inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) + tf->hob_lbam = scc_ide_inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) + tf->hob_lbah = scc_ide_inb(io_ports->lbah_addr); + } +} + +static void scc_input_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + unsigned long data_addr = drive->hwif->io_ports.data_addr; + + len++; + + if (drive->io_32bit) { + scc_ide_insl(data_addr, buf, len / 4); + + if ((len & 3) >= 2) + scc_ide_insw(data_addr, (u8 *)buf + (len & ~3), 1); + } else + scc_ide_insw(data_addr, buf, len / 2); +} + +static void scc_output_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + unsigned long data_addr = drive->hwif->io_ports.data_addr; + + len++; + + if (drive->io_32bit) { + scc_ide_outsl(data_addr, buf, len / 4); + + if ((len & 3) >= 2) + scc_ide_outsw(data_addr, (u8 *)buf + (len & ~3), 1); + } else + scc_ide_outsw(data_addr, buf, len / 2); +} + /** * init_mmio_iops_scc - set up the iops for MMIO * @hwif: interface to set up @@ -632,15 +783,15 @@ static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif) ide_set_hwifdata(hwif, ports); + 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->INB = scc_ide_inb; - hwif->INW = scc_ide_inw; - hwif->INSW = scc_ide_insw; - hwif->INSL = scc_ide_insl; hwif->OUTB = scc_ide_outb; hwif->OUTBSYNC = scc_ide_outbsync; - hwif->OUTW = scc_ide_outw; - hwif->OUTSW = scc_ide_outsw; - hwif->OUTSL = scc_ide_outsl; hwif->dma_base = dma_base; hwif->config_data = ports->ctl; @@ -687,7 +838,6 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif) hwif->dma_command = hwif->dma_base; hwif->dma_status = hwif->dma_base + 0x04; - hwif->dma_prdtable = hwif->dma_base + 0x08; /* PTERADD */ out_be32((void __iomem *)(hwif->dma_base + 0x018), hwif->dmatable_dma); @@ -706,10 +856,10 @@ static const struct ide_port_ops scc_port_ops = { }; static const struct ide_dma_ops scc_dma_ops = { - .dma_host_set = ide_dma_host_set, + .dma_host_set = scc_dma_host_set, .dma_setup = scc_dma_setup, .dma_exec_cmd = ide_dma_exec_cmd, - .dma_start = ide_dma_start, + .dma_start = scc_dma_start, .dma_end = scc_dma_end, .dma_test_irq = scc_dma_test_irq, .dma_lost_irq = ide_dma_lost_irq, @@ -763,9 +913,8 @@ static void __devexit scc_remove(struct pci_dev *dev) hwif->dmatable_cpu = NULL; } - ide_unregister(hwif->index); + ide_unregister(hwif); - hwif->chipset = ide_unknown; iounmap((void*)ports->dma); iounmap((void*)ports->ctl); pci_release_selected_regions(dev, (1 << 2) - 1); diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index 321a4e28ac19..16a0bce17d69 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -98,28 +98,28 @@ sgiioc4_init_hwif_ports(hw_regs_t * hw, unsigned long data_port, int i; /* Registers are word (32 bit) aligned */ - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) - hw->io_ports[i] = reg + i * 4; + for (i = 0; i <= 7; i++) + hw->io_ports_array[i] = reg + i * 4; if (ctrl_port) - hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; + hw->io_ports.ctl_addr = ctrl_port; if (irq_port) - hw->io_ports[IDE_IRQ_OFFSET] = irq_port; + hw->io_ports.irq_addr = irq_port; } static void sgiioc4_maskproc(ide_drive_t * drive, int mask) { writeb(mask ? (drive->ctl | 2) : (drive->ctl & ~2), - (void __iomem *)drive->hwif->io_ports[IDE_CONTROL_OFFSET]); + (void __iomem *)drive->hwif->io_ports.ctl_addr); } static int sgiioc4_checkirq(ide_hwif_t * hwif) { unsigned long intr_addr = - hwif->io_ports[IDE_IRQ_OFFSET] + IOC4_INTR_REG * 4; + hwif->io_ports.irq_addr + IOC4_INTR_REG * 4; if ((u8)readl((void __iomem *)intr_addr) & 0x03) return 1; @@ -134,8 +134,8 @@ sgiioc4_clearirq(ide_drive_t * drive) { u32 intr_reg; ide_hwif_t *hwif = HWIF(drive); - unsigned long other_ir = - hwif->io_ports[IDE_IRQ_OFFSET] + (IOC4_INTR_REG << 2); + struct ide_io_ports *io_ports = &hwif->io_ports; + unsigned long other_ir = io_ports->irq_addr + (IOC4_INTR_REG << 2); /* Code to check for PCI error conditions */ intr_reg = readl((void __iomem *)other_ir); @@ -147,12 +147,12 @@ sgiioc4_clearirq(ide_drive_t * drive) * a "clear" status if it got cleared. If not, then spin * for a bit trying to clear it. */ - u8 stat = sgiioc4_INB(hwif->io_ports[IDE_STATUS_OFFSET]); + u8 stat = sgiioc4_INB(io_ports->status_addr); int count = 0; - stat = sgiioc4_INB(hwif->io_ports[IDE_STATUS_OFFSET]); + stat = sgiioc4_INB(io_ports->status_addr); while ((stat & 0x80) && (count++ < 100)) { udelay(1); - stat = sgiioc4_INB(hwif->io_ports[IDE_STATUS_OFFSET]); + stat = sgiioc4_INB(io_ports->status_addr); } if (intr_reg & 0x02) { @@ -162,9 +162,9 @@ sgiioc4_clearirq(ide_drive_t * drive) pci_stat_cmd_reg; pci_err_addr_low = - readl((void __iomem *)hwif->io_ports[IDE_IRQ_OFFSET]); + readl((void __iomem *)io_ports->irq_addr); pci_err_addr_high = - readl((void __iomem *)(hwif->io_ports[IDE_IRQ_OFFSET] + 4)); + readl((void __iomem *)(io_ports->irq_addr + 4)); pci_read_config_dword(dev, PCI_COMMAND, &pci_stat_cmd_reg); printk(KERN_ERR @@ -573,7 +573,7 @@ static const struct ide_port_info sgiioc4_port_info __devinitdata = { .init_dma = ide_dma_sgiioc4, .port_ops = &sgiioc4_port_ops, .dma_ops = &sgiioc4_dma_ops, - .host_flags = IDE_HFLAG_NO_AUTOTUNE, + .host_flags = IDE_HFLAG_MMIO, .mwdma_mask = ATA_MWDMA2_ONLY, }; diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index 1fffea3211bd..0006b9e58567 100644 --- a/drivers/ide/pci/siimage.c +++ b/drivers/ide/pci/siimage.c @@ -1,8 +1,8 @@ /* * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2003 Red Hat <alan@redhat.com> - * Copyright (C) 2007 MontaVista Software, Inc. - * Copyright (C) 2007 Bartlomiej Zolnierkiewicz + * Copyright (C) 2007-2008 MontaVista Software, Inc. + * Copyright (C) 2007-2008 Bartlomiej Zolnierkiewicz * * May be copied or modified under the terms of the GNU General Public License * @@ -17,10 +17,10 @@ * * FAQ Items: * If you are using Marvell SATA-IDE adapters with Maxtor drives - * ensure the system is set up for ATA100/UDMA5 not UDMA6. + * ensure the system is set up for ATA100/UDMA5, not UDMA6. * * If you are using WD drives with SATA bridges you must set the - * drive to "Single". "Master" will hang + * drive to "Single". "Master" will hang. * * If you have strange problems with nVidia chipset systems please * see the SI support documentation and update your system BIOS @@ -42,25 +42,24 @@ #include <linux/hdreg.h> #include <linux/ide.h> #include <linux/init.h> - -#include <asm/io.h> +#include <linux/io.h> /** * pdev_is_sata - check if device is SATA * @pdev: PCI device to check - * + * * Returns true if this is a SATA controller */ - + static int pdev_is_sata(struct pci_dev *pdev) { #ifdef CONFIG_BLK_DEV_IDE_SATA - switch(pdev->device) { - case PCI_DEVICE_ID_SII_3112: - case PCI_DEVICE_ID_SII_1210SA: - return 1; - case PCI_DEVICE_ID_SII_680: - return 0; + switch (pdev->device) { + case PCI_DEVICE_ID_SII_3112: + case PCI_DEVICE_ID_SII_1210SA: + return 1; + case PCI_DEVICE_ID_SII_680: + return 0; } BUG(); #endif @@ -70,10 +69,10 @@ static int pdev_is_sata(struct pci_dev *pdev) /** * is_sata - check if hwif is SATA * @hwif: interface to check - * + * * Returns true if this is a SATA controller */ - + static inline int is_sata(ide_hwif_t *hwif) { return pdev_is_sata(to_pci_dev(hwif->dev)); @@ -86,21 +85,22 @@ static inline int is_sata(ide_hwif_t *hwif) * * Turn a config register offset into the right address in either * PCI space or MMIO space to access the control register in question - * Thankfully this is a configuration operation so isnt performance - * criticial. + * Thankfully this is a configuration operation, so isn't performance + * critical. */ - + static unsigned long siimage_selreg(ide_hwif_t *hwif, int r) { unsigned long base = (unsigned long)hwif->hwif_data; + base += 0xA0 + r; - if(hwif->mmio) - base += (hwif->channel << 6); + if (hwif->mmio) + base += hwif->channel << 6; else - base += (hwif->channel << 4); + base += hwif->channel << 4; return base; } - + /** * siimage_seldev - return register base * @hwif: interface @@ -110,20 +110,69 @@ static unsigned long siimage_selreg(ide_hwif_t *hwif, int r) * PCI space or MMIO space to access the control register in question * including accounting for the unit shift. */ - + static inline unsigned long siimage_seldev(ide_drive_t *drive, int r) { ide_hwif_t *hwif = HWIF(drive); - unsigned long base = (unsigned long)hwif->hwif_data; + unsigned long base = (unsigned long)hwif->hwif_data; + base += 0xA0 + r; - if(hwif->mmio) - base += (hwif->channel << 6); + if (hwif->mmio) + base += hwif->channel << 6; else - base += (hwif->channel << 4); + base += hwif->channel << 4; base |= drive->select.b.unit << drive->select.b.unit; return base; } +static u8 sil_ioread8(struct pci_dev *dev, unsigned long addr) +{ + u8 tmp = 0; + + if (pci_get_drvdata(dev)) + tmp = readb((void __iomem *)addr); + else + pci_read_config_byte(dev, addr, &tmp); + + return tmp; +} + +static u16 sil_ioread16(struct pci_dev *dev, unsigned long addr) +{ + u16 tmp = 0; + + if (pci_get_drvdata(dev)) + tmp = readw((void __iomem *)addr); + else + pci_read_config_word(dev, addr, &tmp); + + return tmp; +} + +static void sil_iowrite8(struct pci_dev *dev, u8 val, unsigned long addr) +{ + if (pci_get_drvdata(dev)) + writeb(val, (void __iomem *)addr); + else + pci_write_config_byte(dev, addr, val); +} + +static void sil_iowrite16(struct pci_dev *dev, u16 val, unsigned long addr) +{ + if (pci_get_drvdata(dev)) + writew(val, (void __iomem *)addr); + else + pci_write_config_word(dev, addr, val); +} + +static void sil_iowrite32(struct pci_dev *dev, u32 val, unsigned long addr) +{ + if (pci_get_drvdata(dev)) + writel(val, (void __iomem *)addr); + else + pci_write_config_dword(dev, addr, val); +} + /** * sil_udma_filter - compute UDMA mask * @drive: IDE device @@ -136,24 +185,26 @@ static inline unsigned long siimage_seldev(ide_drive_t *drive, int r) static u8 sil_pata_udma_filter(ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = to_pci_dev(hwif->dev); - unsigned long base = (unsigned long) hwif->hwif_data; - u8 mask = 0, scsc = 0; + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = to_pci_dev(hwif->dev); + unsigned long base = (unsigned long)hwif->hwif_data; + u8 scsc, mask = 0; - if (hwif->mmio) - scsc = hwif->INB(base + 0x4A); - else - pci_read_config_byte(dev, 0x8A, &scsc); + scsc = sil_ioread8(dev, base + (hwif->mmio ? 0x4A : 0x8A)); - if ((scsc & 0x30) == 0x10) /* 133 */ + switch (scsc & 0x30) { + case 0x10: /* 133 */ mask = ATA_UDMA6; - else if ((scsc & 0x30) == 0x20) /* 2xPCI */ + break; + case 0x20: /* 2xPCI */ mask = ATA_UDMA6; - else if ((scsc & 0x30) == 0x00) /* 100 */ + break; + case 0x00: /* 100 */ mask = ATA_UDMA5; - else /* Disabled ? */ + break; + default: /* Disabled ? */ BUG(); + } return mask; } @@ -175,15 +226,16 @@ static u8 sil_sata_udma_filter(ide_drive_t *drive) static void sil_set_pio_mode(ide_drive_t *drive, u8 pio) { - const u16 tf_speed[] = { 0x328a, 0x2283, 0x1281, 0x10c3, 0x10c1 }; - const u16 data_speed[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 }; + static const u16 tf_speed[] = { 0x328a, 0x2283, 0x1281, 0x10c3, 0x10c1 }; + static const u16 data_speed[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 }; ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = to_pci_dev(hwif->dev); ide_drive_t *pair = ide_get_paired_drive(drive); u32 speedt = 0; u16 speedp = 0; unsigned long addr = siimage_seldev(drive, 0x04); - unsigned long tfaddr = siimage_selreg(hwif, 0x02); + unsigned long tfaddr = siimage_selreg(hwif, 0x02); unsigned long base = (unsigned long)hwif->hwif_data; u8 tf_pio = pio; u8 addr_mask = hwif->channel ? (hwif->mmio ? 0xF4 : 0x84) @@ -203,36 +255,20 @@ static void sil_set_pio_mode(ide_drive_t *drive, u8 pio) speedp = data_speed[pio]; speedt = tf_speed[tf_pio]; - if (hwif->mmio) { - hwif->OUTW(speedp, addr); - hwif->OUTW(speedt, tfaddr); - /* Now set up IORDY */ - if (pio > 2) - hwif->OUTW(hwif->INW(tfaddr-2)|0x200, tfaddr-2); - else - hwif->OUTW(hwif->INW(tfaddr-2)&~0x200, tfaddr-2); - - mode = hwif->INB(base + addr_mask); - mode &= ~(unit ? 0x30 : 0x03); - mode |= (unit ? 0x10 : 0x01); - hwif->OUTB(mode, base + addr_mask); - } else { - struct pci_dev *dev = to_pci_dev(hwif->dev); - - pci_write_config_word(dev, addr, speedp); - pci_write_config_word(dev, tfaddr, speedt); - pci_read_config_word(dev, tfaddr - 2, &speedp); - speedp &= ~0x200; - /* Set IORDY for mode 3 or 4 */ - if (pio > 2) - speedp |= 0x200; - pci_write_config_word(dev, tfaddr - 2, speedp); - - pci_read_config_byte(dev, addr_mask, &mode); - mode &= ~(unit ? 0x30 : 0x03); - mode |= (unit ? 0x10 : 0x01); - pci_write_config_byte(dev, addr_mask, mode); - } + sil_iowrite16(dev, speedp, addr); + sil_iowrite16(dev, speedt, tfaddr); + + /* now set up IORDY */ + speedp = sil_ioread16(dev, tfaddr - 2); + speedp &= ~0x200; + if (pio > 2) + speedp |= 0x200; + sil_iowrite16(dev, speedp, tfaddr - 2); + + mode = sil_ioread8(dev, base + addr_mask); + mode &= ~(unit ? 0x30 : 0x03); + mode |= unit ? 0x10 : 0x01; + sil_iowrite8(dev, mode, base + addr_mask); } /** @@ -245,59 +281,45 @@ static void sil_set_pio_mode(ide_drive_t *drive, u8 pio) static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed) { - u8 ultra6[] = { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 }; - u8 ultra5[] = { 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01 }; - u16 dma[] = { 0x2208, 0x10C2, 0x10C1 }; + static const u8 ultra6[] = { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 }; + static const u8 ultra5[] = { 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01 }; + static const u16 dma[] = { 0x2208, 0x10C2, 0x10C1 }; ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = to_pci_dev(hwif->dev); u16 ultra = 0, multi = 0; u8 mode = 0, unit = drive->select.b.unit; unsigned long base = (unsigned long)hwif->hwif_data; - u8 scsc = 0, addr_mask = ((hwif->channel) ? - ((hwif->mmio) ? 0xF4 : 0x84) : - ((hwif->mmio) ? 0xB4 : 0x80)); - + u8 scsc = 0, addr_mask = hwif->channel ? + (hwif->mmio ? 0xF4 : 0x84) : + (hwif->mmio ? 0xB4 : 0x80); unsigned long ma = siimage_seldev(drive, 0x08); unsigned long ua = siimage_seldev(drive, 0x0C); - if (hwif->mmio) { - scsc = hwif->INB(base + 0x4A); - mode = hwif->INB(base + addr_mask); - multi = hwif->INW(ma); - ultra = hwif->INW(ua); - } else { - pci_read_config_byte(dev, 0x8A, &scsc); - pci_read_config_byte(dev, addr_mask, &mode); - pci_read_config_word(dev, ma, &multi); - pci_read_config_word(dev, ua, &ultra); - } + scsc = sil_ioread8 (dev, base + (hwif->mmio ? 0x4A : 0x8A)); + mode = sil_ioread8 (dev, base + addr_mask); + multi = sil_ioread16(dev, ma); + ultra = sil_ioread16(dev, ua); - mode &= ~((unit) ? 0x30 : 0x03); + mode &= ~(unit ? 0x30 : 0x03); ultra &= ~0x3F; scsc = ((scsc & 0x30) == 0x00) ? 0 : 1; scsc = is_sata(hwif) ? 1 : scsc; if (speed >= XFER_UDMA_0) { - multi = dma[2]; - ultra |= (scsc ? ultra6[speed - XFER_UDMA_0] : - ultra5[speed - XFER_UDMA_0]); - mode |= (unit ? 0x30 : 0x03); + multi = dma[2]; + ultra |= scsc ? ultra6[speed - XFER_UDMA_0] : + ultra5[speed - XFER_UDMA_0]; + mode |= unit ? 0x30 : 0x03; } else { multi = dma[speed - XFER_MW_DMA_0]; - mode |= (unit ? 0x20 : 0x02); + mode |= unit ? 0x20 : 0x02; } - if (hwif->mmio) { - hwif->OUTB(mode, base + addr_mask); - hwif->OUTW(multi, ma); - hwif->OUTW(ultra, ua); - } else { - pci_write_config_byte(dev, addr_mask, mode); - pci_write_config_word(dev, ma, multi); - pci_write_config_word(dev, ua, ultra); - } + sil_iowrite8 (dev, mode, base + addr_mask); + sil_iowrite16(dev, multi, ma); + sil_iowrite16(dev, ultra, ua); } /* returns 1 if dma irq issued, 0 otherwise */ @@ -309,13 +331,14 @@ static int siimage_io_dma_test_irq(ide_drive_t *drive) unsigned long addr = siimage_selreg(hwif, 1); /* return 1 if INTR asserted */ - if ((hwif->INB(hwif->dma_status) & 4) == 4) + if (hwif->INB(hwif->dma_status) & 4) return 1; /* return 1 if Device INTR asserted */ pci_read_config_byte(dev, addr, &dma_altstat); if (dma_altstat & 8) - return 0; //return 1; + return 0; /* return 1; */ + return 0; } @@ -335,9 +358,9 @@ static int siimage_mmio_dma_test_irq(ide_drive_t *drive) = (void __iomem *)hwif->sata_scr[SATA_ERROR_OFFSET]; if (sata_error_addr) { - unsigned long base = (unsigned long)hwif->hwif_data; - u32 ext_stat = readl((void __iomem *)(base + 0x10)); - u8 watchdog = 0; + unsigned long base = (unsigned long)hwif->hwif_data; + u32 ext_stat = readl((void __iomem *)(base + 0x10)); + u8 watchdog = 0; if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) { u32 sata_error = readl(sata_error_addr); @@ -346,25 +369,22 @@ static int siimage_mmio_dma_test_irq(ide_drive_t *drive) watchdog = (sata_error & 0x00680000) ? 1 : 0; printk(KERN_WARNING "%s: sata_error = 0x%08x, " "watchdog = %d, %s\n", - drive->name, sata_error, watchdog, - __func__); - - } else { + drive->name, sata_error, watchdog, __func__); + } else watchdog = (ext_stat & 0x8000) ? 1 : 0; - } - ext_stat >>= 16; + ext_stat >>= 16; if (!(ext_stat & 0x0404) && !watchdog) return 0; } /* return 1 if INTR asserted */ - if ((readb((void __iomem *)hwif->dma_status) & 0x04) == 0x04) + if (readb((void __iomem *)hwif->dma_status) & 0x04) return 1; /* return 1 if Device INTR asserted */ - if ((readb((void __iomem *)addr) & 8) == 8) - return 0; //return 1; + if (readb((void __iomem *)addr) & 8) + return 0; /* return 1; */ return 0; } @@ -423,63 +443,33 @@ static void sil_sata_pre_reset(ide_drive_t *drive) } /** - * proc_reports_siimage - add siimage controller to proc - * @dev: PCI device - * @clocking: SCSC value - * @name: controller name - * - * Report the clocking mode of the controller and add it to - * the /proc interface layer - */ - -static void proc_reports_siimage (struct pci_dev *dev, u8 clocking, const char *name) -{ - if (!pdev_is_sata(dev)) { - printk(KERN_INFO "%s: BASE CLOCK ", name); - clocking &= 0x03; - switch (clocking) { - case 0x03: printk("DISABLED!\n"); break; - case 0x02: printk("== 2X PCI\n"); break; - case 0x01: printk("== 133\n"); break; - case 0x00: printk("== 100\n"); break; - } - } -} - -/** - * setup_mmio_siimage - switch an SI controller into MMIO + * setup_mmio_siimage - switch controller into MMIO mode * @dev: PCI device we are configuring * @name: device name * - * Attempt to put the device into mmio mode. There are some slight - * complications here with certain systems where the mmio bar isnt - * mapped so we have to be sure we can fall back to I/O. + * Attempt to put the device into MMIO mode. There are some slight + * complications here with certain systems where the MMIO BAR isn't + * mapped, so we have to be sure that we can fall back to I/O. */ - -static unsigned int setup_mmio_siimage (struct pci_dev *dev, const char *name) + +static unsigned int setup_mmio_siimage(struct pci_dev *dev, const char *name) { resource_size_t bar5 = pci_resource_start(dev, 5); unsigned long barsize = pci_resource_len(dev, 5); - u8 tmpbyte = 0; void __iomem *ioaddr; - u32 tmp, irq_mask; /* - * Drop back to PIO if we can't map the mmio. Some - * systems seem to get terminally confused in the PCI - * spaces. + * Drop back to PIO if we can't map the MMIO. Some systems + * seem to get terminally confused in the PCI spaces. */ - - if(!request_mem_region(bar5, barsize, name)) - { - printk(KERN_WARNING "siimage: IDE controller MMIO ports not available.\n"); + if (!request_mem_region(bar5, barsize, name)) { + printk(KERN_WARNING "siimage: IDE controller MMIO ports not " + "available.\n"); return 0; } - - ioaddr = ioremap(bar5, barsize); - if (ioaddr == NULL) - { + ioaddr = ioremap(bar5, barsize); + if (ioaddr == NULL) { release_mem_region(bar5, barsize); return 0; } @@ -487,62 +477,6 @@ static unsigned int setup_mmio_siimage (struct pci_dev *dev, const char *name) pci_set_master(dev); pci_set_drvdata(dev, (void *) ioaddr); - if (pdev_is_sata(dev)) { - /* make sure IDE0/1 interrupts are not masked */ - irq_mask = (1 << 22) | (1 << 23); - tmp = readl(ioaddr + 0x48); - if (tmp & irq_mask) { - tmp &= ~irq_mask; - writel(tmp, ioaddr + 0x48); - readl(ioaddr + 0x48); /* flush */ - } - writel(0, ioaddr + 0x148); - writel(0, ioaddr + 0x1C8); - } - - writeb(0, ioaddr + 0xB4); - writeb(0, ioaddr + 0xF4); - tmpbyte = readb(ioaddr + 0x4A); - - switch(tmpbyte & 0x30) { - case 0x00: - /* In 100 MHz clocking, try and switch to 133 */ - writeb(tmpbyte|0x10, ioaddr + 0x4A); - break; - case 0x10: - /* On 133Mhz clocking */ - break; - case 0x20: - /* On PCIx2 clocking */ - break; - case 0x30: - /* Clocking is disabled */ - /* 133 clock attempt to force it on */ - writeb(tmpbyte & ~0x20, ioaddr + 0x4A); - break; - } - - writeb( 0x72, ioaddr + 0xA1); - writew( 0x328A, ioaddr + 0xA2); - writel(0x62DD62DD, ioaddr + 0xA4); - writel(0x43924392, ioaddr + 0xA8); - writel(0x40094009, ioaddr + 0xAC); - writeb( 0x72, ioaddr + 0xE1); - writew( 0x328A, ioaddr + 0xE2); - writel(0x62DD62DD, ioaddr + 0xE4); - writel(0x43924392, ioaddr + 0xE8); - writel(0x40094009, ioaddr + 0xEC); - - if (pdev_is_sata(dev)) { - writel(0xFFFF0000, ioaddr + 0x108); - writel(0xFFFF0000, ioaddr + 0x188); - writel(0x00680000, ioaddr + 0x148); - writel(0x00680000, ioaddr + 0x1C8); - } - - tmpbyte = readb(ioaddr + 0x4A); - - proc_reports_siimage(dev, (tmpbyte>>4), name); return 1; } @@ -552,55 +486,92 @@ static unsigned int setup_mmio_siimage (struct pci_dev *dev, const char *name) * @name: device name * * Perform the initial PCI set up for this device. Attempt to switch - * to 133MHz clocking if the system isn't already set up to do it. + * to 133 MHz clocking if the system isn't already set up to do it. */ -static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev, const char *name) +static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev, + const char *name) { - u8 rev = dev->revision, tmpbyte = 0, BA5_EN = 0; + unsigned long base, scsc_addr; + void __iomem *ioaddr = NULL; + u8 rev = dev->revision, tmp, BA5_EN; pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, rev ? 1 : 255); pci_read_config_byte(dev, 0x8A, &BA5_EN); - if ((BA5_EN & 0x01) || (pci_resource_start(dev, 5))) { - if (setup_mmio_siimage(dev, name)) { - return 0; + + if ((BA5_EN & 0x01) || pci_resource_start(dev, 5)) + if (setup_mmio_siimage(dev, name)) + ioaddr = pci_get_drvdata(dev); + + base = (unsigned long)ioaddr; + + if (ioaddr && pdev_is_sata(dev)) { + u32 tmp32, irq_mask; + + /* make sure IDE0/1 interrupts are not masked */ + irq_mask = (1 << 22) | (1 << 23); + tmp32 = readl(ioaddr + 0x48); + if (tmp32 & irq_mask) { + tmp32 &= ~irq_mask; + writel(tmp32, ioaddr + 0x48); + readl(ioaddr + 0x48); /* flush */ } + writel(0, ioaddr + 0x148); + writel(0, ioaddr + 0x1C8); + } + + sil_iowrite8(dev, 0, base ? (base + 0xB4) : 0x80); + sil_iowrite8(dev, 0, base ? (base + 0xF4) : 0x84); + + scsc_addr = base ? (base + 0x4A) : 0x8A; + tmp = sil_ioread8(dev, scsc_addr); + + switch (tmp & 0x30) { + case 0x00: + /* On 100 MHz clocking, try and switch to 133 MHz */ + sil_iowrite8(dev, tmp | 0x10, scsc_addr); + break; + case 0x30: + /* Clocking is disabled, attempt to force 133MHz clocking. */ + sil_iowrite8(dev, tmp & ~0x20, scsc_addr); + case 0x10: + /* On 133Mhz clocking. */ + break; + case 0x20: + /* On PCIx2 clocking. */ + break; } - pci_write_config_byte(dev, 0x80, 0x00); - pci_write_config_byte(dev, 0x84, 0x00); - pci_read_config_byte(dev, 0x8A, &tmpbyte); - switch(tmpbyte & 0x30) { - case 0x00: - /* 133 clock attempt to force it on */ - pci_write_config_byte(dev, 0x8A, tmpbyte|0x10); - case 0x30: - /* if clocking is disabled */ - /* 133 clock attempt to force it on */ - pci_write_config_byte(dev, 0x8A, tmpbyte & ~0x20); - case 0x10: - /* 133 already */ - break; - case 0x20: - /* BIOS set PCI x2 clocking */ - break; + tmp = sil_ioread8(dev, scsc_addr); + + sil_iowrite8 (dev, 0x72, base + 0xA1); + sil_iowrite16(dev, 0x328A, base + 0xA2); + sil_iowrite32(dev, 0x62DD62DD, base + 0xA4); + sil_iowrite32(dev, 0x43924392, base + 0xA8); + sil_iowrite32(dev, 0x40094009, base + 0xAC); + sil_iowrite8 (dev, 0x72, base ? (base + 0xE1) : 0xB1); + sil_iowrite16(dev, 0x328A, base ? (base + 0xE2) : 0xB2); + sil_iowrite32(dev, 0x62DD62DD, base ? (base + 0xE4) : 0xB4); + sil_iowrite32(dev, 0x43924392, base ? (base + 0xE8) : 0xB8); + sil_iowrite32(dev, 0x40094009, base ? (base + 0xEC) : 0xBC); + + if (base && pdev_is_sata(dev)) { + writel(0xFFFF0000, ioaddr + 0x108); + writel(0xFFFF0000, ioaddr + 0x188); + writel(0x00680000, ioaddr + 0x148); + writel(0x00680000, ioaddr + 0x1C8); } - pci_read_config_byte(dev, 0x8A, &tmpbyte); + /* report the clocking mode of the controller */ + if (!pdev_is_sata(dev)) { + static const char *clk_str[] = + { "== 100", "== 133", "== 2X PCI", "DISABLED!" }; - pci_write_config_byte(dev, 0xA1, 0x72); - pci_write_config_word(dev, 0xA2, 0x328A); - pci_write_config_dword(dev, 0xA4, 0x62DD62DD); - pci_write_config_dword(dev, 0xA8, 0x43924392); - pci_write_config_dword(dev, 0xAC, 0x40094009); - pci_write_config_byte(dev, 0xB1, 0x72); - pci_write_config_word(dev, 0xB2, 0x328A); - pci_write_config_dword(dev, 0xB4, 0x62DD62DD); - pci_write_config_dword(dev, 0xB8, 0x43924392); - pci_write_config_dword(dev, 0xBC, 0x40094009); + tmp >>= 4; + printk(KERN_INFO "%s: BASE CLOCK %s\n", name, clk_str[tmp & 3]); + } - proc_reports_siimage(dev, (tmpbyte>>4), name); return 0; } @@ -610,8 +581,7 @@ static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev, const ch * * The basic setup here is fairly simple, we can use standard MMIO * operations. However we do have to set the taskfile register offsets - * by hand as there isnt a standard defined layout for them this - * time. + * by hand as there isn't a standard defined layout for them this time. * * The hardware supports buffered taskfiles and also some rather nice * extended PRD tables. For better SI3112 support use the libata driver @@ -622,23 +592,21 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif) struct pci_dev *dev = to_pci_dev(hwif->dev); void *addr = pci_get_drvdata(dev); u8 ch = hwif->channel; - hw_regs_t hw; - unsigned long base; + struct ide_io_ports *io_ports = &hwif->io_ports; + unsigned long base; /* - * Fill in the basic HWIF bits + * Fill in the basic hwif bits */ - + hwif->host_flags |= IDE_HFLAG_MMIO; default_hwif_mmiops(hwif); - hwif->hwif_data = addr; + hwif->hwif_data = addr; /* - * Now set up the hw. We have to do this ourselves as - * the MMIO layout isnt the same as the standard port - * based I/O + * Now set up the hw. We have to do this ourselves as the + * MMIO layout isn't the same as the standard port based I/O. */ - - memset(&hw, 0, sizeof(hw_regs_t)); + memset(io_ports, 0, sizeof(*io_ports)); base = (unsigned long)addr; if (ch) @@ -647,21 +615,18 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif) base += 0x80; /* - * The buffered task file doesn't have status/control - * so we can't currently use it sanely since we want to - * use LBA48 mode. - */ - hw.io_ports[IDE_DATA_OFFSET] = base; - hw.io_ports[IDE_ERROR_OFFSET] = base + 1; - hw.io_ports[IDE_NSECTOR_OFFSET] = base + 2; - hw.io_ports[IDE_SECTOR_OFFSET] = base + 3; - hw.io_ports[IDE_LCYL_OFFSET] = base + 4; - hw.io_ports[IDE_HCYL_OFFSET] = base + 5; - hw.io_ports[IDE_SELECT_OFFSET] = base + 6; - hw.io_ports[IDE_STATUS_OFFSET] = base + 7; - hw.io_ports[IDE_CONTROL_OFFSET] = base + 10; - - hw.io_ports[IDE_IRQ_OFFSET] = 0; + * The buffered task file doesn't have status/control, so we + * can't currently use it sanely since we want to use LBA48 mode. + */ + io_ports->data_addr = base; + io_ports->error_addr = base + 1; + io_ports->nsect_addr = base + 2; + io_ports->lbal_addr = base + 3; + io_ports->lbam_addr = base + 4; + io_ports->lbah_addr = base + 5; + io_ports->device_addr = base + 6; + io_ports->status_addr = base + 7; + io_ports->ctl_addr = base + 10; if (pdev_is_sata(dev)) { base = (unsigned long)addr; @@ -672,8 +637,6 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif) hwif->sata_scr[SATA_CONTROL_OFFSET] = base + 0x100; } - memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports)); - hwif->irq = dev->irq; hwif->dma_base = (unsigned long)addr + (ch ? 0x08 : 0x00); @@ -683,19 +646,17 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif) static int is_dev_seagate_sata(ide_drive_t *drive) { - const char *s = &drive->id->model[0]; - unsigned len; - - len = strnlen(s, sizeof(drive->id->model)); + const char *s = &drive->id->model[0]; + unsigned len = strnlen(s, sizeof(drive->id->model)); - if ((len > 4) && (!memcmp(s, "ST", 2))) { + if ((len > 4) && (!memcmp(s, "ST", 2))) if ((!memcmp(s + len - 2, "AS", 2)) || (!memcmp(s + len - 3, "ASL", 3))) { printk(KERN_INFO "%s: applying pessimistic Seagate " "errata fix\n", drive->name); return 1; } - } + return 0; } @@ -712,7 +673,7 @@ static void __devinit sil_quirkproc(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; - /* Try and raise the rqsize */ + /* Try and rise the rqsize */ if (!is_sata(hwif) || !is_dev_seagate_sata(drive)) hwif->rqsize = 128; } @@ -746,20 +707,14 @@ static void __devinit init_iops_siimage(ide_hwif_t *hwif) * sil_cable_detect - cable detection * @hwif: interface to check * - * Check for the presence of an ATA66 capable cable on the - * interface. + * Check for the presence of an ATA66 capable cable on the interface. */ static u8 __devinit sil_cable_detect(ide_hwif_t *hwif) { - struct pci_dev *dev = to_pci_dev(hwif->dev); - unsigned long addr = siimage_selreg(hwif, 0); - u8 ata66 = 0; - - if (pci_get_drvdata(dev) == NULL) - pci_read_config_byte(dev, addr, &ata66); - else - ata66 = hwif->INB(addr); + struct pci_dev *dev = to_pci_dev(hwif->dev); + unsigned long addr = siimage_selreg(hwif, 0); + u8 ata66 = sil_ioread8(dev, addr); return (ata66 & 0x01) ? ATA_CBL_PATA80 : ATA_CBL_PATA40; } @@ -782,8 +737,15 @@ static const struct ide_port_ops sil_sata_port_ops = { .cable_detect = sil_cable_detect, }; -static struct ide_dma_ops sil_dma_ops = { +static const struct ide_dma_ops sil_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ide_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = ide_dma_start, + .dma_end = __ide_dma_end, .dma_test_irq = siimage_dma_test_irq, + .dma_timeout = ide_dma_timeout, + .dma_lost_irq = ide_dma_lost_irq, }; #define DECLARE_SII_DEV(name_str, p_ops) \ @@ -805,15 +767,16 @@ static const struct ide_port_info siimage_chipsets[] __devinitdata = { }; /** - * siimage_init_one - pci layer discovery entry + * siimage_init_one - PCI layer discovery entry * @dev: PCI device * @id: ident table entry * - * Called by the PCI code when it finds an SI680 or SI3112 controller. + * Called by the PCI code when it finds an SiI680 or SiI3112 controller. * We then use the IDE PCI generic helper to do most of the work. */ - -static int __devinit siimage_init_one(struct pci_dev *dev, const struct pci_device_id *id) + +static int __devinit siimage_init_one(struct pci_dev *dev, + const struct pci_device_id *id) { struct ide_port_info d; u8 idx = id->driver_data; diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c index 15ee38f7ad3f..a8a3138682ef 100644 --- a/drivers/ide/pci/trm290.c +++ b/drivers/ide/pci/trm290.c @@ -298,7 +298,7 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif) if (old != compat && old_mask == 0xff) { /* leave lower 10 bits untouched */ compat += (next_offset += 0x400); - hwif->io_ports[IDE_CONTROL_OFFSET] = compat + 2; + hwif->io_ports.ctl_addr = compat + 2; outw(compat | 1, hwif->config_data); new = inw(hwif->config_data); printk(KERN_INFO "%s: control basereg workaround: " diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index bbd17bec6ffe..566e0ecb8db1 100644 --- a/drivers/ide/pci/via82cxxx.c +++ b/drivers/ide/pci/via82cxxx.c @@ -340,7 +340,7 @@ static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const * Determine system bus clock. */ - via_clock = system_bus_clock() * 1000; + via_clock = (ide_pci_clk ? ide_pci_clk : system_bus_clock()) * 1000; switch (via_clock) { case 33000: via_clock = 33333; break; diff --git a/drivers/ide/ppc/mpc8xx.c b/drivers/ide/ppc/mpc8xx.c index a82f6efb660b..f0e638dcc3ab 100644 --- a/drivers/ide/ppc/mpc8xx.c +++ b/drivers/ide/ppc/mpc8xx.c @@ -131,7 +131,7 @@ static int pcmcia_schlvl = PCMCIA_SCHLVL; #if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT) static int __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port) { - unsigned long *p = hw->io_ports; + unsigned long *p = hw->io_ports_array; int i; typedef struct { @@ -314,7 +314,7 @@ static int __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port) #if defined(CONFIG_IDE_EXT_DIRECT) static int __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port) { - unsigned long *p = hw->io_ports; + unsigned long *p = hw->io_ports_array; int i; u32 ide_phy_base; @@ -811,24 +811,28 @@ static int __init mpc8xx_ide_probe(void) #ifdef IDE0_BASE_OFFSET memset(&hw, 0, sizeof(hw)); if (!m8xx_ide_init_ports(&hw, 0)) { - ide_hwif_t *hwif = &ide_hwifs[0]; + ide_hwif_t *hwif = ide_find_port(); - ide_init_port_hw(hwif, &hw); - hwif->pio_mask = ATA_PIO4; - hwif->port_ops = &m8xx_port_ops; + if (hwif) { + ide_init_port_hw(hwif, &hw); + hwif->pio_mask = ATA_PIO4; + hwif->port_ops = &m8xx_port_ops; - idx[0] = 0; + idx[0] = hwif->index; + } } #ifdef IDE1_BASE_OFFSET memset(&hw, 0, sizeof(hw)); if (!m8xx_ide_init_ports(&hw, 1)) { - ide_hwif_t *mate = &ide_hwifs[1]; + ide_hwif_t *mate = ide_find_port(); - ide_init_port_hw(mate, &hw); - mate->pio_mask = ATA_PIO4; - mate->port_ops = &m8xx_port_ops; + if (mate) { + ide_init_port_hw(mate, &hw); + mate->pio_mask = ATA_PIO4; + mate->port_ops = &m8xx_port_ops; - idx[1] = 1; + idx[1] = mate->index; + } } #endif #endif diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 185faa0dce94..48aa019127bc 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -417,7 +417,7 @@ static void pmac_ide_kauai_selectproc(ide_drive_t *drive); #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ #define PMAC_IDE_REG(x) \ - ((void __iomem *)((drive)->hwif->io_ports[IDE_DATA_OFFSET] + (x))) + ((void __iomem *)((drive)->hwif->io_ports.data_addr + (x))) /* * Apply the timings of the proper unit (master/slave) to the shared @@ -941,6 +941,7 @@ static const struct ide_port_info pmac_port_info = { .port_ops = &pmac_ide_port_ops, .host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA | IDE_HFLAG_POST_SET_MODE | + IDE_HFLAG_MMIO | IDE_HFLAG_UNMASK_IRQS, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, @@ -1086,8 +1087,9 @@ static void __devinit pmac_ide_init_ports(hw_regs_t *hw, unsigned long base) int i; for (i = 0; i < 8; ++i) - hw->io_ports[i] = base + i * 0x10; - hw->io_ports[8] = base + 0x160; + hw->io_ports_array[i] = base + i * 0x10; + + hw->io_ports.ctl_addr = base + 0x160; } /* |