diff options
Diffstat (limited to 'drivers/ide')
83 files changed, 5033 insertions, 7365 deletions
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index eed6d8e1b5c7..f702f9152ce6 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -122,24 +122,6 @@ config BLK_DEV_IDE_SATA If unsure, say N. -config BLK_DEV_HD_IDE - bool "Use old disk-only driver on primary interface" - depends on (X86 || SH_MPC1211) - ---help--- - There are two drivers for MFM/RLL/IDE disks. Most people use just - the new enhanced driver by itself. This option however installs the - old hard disk driver to control the primary IDE/disk interface in - the system, leaving the new enhanced IDE driver to take care of only - the 2nd/3rd/4th IDE interfaces. Doing this will prevent you from - having an IDE/ATAPI CD-ROM or tape drive connected to the primary - IDE interface. Choosing this option may be useful for older systems - which have MFM/RLL/ESDI controller+drives at the primary port - address (0x1f0), along with IDE drives at the secondary/3rd/4th port - addresses. - - Normally, just say N here; you will then use the new driver for all - 4 interfaces. - config BLK_DEV_IDEDISK tristate "Include IDE/ATA-2 DISK support" ---help--- @@ -325,6 +307,7 @@ comment "IDE chipset support/bugfixes" config IDE_GENERIC tristate "generic/default IDE chipset support" + depends on ALPHA || X86 || IA64 || M32R || MIPS || PPC32 help If unsure, say N. @@ -416,12 +399,6 @@ config BLK_DEV_OFFBOARD This can improve the usability of some boot managers such as lilo when booting from a drive on an off-board controller. - If you say Y here, and you actually want to reverse the device scan - order as explained above, you also need to issue the kernel command - line option "ide=reverse". (Try "man bootparam" or see the - documentation of your boot loader (lilo or loadlin) about how to - pass options to the kernel at boot time.) - Note that, if you do this, the order of the hd* devices will be rearranged which may require modification of fstab and other files. @@ -615,8 +592,7 @@ config BLK_DEV_HPT366 reference to device 0x80. The other solution is to say Y to "Boot off-board chipsets first support" (CONFIG_BLK_DEV_OFFBOARD) unless your mother board has the chipset natively mounted. Regardless one - should use the fore mentioned option and call at LILO or include - "ide=reverse" in LILO's append-line. + should use the fore mentioned option and call at LILO. This driver requires dynamic tuning of the chipset during the ide-probe at boot. It is reported to support DVD II drives, by the @@ -886,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 @@ -1049,19 +991,19 @@ config IDE_EXT_DIRECT endchoice # no isa -> no vlb -if ISA +if ISA && (ALPHA || X86 || MIPS) comment "Other IDE chipsets support" comment "Note: most of these also require special kernel boot parameters" config BLK_DEV_4DRIVES - bool "Generic 4 drives/port support" + tristate "Generic 4 drives/port support" help Certain older chipsets, including the Tekram 690CD, use a single set of I/O ports at 0x1f0 to control up to four drives, instead of the customary two drives per port. Support for this can be enabled at - runtime using the "ide0=four" kernel boot parameter if you say Y - here. + runtime using the "ide-4drives.probe" kernel boot parameter if you + say Y here. config BLK_DEV_ALI14XX tristate "ALI M14xx support" @@ -1114,14 +1056,10 @@ config BLK_DEV_IDEDMA def_bool BLK_DEV_IDEDMA_SFF || BLK_DEV_IDEDMA_PMAC || \ BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA -config IDE_ARCH_OBSOLETE_INIT - def_bool ALPHA || (ARM && !ARCH_L7200) || BLACKFIN || X86 || IA64 || M32R || MIPS || PARISC || PPC || (SUPERH64 && BLK_DEV_IDEPCI) || SPARC - endif config BLK_DEV_HD_ONLY bool "Old hard disk (MFM/RLL/IDE) driver" - depends on BLK_DEV_IDE=n help There are two drivers for MFM/RLL/IDE hard disks. Most people use the newer enhanced driver, but this old one is still around for two @@ -1133,12 +1071,16 @@ config BLK_DEV_HD_ONLY for systems with only older MFM/RLL/ESDI drives. Choosing the old driver can save 13 KB or so of kernel memory. + If you want to use this driver together with the new one you have + to use "hda=noprobe hdb=noprobe" kernel parameters to prevent the new + driver from probing the primary interface. + If you are unsure, then just choose the Enhanced IDE/MFM/RLL driver instead of this one. For more detailed information, read the Disk-HOWTO, available from <http://www.tldp.org/docs.html#howto>. config BLK_DEV_HD - def_bool BLK_DEV_HD_IDE || BLK_DEV_HD_ONLY + def_bool BLK_DEV_HD_ONLY endif # IDE diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index a4a4323be911..f94b679b611e 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -35,10 +35,10 @@ ifeq ($(CONFIG_BLK_DEV_CMD640), y) obj-y += cmd640-core.o endif -obj-$(CONFIG_BLK_DEV_IDE) += cris/ ppc/ -obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o +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 ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o diff --git a/drivers/ide/arm/bast-ide.c b/drivers/ide/arm/bast-ide.c index 161d30c8481e..713cef20622e 100644 --- a/drivers/ide/arm/bast-ide.c +++ b/drivers/ide/arm/bast-ide.c @@ -21,6 +21,8 @@ #include <asm/arch/bast-map.h> #include <asm/arch/bast-irq.h> +#define DRV_NAME "bast-ide" + static int __init bastide_register(unsigned int base, unsigned int aux, int irq) { ide_hwif_t *hwif; @@ -33,27 +35,23 @@ 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_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]); + hwif = ide_find_port(); if (hwif == NULL) goto out; i = hwif->index; - if (hwif->present) - ide_unregister(i, 0, 0); - else if (!hwif->hold) - ide_init_port_data(hwif, i); - + ide_init_port_data(hwif, i); ide_init_port_hw(hwif, &hw); - hwif->quirkproc = NULL; + hwif->port_ops = NULL; idx[0] = i; @@ -64,6 +62,8 @@ out: static int __init bastide_init(void) { + unsigned long base = BAST_VA_IDEPRI + BAST_IDE_CS; + /* we can treat the VR1000 and the BAST the same */ if (!(machine_is_bast() || machine_is_vr1000())) @@ -71,6 +71,11 @@ static int __init bastide_init(void) printk("BAST: IDE driver, (c) 2003-2004 Simtec Electronics\n"); + if (!request_mem_region(base, 0x400000, DRV_NAME)) { + printk(KERN_ERR "%s: resources busy\n", DRV_NAME); + return -EBUSY; + } + bastide_register(BAST_VA_IDEPRI, BAST_VA_IDEPRIAUX, IRQ_IDE0); bastide_register(BAST_VA_IDESEC, BAST_VA_IDESECAUX, IRQ_IDE1); diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c index e816b0ffcfe6..061456914ca3 100644 --- a/drivers/ide/arm/icside.c +++ b/drivers/ide/arm/icside.c @@ -191,6 +191,10 @@ static void icside_maskproc(ide_drive_t *drive, int mask) local_irq_restore(flags); } +static const struct ide_port_ops icside_v6_no_dma_port_ops = { + .maskproc = icside_maskproc, +}; + #ifdef CONFIG_BLK_DEV_IDEDMA_ICS /* * SG-DMA support. @@ -266,6 +270,11 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode) ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data); } +static const struct ide_port_ops icside_v6_port_ops = { + .set_dma_mode = icside_set_dma_mode, + .maskproc = icside_maskproc, +}; + static void icside_dma_host_set(ide_drive_t *drive, int on) { } @@ -375,48 +384,57 @@ static void icside_dma_lost_irq(ide_drive_t *drive) printk(KERN_ERR "%s: IRQ lost\n", drive->name); } -static void icside_dma_init(ide_hwif_t *hwif) +static int icside_dma_init(ide_hwif_t *hwif, const struct ide_port_info *d) { hwif->dmatable_cpu = NULL; hwif->dmatable_dma = 0; - hwif->set_dma_mode = icside_set_dma_mode; - - hwif->dma_host_set = icside_dma_host_set; - hwif->dma_setup = icside_dma_setup; - hwif->dma_exec_cmd = icside_dma_exec_cmd; - hwif->dma_start = icside_dma_start; - hwif->ide_dma_end = icside_dma_end; - hwif->ide_dma_test_irq = icside_dma_test_irq; - hwif->dma_timeout = icside_dma_timeout; - hwif->dma_lost_irq = icside_dma_lost_irq; + + return 0; } + +static const struct ide_dma_ops icside_v6_dma_ops = { + .dma_host_set = icside_dma_host_set, + .dma_setup = icside_dma_setup, + .dma_exec_cmd = icside_dma_exec_cmd, + .dma_start = icside_dma_start, + .dma_end = icside_dma_end, + .dma_test_irq = icside_dma_test_irq, + .dma_timeout = icside_dma_timeout, + .dma_lost_irq = icside_dma_lost_irq, +}; #else -#define icside_dma_init(hwif) (0) +#define icside_v6_dma_ops NULL #endif +static int icside_dma_off_init(ide_hwif_t *hwif, const struct ide_port_info *d) +{ + return -EOPNOTSUPP; +} + static ide_hwif_t * icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *ec) { unsigned long port = (unsigned long)base + info->dataoffset; ide_hwif_t *hwif; - hwif = ide_find_port(port); + hwif = ide_find_port(); if (hwif) { - int i; - /* * Ensure we're using MMIO */ default_hwif_mmiops(hwif); - hwif->mmio = 1; - 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->noprobe = 0; hwif->chipset = ide_acorn; hwif->gendev.parent = &ec->dev; hwif->dev = &ec->dev; @@ -462,9 +480,10 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec) } static const struct ide_port_info icside_v6_port_info __initdata = { - .host_flags = IDE_HFLAG_SERIALIZE | - IDE_HFLAG_NO_DMA | /* no SFF-style DMA */ - IDE_HFLAG_NO_AUTOTUNE, + .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_MMIO, .mwdma_mask = ATA_MWDMA2, .swdma_mask = ATA_SWDMA2, }; @@ -526,21 +545,19 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) state->hwif[0] = hwif; state->hwif[1] = mate; - hwif->maskproc = icside_maskproc; hwif->hwif_data = state; 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)) { - icside_dma_init(hwif); - icside_dma_init(mate); - } else - d.mwdma_mask = d.swdma_mask = 0; + d.init_dma = icside_dma_init; + d.port_ops = &icside_v6_port_ops; + d.dma_ops = NULL; + } idx[0] = hwif->index; idx[1] = mate->index; diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c index be9ff7334c52..4263ffd4ab20 100644 --- a/drivers/ide/arm/ide_arm.c +++ b/drivers/ide/arm/ide_arm.c @@ -14,6 +14,8 @@ #include <asm/mach-types.h> #include <asm/irq.h> +#define DRV_NAME "ide_arm" + #ifdef CONFIG_ARCH_CLPS7500 # include <asm/arch/hardware.h> # @@ -28,13 +30,27 @@ static int __init ide_arm_init(void) { ide_hwif_t *hwif; hw_regs_t hw; + unsigned long base = IDE_ARM_IO, ctl = IDE_ARM_IO + 0x206; u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; + if (!request_region(base, 8, DRV_NAME)) { + printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", + DRV_NAME, base, base + 7); + return -EBUSY; + } + + if (!request_region(ctl, 1, DRV_NAME)) { + printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n", + DRV_NAME, ctl); + release_region(base, 8); + return -EBUSY; + } + memset(&hw, 0, sizeof(hw)); - ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206); + ide_std_init_ports(&hw, base, ctl); hw.irq = IDE_ARM_IRQ; - hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]); + hwif = ide_find_port(); if (hwif) { ide_init_port_hw(hwif, &hw); idx[0] = hwif->index; diff --git a/drivers/ide/arm/palm_bk3710.c b/drivers/ide/arm/palm_bk3710.c index 8e1f6bd33887..96378ebfb31f 100644 --- a/drivers/ide/arm/palm_bk3710.c +++ b/drivers/ide/arm/palm_bk3710.c @@ -96,11 +96,11 @@ static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev, u16 val16; /* DMA Data Setup */ - t0 = (palm_bk3710_udmatimings[mode].cycletime + ide_palm_clk - 1) - / ide_palm_clk - 1; - tenv = (20 + ide_palm_clk - 1) / ide_palm_clk - 1; - trp = (palm_bk3710_udmatimings[mode].rptime + ide_palm_clk - 1) - / ide_palm_clk - 1; + t0 = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].cycletime, + ide_palm_clk) - 1; + tenv = DIV_ROUND_UP(20, ide_palm_clk) - 1; + trp = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].rptime, + ide_palm_clk) - 1; /* udmatim Register */ val16 = readw(base + BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0); @@ -141,8 +141,8 @@ static void palm_bk3710_setdmamode(void __iomem *base, unsigned int dev, cycletime = max_t(int, t->cycle, min_cycle); /* DMA Data Setup */ - t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk; - td = (t->active + ide_palm_clk - 1) / ide_palm_clk; + t0 = DIV_ROUND_UP(cycletime, ide_palm_clk); + td = DIV_ROUND_UP(t->active, ide_palm_clk); tkw = t0 - td - 1; td -= 1; @@ -168,9 +168,9 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate, struct ide_timing *t; /* PIO Data Setup */ - t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk; - t2 = (ide_timing_find_mode(XFER_PIO_0 + mode)->active + - ide_palm_clk - 1) / ide_palm_clk; + t0 = DIV_ROUND_UP(cycletime, ide_palm_clk); + t2 = DIV_ROUND_UP(ide_timing_find_mode(XFER_PIO_0 + mode)->active, + ide_palm_clk); t2i = t0 - t2 - 1; t2 -= 1; @@ -192,8 +192,8 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate, /* TASKFILE Setup */ t = ide_timing_find_mode(XFER_PIO_0 + mode); - t0 = (t->cyc8b + ide_palm_clk - 1) / ide_palm_clk; - t2 = (t->act8b + ide_palm_clk - 1) / ide_palm_clk; + t0 = DIV_ROUND_UP(t->cyc8b, ide_palm_clk); + t2 = DIV_ROUND_UP(t->act8b, ide_palm_clk); t2i = t0 - t2 - 1; t2 -= 1; @@ -317,17 +317,32 @@ static u8 __devinit palm_bk3710_cable_detect(ide_hwif_t *hwif) return ATA_CBL_PATA80; } -static void __devinit palm_bk3710_init_hwif(ide_hwif_t *hwif) +static int __devinit palm_bk3710_init_dma(ide_hwif_t *hwif, + const struct ide_port_info *d) { - hwif->set_pio_mode = palm_bk3710_set_pio_mode; - hwif->set_dma_mode = palm_bk3710_set_dma_mode; + unsigned long base = + hwif->io_ports.data_addr - IDE_PALM_ATA_PRI_REG_OFFSET; - hwif->cable_detect = palm_bk3710_cable_detect; + printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name); + + if (ide_allocate_dma_engine(hwif)) + return -1; + + ide_setup_dma(hwif, base); + + return 0; } +static const struct ide_port_ops palm_bk3710_ports_ops = { + .set_pio_mode = palm_bk3710_set_pio_mode, + .set_dma_mode = palm_bk3710_set_dma_mode, + .cable_detect = palm_bk3710_cable_detect, +}; + static const struct ide_port_info __devinitdata palm_bk3710_port_info = { - .init_hwif = palm_bk3710_init_hwif, - .host_flags = IDE_HFLAG_NO_DMA, /* hack (no PCI) */ + .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, @@ -372,30 +387,24 @@ 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; - hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]); + hwif = ide_find_port(); if (hwif == NULL) goto out; i = hwif->index; - if (hwif->present) - ide_unregister(i, 0, 0); - else if (!hwif->hold) - ide_init_port_data(hwif, i); - + ide_init_port_data(hwif, i); ide_init_port_hw(hwif, &hw); hwif->mmio = 1; default_hwif_mmiops(hwif); - ide_setup_dma(hwif, mem->start); - idx[0] = i; ide_device_add(idx, &palm_bk3710_port_info); @@ -409,9 +418,13 @@ out: return -ENODEV; } +/* work with hotplug and coldplug */ +MODULE_ALIAS("platform:palm_bk3710"); + static struct platform_driver platform_bk_driver = { .driver = { .name = "palm_bk3710", + .owner = THIS_MODULE, }, .probe = palm_bk3710_probe, .remove = NULL, diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c index efba00d2fc37..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; } @@ -44,7 +44,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id) goto release; } - hwif = ide_find_port((unsigned long)base); + hwif = ide_find_port(); if (hwif) { memset(&hw, 0, sizeof(hw)); rapide_setup_ports(&hw, base, base + 0x818, 1 << 6, ec->irq); @@ -53,7 +53,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id) ide_init_port_hw(hwif, &hw); - hwif->mmio = 1; + hwif->host_flags = IDE_HFLAG_MMIO; default_hwif_mmiops(hwif); idx[0] = hwif->index; @@ -76,7 +76,7 @@ static void __devexit rapide_remove(struct expansion_card *ec) ecard_set_drvdata(ec, NULL); - ide_unregister(hwif->index, 0, 0); + 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 c8ffbaf29a88..000000000000 --- a/drivers/ide/cris/ide-cris.c +++ /dev/null @@ -1,1071 +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) -{ - reg_ata_rw_ctrl2 ctrl2 = REG_TYPE_CONV(reg_ata_rw_ctrl2, int, IDE_DATA_REG); - 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) -{ - int intr = REG_RD_INT(ata, regi_ata, r_intr); - reg_ata_rw_ctrl2 ctrl2 = REG_TYPE_CONV(reg_ata_rw_ctrl2, int, IDE_DATA_REG); - 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, IDE_DATA_REG) | - 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, IDE_DATA_REG); - 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 int cris_dma_end (ide_drive_t *drive); -static int cris_dma_setup (ide_drive_t *drive); -static void cris_dma_exec_cmd (ide_drive_t *drive, u8 command); -static int cris_dma_test_irq(ide_drive_t *drive); -static void cris_dma_start(ide_drive_t *drive); -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_info cris_port_info __initdata = { - .chipset = ide_etrax100, - .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(hw.io_ports[IDE_DATA_OFFSET]); - if (hwif == NULL) - continue; - ide_init_port_data(hwif, hwif->index); - ide_init_port_hw(hwif, &hw); - hwif->mmio = 1; - hwif->set_pio_mode = &cris_set_pio_mode; - hwif->set_dma_mode = &cris_set_dma_mode; - 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->dma_host_set = &cris_dma_host_set; - hwif->ide_dma_end = &cris_dma_end; - hwif->dma_setup = &cris_dma_setup; - hwif->dma_exec_cmd = &cris_dma_exec_cmd; - hwif->ide_dma_test_irq = &cris_dma_test_irq; - hwif->dma_start = &cris_dma_start; - 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); - } -} - -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 4108ec4ffa7f..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,13 +171,11 @@ static inline void hwif_setup(ide_hwif_t *hwif) { default_hwif_iops(hwif); - hwif->mmio = 1; - 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) @@ -99,8 +194,7 @@ static int __init h8300_ide_init(void) hw_setup(&hw); - /* register if */ - hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]); + hwif = ide_find_port(); if (hwif == NULL) { printk(KERN_ERR "ide-h8300: IDE I/F register failed\n"); return -ENOENT; diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index e07b189f3ec8..9d3601fa5680 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -55,14 +55,22 @@ struct ide_acpi_hwif_link { /* note: adds function name and KERN_DEBUG */ #ifdef DEBUGGING #define DEBPRINT(fmt, args...) \ - printk(KERN_DEBUG "%s: " fmt, __FUNCTION__, ## args) + printk(KERN_DEBUG "%s: " fmt, __func__, ## args) #else #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) @@ -309,7 +317,7 @@ static int do_drive_get_GTF(ide_drive_t *drive, if (ACPI_FAILURE(status)) { printk(KERN_DEBUG "%s: Run _GTF error: status = 0x%x\n", - __FUNCTION__, status); + __func__, status); goto out; } @@ -335,7 +343,7 @@ static int do_drive_get_GTF(ide_drive_t *drive, out_obj->buffer.length % REGS_PER_GTF) { printk(KERN_ERR "%s: unexpected GTF length (%d) or addr (0x%p)\n", - __FUNCTION__, out_obj->buffer.length, + __func__, out_obj->buffer.length, out_obj->buffer.pointer); err = -ENOENT; kfree(output.pointer); @@ -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; } @@ -384,7 +392,7 @@ static int taskfile_load_raw(ide_drive_t *drive, err = ide_no_data_taskfile(drive, &args); if (err) printk(KERN_ERR "%s: ide_no_data_taskfile failed: %u\n", - __FUNCTION__, err); + __func__, err); return err; } @@ -422,7 +430,7 @@ static int do_drive_set_taskfiles(ide_drive_t *drive, if (gtf_length % REGS_PER_GTF) { printk(KERN_ERR "%s: unexpected GTF length (%d)\n", - __FUNCTION__, gtf_length); + __func__, gtf_length); goto out; } @@ -547,7 +555,7 @@ void ide_acpi_get_timing(ide_hwif_t *hwif) printk(KERN_ERR "%s: unexpected _GTM length (0x%x)[should be 0x%zx] or " "addr (0x%p)\n", - __FUNCTION__, out_obj->buffer.length, + __func__, out_obj->buffer.length, sizeof(struct GTM_buffer), out_obj->buffer.pointer); return; } @@ -710,6 +718,8 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif) for (i = 0; i < MAX_DRIVES; i++) { drive = &hwif->drives[i]; + memset(drive->acpidata, 0, sizeof(*drive->acpidata)); + if (!drive->present) continue; @@ -719,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 c8d0e8715997..fe9df38f62cc 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -13,8 +13,8 @@ * * Suggestions are welcome. Patches that work are more welcome though. ;-) * For those wishing to work on this driver, please be sure you download - * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI - * (SFF-8020i rev 2.6) standards. These documents can be obtained by + * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI + * (SFF-8020i rev 2.6) standards. These documents can be obtained by * anonymous ftp from: * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r10.pdf @@ -39,19 +39,20 @@ #include <linux/mutex.h> #include <linux/bcd.h> -#include <scsi/scsi.h> /* For SCSI -> ATAPI command conversion */ +/* For SCSI -> ATAPI command conversion */ +#include <scsi/scsi.h> -#include <asm/irq.h> -#include <asm/io.h> +#include <linux/irq.h> +#include <linux/io.h> #include <asm/byteorder.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/unaligned.h> #include "ide-cd.h" static DEFINE_MUTEX(idecd_ref_mutex); -#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref) +#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref) #define ide_cd_g(disk) \ container_of((disk)->private_data, struct cdrom_info, driver) @@ -77,19 +78,17 @@ static void ide_cd_put(struct cdrom_info *cd) mutex_unlock(&idecd_ref_mutex); } -/**************************************************************************** +/* * Generic packet command support and error handling routines. */ -/* Mark that we've seen a media change, and invalidate our internal - buffers. */ -static void cdrom_saw_media_change (ide_drive_t *drive) +/* Mark that we've seen a media change and invalidate our internal buffers. */ +static void cdrom_saw_media_change(ide_drive_t *drive) { struct cdrom_info *cd = drive->driver_data; cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED; cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID; - cd->nsectors_buffered = 0; } static int cdrom_log_sense(ide_drive_t *drive, struct request *rq, @@ -101,66 +100,65 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq, return 0; switch (sense->sense_key) { - case NO_SENSE: case RECOVERED_ERROR: - break; - case NOT_READY: - /* - * don't care about tray state messages for - * e.g. capacity commands or in-progress or - * becoming ready - */ - if (sense->asc == 0x3a || sense->asc == 0x04) - break; - log = 1; - break; - case ILLEGAL_REQUEST: - /* - * don't log START_STOP unit with LoEj set, since - * we cannot reliably check if drive can auto-close - */ - if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24) - break; - log = 1; - break; - case UNIT_ATTENTION: - /* - * Make good and sure we've seen this potential media - * change. Some drives (i.e. Creative) fail to present - * the correct sense key in the error register. - */ - cdrom_saw_media_change(drive); + case NO_SENSE: + case RECOVERED_ERROR: + break; + case NOT_READY: + /* + * don't care about tray state messages for e.g. capacity + * commands or in-progress or becoming ready + */ + if (sense->asc == 0x3a || sense->asc == 0x04) break; - default: - log = 1; + log = 1; + break; + case ILLEGAL_REQUEST: + /* + * don't log START_STOP unit with LoEj set, since we cannot + * reliably check if drive can auto-close + */ + if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24) break; + log = 1; + break; + case UNIT_ATTENTION: + /* + * Make good and sure we've seen this potential media change. + * Some drives (i.e. Creative) fail to present the correct sense + * key in the error register. + */ + cdrom_saw_media_change(drive); + break; + default: + log = 1; + break; } return log; } -static -void cdrom_analyze_sense_data(ide_drive_t *drive, +static void cdrom_analyze_sense_data(ide_drive_t *drive, struct request *failed_command, struct request_sense *sense) { 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)) return; /* - * If a read toc is executed for a CD-R or CD-RW medium where - * the first toc has not been recorded yet, it will fail with - * 05/24/00 (which is a confusing error) + * If a read toc is executed for a CD-R or CD-RW medium where the first + * toc has not been recorded yet, it will fail with 05/24/00 (which is a + * confusing error) */ if (failed_command && failed_command->cmd[0] == GPCMD_READ_TOC_PMA_ATIP) if (sense->sense_key == 0x05 && sense->asc == 0x24) return; - if (sense->error_code == 0x70) { /* Current Error */ - switch(sense->sense_key) { + /* current error */ + if (sense->error_code == 0x70) { + switch (sense->sense_key) { case MEDIUM_ERROR: case VOLUME_OVERFLOW: case ILLEGAL_REQUEST: @@ -174,29 +172,23 @@ 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) - sector <<= 2; /* Device sector size is 2K */ - sector &= ~(bio_sectors -1); - valid = (sector - failed_command->sector) << 9; + /* device sector size is 2K */ + sector <<= 2; + + bio_sectors = max(bio_sectors(failed_command->bio), 4U); + sector &= ~(bio_sectors - 1); - if (valid < 0) - valid = 0; if (sector < get_capacity(info->disk) && - drive->probed_capacity - sector < 4 * 75) { + drive->probed_capacity - sector < 4 * 75) set_capacity(info->disk, sector); - } - } - } + } + } ide_cd_log_error(drive->name, failed_command, sense); } -/* - * Initialize a ide-cd packet command request - */ +/* Initialize a ide-cd packet command request */ void ide_cd_init_rq(ide_drive_t *drive, struct request *rq) { struct cdrom_info *cd = drive->driver_data; @@ -220,7 +212,8 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense, rq->data = sense; rq->cmd[0] = GPCMD_REQUEST_SENSE; - rq->cmd[4] = rq->data_len = 18; + rq->cmd[4] = 18; + rq->data_len = 18; rq->cmd_type = REQ_TYPE_SENSE; @@ -230,7 +223,7 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense, (void) ide_do_drive_cmd(drive, rq, ide_preempt); } -static void cdrom_end_request (ide_drive_t *drive, int uptodate) +static void cdrom_end_request(ide_drive_t *drive, int uptodate) { struct request *rq = HWGROUP(drive)->rq; int nsectors = rq->hard_cur_sectors; @@ -252,7 +245,7 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate) } cdrom_analyze_sense_data(drive, failed, sense); /* - * now end failed request + * now end the failed request */ if (blk_fs_request(failed)) { if (ide_end_dequeued_request(drive, failed, 0, @@ -280,21 +273,24 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate) ide_end_request(drive, uptodate, nsectors); } -static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 stat) +static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 st) { - if (stat & 0x80) + if (st & 0x80) return; - ide_dump_status(drive, msg, stat); + ide_dump_status(drive, msg, st); } -/* Returns 0 if the request should be continued. - Returns 1 if the request was ended. */ +/* + * Returns: + * 0: if the request should be continued. + * 1: if the request was ended. + */ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) { struct request *rq = HWGROUP(drive)->rq; int stat, err, sense_key; - - /* Check for errors. */ + + /* check for errors */ stat = ide_read_status(drive); if (stat_ret) @@ -303,20 +299,22 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) if (OK_STAT(stat, good_stat, BAD_R_STAT)) return 0; - /* Get the IDE error register. */ + /* get the IDE error register */ err = ide_read_error(drive); sense_key = err >> 4; if (rq == NULL) { - printk("%s: missing rq in cdrom_decode_status\n", drive->name); + printk(KERN_ERR "%s: missing rq in %s\n", + drive->name, __func__); return 1; } if (blk_sense_request(rq)) { - /* We got an error trying to get sense info - from the drive (probably while trying - to recover from a former error). Just give up. */ - + /* + * We got an error trying to get sense info from the drive + * (probably while trying to recover from a former error). + * Just give up. + */ rq->cmd_flags |= REQ_FAILED; cdrom_end_request(drive, 0); ide_error(drive, "request sense failure", stat); @@ -332,28 +330,27 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) if (blk_pc_request(rq) && !rq->errors) rq->errors = SAM_STAT_CHECK_CONDITION; - /* Check for tray open. */ + /* check for tray open */ if (sense_key == NOT_READY) { - cdrom_saw_media_change (drive); + cdrom_saw_media_change(drive); } else if (sense_key == UNIT_ATTENTION) { - /* Check for media change. */ - cdrom_saw_media_change (drive); - /*printk("%s: media changed\n",drive->name);*/ + /* check for media change */ + cdrom_saw_media_change(drive); return 0; - } else if ((sense_key == ILLEGAL_REQUEST) && - (rq->cmd[0] == GPCMD_START_STOP_UNIT)) { - /* - * Don't print error message for this condition-- - * SFF8090i indicates that 5/24/00 is the correct - * response to a request to close the tray if the - * drive doesn't have that capability. - * cdrom_log_sense() knows this! - */ + } else if (sense_key == ILLEGAL_REQUEST && + rq->cmd[0] == GPCMD_START_STOP_UNIT) { + /* + * Don't print error message for this condition-- + * SFF8090i indicates that 5/24/00 is the correct + * response to a request to close the tray if the + * drive doesn't have that capability. + * cdrom_log_sense() knows this! + */ } else if (!(rq->cmd_flags & REQ_QUIET)) { - /* Otherwise, print an error. */ + /* otherwise, print an error */ ide_dump_status(drive, "packet command error", stat); } - + rq->cmd_flags |= REQ_FAILED; /* @@ -366,27 +363,30 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) } else if (blk_fs_request(rq)) { int do_end_request = 0; - /* Handle errors from READ and WRITE requests. */ + /* handle errors from READ and WRITE requests */ if (blk_noretry_request(rq)) do_end_request = 1; if (sense_key == NOT_READY) { - /* Tray open. */ + /* tray open */ if (rq_data_dir(rq) == READ) { - cdrom_saw_media_change (drive); + cdrom_saw_media_change(drive); - /* Fail the request. */ - printk ("%s: tray open\n", drive->name); + /* fail the request */ + printk(KERN_ERR "%s: tray open\n", drive->name); do_end_request = 1; } else { struct cdrom_info *info = drive->driver_data; - /* allow the drive 5 seconds to recover, some + /* + * Allow the drive 5 seconds to recover, some * devices will return this error while flushing - * data from cache */ + * data from cache. + */ if (!rq->errors) - info->write_timeout = jiffies + ATAPI_WAIT_WRITE_BUSY; + info->write_timeout = jiffies + + ATAPI_WAIT_WRITE_BUSY; rq->errors = 1; if (time_after(jiffies, info->write_timeout)) do_end_request = 1; @@ -394,59 +394,68 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) unsigned long flags; /* - * take a breather relying on the - * unplug timer to kick us again + * take a breather relying on the unplug + * timer to kick us again */ spin_lock_irqsave(&ide_lock, flags); blk_plug_device(drive->queue); - spin_unlock_irqrestore(&ide_lock,flags); + spin_unlock_irqrestore(&ide_lock, + flags); return 1; } } } else if (sense_key == UNIT_ATTENTION) { - /* Media change. */ - cdrom_saw_media_change (drive); + /* media change */ + cdrom_saw_media_change(drive); - /* Arrange to retry the request. - But be sure to give up if we've retried - too many times. */ + /* + * Arrange to retry the request but be sure to give up + * if we've retried too many times. + */ if (++rq->errors > ERROR_MAX) do_end_request = 1; } else if (sense_key == ILLEGAL_REQUEST || sense_key == DATA_PROTECT) { - /* No point in retrying after an illegal - request or data protect error.*/ - ide_dump_status_no_sense (drive, "command error", stat); + /* + * No point in retrying after an illegal request or data + * protect error. + */ + ide_dump_status_no_sense(drive, "command error", stat); do_end_request = 1; } else if (sense_key == MEDIUM_ERROR) { - /* No point in re-trying a zillion times on a bad - * sector... If we got here the error is not correctable */ - ide_dump_status_no_sense (drive, "media error (bad sector)", stat); + /* + * No point in re-trying a zillion times on a bad + * sector. If we got here the error is not correctable. + */ + ide_dump_status_no_sense(drive, + "media error (bad sector)", + stat); do_end_request = 1; } else if (sense_key == BLANK_CHECK) { - /* Disk appears blank ?? */ - ide_dump_status_no_sense (drive, "media error (blank)", stat); + /* disk appears blank ?? */ + ide_dump_status_no_sense(drive, "media error (blank)", + stat); do_end_request = 1; } else if ((err & ~ABRT_ERR) != 0) { - /* Go to the default handler - for other errors. */ + /* go to the default handler for other errors */ ide_error(drive, "cdrom_decode_status", stat); return 1; } else if ((++rq->errors > ERROR_MAX)) { - /* We've racked up too many retries. Abort. */ + /* we've racked up too many retries, abort */ do_end_request = 1; } - /* End a request through request sense analysis when we have - sense data. We need this in order to perform end of media - processing */ - + /* + * End a request through request sense analysis when we have + * sense data. We need this in order to perform end of media + * processing. + */ if (do_end_request) goto end_request; /* - * If we got a CHECK_CONDITION status, - * queue a request sense command. + * If we got a CHECK_CONDITION status, queue + * a request sense command. */ if (stat & ERR_STAT) cdrom_queue_request_sense(drive, NULL, NULL); @@ -455,7 +464,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) cdrom_end_request(drive, 0); } - /* Retry, or handle the next request. */ + /* retry, or handle the next request */ return 1; end_request: @@ -480,35 +489,37 @@ static int cdrom_timer_expiry(ide_drive_t *drive) unsigned long wait = 0; /* - * Some commands are *slow* and normally take a long time to - * complete. Usually we can use the ATAPI "disconnect" to bypass - * this, but not all commands/drives support that. Let - * ide_timer_expiry keep polling us for these. + * Some commands are *slow* and normally take a long time to complete. + * Usually we can use the ATAPI "disconnect" to bypass this, but not all + * commands/drives support that. Let ide_timer_expiry keep polling us + * for these. */ switch (rq->cmd[0]) { - case GPCMD_BLANK: - case GPCMD_FORMAT_UNIT: - case GPCMD_RESERVE_RZONE_TRACK: - case GPCMD_CLOSE_TRACK: - case GPCMD_FLUSH_CACHE: - wait = ATAPI_WAIT_PC; - break; - default: - if (!(rq->cmd_flags & REQ_QUIET)) - printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n", rq->cmd[0]); - wait = 0; - break; + case GPCMD_BLANK: + case GPCMD_FORMAT_UNIT: + case GPCMD_RESERVE_RZONE_TRACK: + case GPCMD_CLOSE_TRACK: + case GPCMD_FLUSH_CACHE: + wait = ATAPI_WAIT_PC; + break; + default: + if (!(rq->cmd_flags & REQ_QUIET)) + printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n", + rq->cmd[0]); + wait = 0; + break; } return wait; } -/* Set up the device registers for transferring a packet command on DEV, - expecting to later transfer XFERLEN bytes. HANDLER is the routine - which actually transfers the command to the drive. If this is a - drq_interrupt device, this routine will arrange for HANDLER to be - called when the interrupt from the drive arrives. Otherwise, HANDLER - will be called immediately after the drive is prepared for the transfer. */ - +/* + * Set up the device registers for transferring a packet command on DEV, + * expecting to later transfer XFERLEN bytes. HANDLER is the routine + * which actually transfers the command to the drive. If this is a + * drq_interrupt device, this routine will arrange for HANDLER to be + * called when the interrupt from the drive arrives. Otherwise, HANDLER + * will be called immediately after the drive is prepared for the transfer. + */ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, int xferlen, ide_handler_t *handler) @@ -517,15 +528,15 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, struct cdrom_info *info = drive->driver_data; ide_hwif_t *hwif = drive->hwif; - /* Wait for the controller to be idle. */ + /* wait for the controller to be idle */ if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY)) return startstop; /* FIXME: for Virtual DMA we must check harder */ if (info->dma) - info->dma = !hwif->dma_setup(drive); + info->dma = !hwif->dma_ops->dma_setup(drive); - /* Set up the controller registers. */ + /* set up the controller registers */ ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL | IDE_TFLAG_NO_SELECT_MASK, xferlen, info->dma); @@ -535,28 +546,24 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, drive->waiting_for_dma = 0; /* packet command */ - ide_execute_command(drive, WIN_PACKETCMD, handler, ATAPI_WAIT_PC, cdrom_timer_expiry); + ide_execute_command(drive, WIN_PACKETCMD, handler, + 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, IDE_COMMAND_REG); - ndelay(400); - spin_unlock_irqrestore(&ide_lock, flags); + ide_execute_pkt_cmd(drive); return (*handler) (drive); } } -/* Send a packet command to DRIVE described by CMD_BUF and CMD_LEN. - The device registers must have already been prepared - by cdrom_start_packet_command. - HANDLER is the interrupt handler to call when the command completes - or there's data ready. */ +/* + * Send a packet command to DRIVE described by CMD_BUF and CMD_LEN. The device + * registers must have already been prepared by cdrom_start_packet_command. + * HANDLER is the interrupt handler to call when the command completes or + * there's data ready. + */ #define ATAPI_MIN_CDB_BYTES 12 -static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, +static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive, struct request *rq, ide_handler_t *handler) { @@ -566,24 +573,26 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, ide_startstop_t startstop; if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) { - /* Here we should have been called after receiving an interrupt - from the device. DRQ should how be set. */ + /* + * Here we should have been called after receiving an interrupt + * from the device. DRQ should how be set. + */ - /* Check for errors. */ + /* check for errors */ if (cdrom_decode_status(drive, DRQ_STAT, NULL)) return ide_stopped; - /* Ok, next interrupt will be DMA interrupt. */ + /* ok, next interrupt will be DMA interrupt */ if (info->dma) drive->waiting_for_dma = 1; } else { - /* Otherwise, we must wait for DRQ to get set. */ + /* otherwise, we must wait for DRQ to get set */ if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) return startstop; } - /* Arm the interrupt handler. */ + /* arm the interrupt handler */ ide_set_handler(drive, handler, rq->timeout, cdrom_timer_expiry); /* ATAPI commands get padded out to 12 bytes minimum */ @@ -591,25 +600,24 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, if (cmd_len < ATAPI_MIN_CDB_BYTES) cmd_len = ATAPI_MIN_CDB_BYTES; - /* Send the command to the device. */ - HWIF(drive)->atapi_output_bytes(drive, rq->cmd, cmd_len); + /* send the command to the device */ + hwif->output_data(drive, NULL, rq->cmd, cmd_len); - /* Start the DMA if need be */ + /* start the DMA if need be */ if (info->dma) - hwif->dma_start(drive); + hwif->dma_ops->dma_start(drive); return ide_started; } -/**************************************************************************** +/* * Block read functions. */ - 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); } } @@ -619,53 +627,12 @@ 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--; } } /* - * Buffer up to SECTORS_TO_TRANSFER sectors from the drive in our sector - * buffer. Once the first sector is added, any subsequent sectors are - * assumed to be continuous (until the buffer is cleared). For the first - * sector added, SECTOR is its sector number. (SECTOR is then ignored until - * the buffer is cleared.) - */ -static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector, - int sectors_to_transfer) -{ - struct cdrom_info *info = drive->driver_data; - - /* Number of sectors to read into the buffer. */ - int sectors_to_buffer = min_t(int, sectors_to_transfer, - (SECTOR_BUFFER_SIZE >> SECTOR_BITS) - - info->nsectors_buffered); - - char *dest; - - /* If we couldn't get a buffer, don't try to buffer anything... */ - if (info->buffer == NULL) - sectors_to_buffer = 0; - - /* If this is the first sector in the buffer, remember its number. */ - if (info->nsectors_buffered == 0) - info->sector_buffered = sector; - - /* Read the data into the buffer. */ - dest = info->buffer + info->nsectors_buffered * SECTOR_SIZE; - while (sectors_to_buffer > 0) { - HWIF(drive)->atapi_input_bytes(drive, dest, SECTOR_SIZE); - --sectors_to_buffer; - --sectors_to_transfer; - ++info->nsectors_buffered; - dest += SECTOR_SIZE; - } - - /* Throw away any remaining data. */ - ide_cd_drain_data(drive, sectors_to_transfer); -} - -/* * Check the contents of the interrupt reason register from the cdrom * and attempt to recover if there are problems. Returns 0 if everything's * ok; nonzero if the request has been terminated. @@ -683,22 +650,23 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq, ide_hwif_t *hwif = drive->hwif; xfer_func_t *xf; - /* Whoops... */ + /* whoops... */ printk(KERN_ERR "%s: %s: wrong transfer direction!\n", - drive->name, __FUNCTION__); + 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) { - /* Some drives (ASUS) seem to tell us that status - * info is available. just get it and ignore. + /* + * Some drives (ASUS) seem to tell us that status info is + * available. Just get it and ignore. */ (void)ide_read_status(drive); return 0; } else { - /* Drive wants a command packet, or invalid ireason... */ + /* drive wants a command packet, or invalid ireason... */ printk(KERN_ERR "%s: %s: bad interrupt reason 0x%02x\n", - drive->name, __FUNCTION__, ireason); + drive->name, __func__, ireason); } if (rq->cmd_type == REQ_TYPE_ATA_PC) @@ -720,7 +688,7 @@ static int ide_cd_check_transfer_size(ide_drive_t *drive, int len) return 0; printk(KERN_ERR "%s: %s: Bad transfer size %d\n", - drive->name, __FUNCTION__, len); + drive->name, __func__, len); if (cd->cd_flags & IDE_CD_FLAG_LIMIT_NFRAMES) printk(KERN_ERR " This drive is not supported by " @@ -733,72 +701,13 @@ static int ide_cd_check_transfer_size(ide_drive_t *drive, int len) return 1; } -/* - * Try to satisfy some of the current read request from our cached data. - * Returns nonzero if the request has been completed, zero otherwise. - */ -static int cdrom_read_from_buffer (ide_drive_t *drive) -{ - struct cdrom_info *info = drive->driver_data; - struct request *rq = HWGROUP(drive)->rq; - unsigned short sectors_per_frame; - - sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS; - - /* Can't do anything if there's no buffer. */ - if (info->buffer == NULL) return 0; - - /* Loop while this request needs data and the next block is present - in our cache. */ - while (rq->nr_sectors > 0 && - rq->sector >= info->sector_buffered && - rq->sector < info->sector_buffered + info->nsectors_buffered) { - if (rq->current_nr_sectors == 0) - cdrom_end_request(drive, 1); - - memcpy (rq->buffer, - info->buffer + - (rq->sector - info->sector_buffered) * SECTOR_SIZE, - SECTOR_SIZE); - rq->buffer += SECTOR_SIZE; - --rq->current_nr_sectors; - --rq->nr_sectors; - ++rq->sector; - } - - /* If we've satisfied the current request, - terminate it successfully. */ - if (rq->nr_sectors == 0) { - cdrom_end_request(drive, 1); - return -1; - } - - /* Move on to the next buffer if needed. */ - if (rq->current_nr_sectors == 0) - cdrom_end_request(drive, 1); - - /* If this condition does not hold, then the kluge i use to - represent the number of sectors to skip at the start of a transfer - will fail. I think that this will never happen, but let's be - paranoid and check. */ - if (rq->current_nr_sectors < bio_cur_sectors(rq->bio) && - (rq->sector & (sectors_per_frame - 1))) { - printk(KERN_ERR "%s: cdrom_read_from_buffer: buffer botch (%ld)\n", - drive->name, (long)rq->sector); - cdrom_end_request(drive, 0); - return -1; - } - - return 0; -} - static ide_startstop_t cdrom_newpc_intr(ide_drive_t *); /* - * Routine to send a read/write packet command to the drive. - * This is usually called directly from cdrom_start_{read,write}(). - * However, for drq_interrupt devices, it is called from an interrupt - * when the drive is ready to accept the command. + * Routine to send a read/write packet command to the drive. This is usually + * called directly from cdrom_start_{read,write}(). However, for drq_interrupt + * devices, it is called from an interrupt when the drive is ready to accept + * the command. */ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive) { @@ -820,11 +729,11 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive) * is larger than the buffer size. */ if (nskip > 0) { - /* Sanity check... */ + /* sanity check... */ if (rq->current_nr_sectors != bio_cur_sectors(rq->bio)) { printk(KERN_ERR "%s: %s: buffer botch (%u)\n", - drive->name, __FUNCTION__, + drive->name, __func__, rq->current_nr_sectors); cdrom_end_request(drive, 0); return ide_stopped; @@ -837,10 +746,10 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive) /* the immediate bit */ rq->cmd[1] = 1 << 3; #endif - /* Set up the command */ + /* set up the command */ rq->timeout = ATAPI_WAIT_PC; - /* Send the command to the drive and return. */ + /* send the command to the drive and return */ return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr); } @@ -848,7 +757,7 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive) #define IDECD_SEEK_TIMER (5 * WAIT_MIN_SLEEP) /* 100 ms */ #define IDECD_SEEK_TIMEOUT (2 * WAIT_CMD) /* 20 sec */ -static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive) +static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive) { struct cdrom_info *info = drive->driver_data; int stat; @@ -860,19 +769,13 @@ static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive) info->cd_flags |= IDE_CD_FLAG_SEEKING; if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) { - if (--retry == 0) { - /* - * this condition is far too common, to bother - * users about it - */ - /* printk("%s: disabled DSC seek overlap\n", drive->name);*/ + if (--retry == 0) drive->dsc_overlap = 0; - } } return ide_stopped; } -static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive) +static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive) { struct request *rq = HWGROUP(drive)->rq; sector_t frame = rq->sector; @@ -887,36 +790,40 @@ static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive) return cdrom_transfer_packet_command(drive, rq, &cdrom_seek_intr); } -static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block) +static ide_startstop_t cdrom_start_seek(ide_drive_t *drive, unsigned int block) { struct cdrom_info *info = drive->driver_data; info->dma = 0; info->start_seek = jiffies; - return cdrom_start_packet_command(drive, 0, cdrom_start_seek_continuation); + return cdrom_start_packet_command(drive, 0, + cdrom_start_seek_continuation); } -/* Fix up a possibly partially-processed request so that we can - start it over entirely, or even put it back on the request queue. */ -static void restore_request (struct request *rq) +/* + * Fix up a possibly partially-processed request so that we can start it over + * entirely, or even put it back on the request queue. + */ +static void restore_request(struct request *rq) { if (rq->buffer != bio_data(rq->bio)) { - sector_t n = (rq->buffer - (char *) bio_data(rq->bio)) / SECTOR_SIZE; + sector_t n = + (rq->buffer - (char *)bio_data(rq->bio)) / SECTOR_SIZE; rq->buffer = bio_data(rq->bio); rq->nr_sectors += n; rq->sector -= n; } - rq->hard_cur_sectors = rq->current_nr_sectors = bio_cur_sectors(rq->bio); + rq->current_nr_sectors = bio_cur_sectors(rq->bio); + rq->hard_cur_sectors = rq->current_nr_sectors; rq->hard_nr_sectors = rq->nr_sectors; rq->hard_sector = rq->sector; rq->q->prep_rq_fn(rq->q, rq); } -/**************************************************************************** - * Execute all other packet commands. +/* + * All other packet commands. */ - static void ide_cd_request_sense_fixup(struct request *rq) { /* @@ -940,7 +847,7 @@ int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq) if (rq->sense == NULL) rq->sense = &sense; - /* Start of retry loop. */ + /* start of retry loop */ do { int error; unsigned long time = jiffies; @@ -949,41 +856,45 @@ int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq) error = ide_do_drive_cmd(drive, rq, ide_wait); time = jiffies - time; - /* FIXME: we should probably abort/retry or something - * in case of failure */ + /* + * FIXME: we should probably abort/retry or something in case of + * failure. + */ if (rq->cmd_flags & REQ_FAILED) { - /* The request failed. Retry if it was due to a unit - attention status - (usually means media was changed). */ + /* + * The request failed. Retry if it was due to a unit + * attention status (usually means media was changed). + */ struct request_sense *reqbuf = rq->sense; if (reqbuf->sense_key == UNIT_ATTENTION) cdrom_saw_media_change(drive); else if (reqbuf->sense_key == NOT_READY && reqbuf->asc == 4 && reqbuf->ascq != 4) { - /* The drive is in the process of loading - a disk. Retry, but wait a little to give - the drive time to complete the load. */ + /* + * The drive is in the process of loading + * a disk. Retry, but wait a little to give + * the drive time to complete the load. + */ ssleep(2); } else { - /* Otherwise, don't retry. */ + /* otherwise, don't retry */ retries = 0; } --retries; } - /* End of retry loop. */ + /* end of retry loop */ } while ((rq->cmd_flags & REQ_FAILED) && retries >= 0); - /* Return an error if the command failed. */ + /* return an error if the command failed */ return (rq->cmd_flags & REQ_FAILED) ? -EIO : 0; } /* - * Called from blk_end_request_callback() after the data of the request - * is completed and before the request is completed. - * By returning value '1', blk_end_request_callback() returns immediately - * without completing the request. + * Called from blk_end_request_callback() after the data of the request is + * completed and before the request itself is completed. By returning value '1', + * blk_end_request_callback() returns immediately without completing it. */ static int cdrom_newpc_intr_dummy_cb(struct request *rq) { @@ -992,6 +903,7 @@ static int cdrom_newpc_intr_dummy_cb(struct request *rq) static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) { + ide_hwif_t *hwif = drive->hwif; struct cdrom_info *info = drive->driver_data; struct request *rq = HWGROUP(drive)->rq; xfer_func_t *xferfunc; @@ -1001,11 +913,11 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) unsigned int timeout; u8 lowcyl, highcyl; - /* Check for errors. */ + /* check for errors */ dma = info->dma; if (dma) { info->dma = 0; - dma_error = HWIF(drive)->ide_dma_end(drive); + dma_error = hwif->dma_ops->dma_end(drive); if (dma_error) { printk(KERN_ERR "%s: DMA %s error\n", drive->name, write ? "write" : "read"); @@ -1016,9 +928,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) if (cdrom_decode_status(drive, 0, &stat)) return ide_stopped; - /* - * using dma, transfer is complete now - */ + /* using dma, transfer is complete now */ if (dma) { if (dma_error) return ide_error(drive, "dma error", stat); @@ -1029,12 +939,10 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) goto end_request; } - /* - * ok we fall to pio :/ - */ - ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3; - lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG); - highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG); + /* ok we fall to pio :/ */ + 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); @@ -1042,9 +950,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) if (thislen > len) thislen = len; - /* - * If DRQ is clear, the command has completed. - */ + /* If DRQ is clear, the command has completed. */ if ((stat & DRQ_STAT) == 0) { if (blk_fs_request(rq)) { /* @@ -1055,7 +961,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) if (rq->current_nr_sectors > 0) { printk(KERN_ERR "%s: %s: data underrun " "(%d blocks)\n", - drive->name, __FUNCTION__, + drive->name, __func__, rq->current_nr_sectors); if (!write) rq->cmd_flags |= REQ_FAILED; @@ -1065,15 +971,13 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) return ide_stopped; } else if (!blk_pc_request(rq)) { ide_cd_request_sense_fixup(rq); - /* Complain if we still have data left to transfer. */ + /* complain if we still have data left to transfer */ uptodate = rq->data_len ? 0 : 1; } goto end_request; } - /* - * check which way to transfer data - */ + /* check which way to transfer data */ if (ide_cd_check_ireason(drive, rq, len, ireason, write)) return ide_stopped; @@ -1103,22 +1007,18 @@ 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 - */ + /* transfer data */ while (thislen > 0) { u8 *ptr = blk_fs_request(rq) ? NULL : rq->data; int blen = rq->data_len; - /* - * bio backed? - */ + /* bio backed? */ if (rq->bio) { if (blk_fs_request(rq)) { ptr = rq->buffer; @@ -1132,11 +1032,10 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) if (!ptr) { if (blk_fs_request(rq) && !write) /* - * If the buffers are full, cache the rest - * of the data in our internal buffer. + * If the buffers are full, pipe the rest into + * oblivion. */ - cdrom_buffer_sectors(drive, rq->sector, - thislen >> 9); + ide_cd_drain_data(drive, thislen >> 9); else { printk(KERN_ERR "%s: confused, missing data\n", drive->name); @@ -1150,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; @@ -1182,9 +1081,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) rq->sense_len += blen; } - /* - * pad, if necessary - */ + /* pad, if necessary */ if (!blk_fs_request(rq) && len > 0) ide_cd_pad_transfer(drive, xferfunc, len); @@ -1228,9 +1125,7 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) queue_hardsect_size(drive->queue) >> SECTOR_BITS; if (write) { - /* - * disk has become write protected - */ + /* disk has become write protected */ if (cd->disk->policy) { cdrom_end_request(drive, 0); return ide_stopped; @@ -1241,15 +1136,9 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) * weirdness which might be present in the request packet. */ restore_request(rq); - - /* Satisfy whatever we can of this request from our cache. */ - if (cdrom_read_from_buffer(drive)) - return ide_stopped; } - /* - * use DMA, if possible / writes *must* be hardware frame aligned - */ + /* use DMA, if possible / writes *must* be hardware frame aligned */ if ((rq->nr_sectors & (sectors_per_frame - 1)) || (rq->sector & (sectors_per_frame - 1))) { if (write) { @@ -1260,13 +1149,10 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) } else cd->dma = drive->using_dma; - /* Clear the local sector buffer. */ - cd->nsectors_buffered = 0; - if (write) cd->devinfo.media_written = 1; - /* Start sending the read/write request to the drive. */ + /* start sending the read/write request to the drive */ return cdrom_start_packet_command(drive, 32768, cdrom_start_rw_cont); } @@ -1291,12 +1177,11 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) info->dma = 0; - /* - * sg request - */ + /* sg request */ if (rq->bio) { int mask = drive->queue->dma_alignment; - unsigned long addr = (unsigned long) page_address(bio_page(rq->bio)); + unsigned long addr = + (unsigned long)page_address(bio_page(rq->bio)); info->dma = drive->using_dma; @@ -1310,15 +1195,16 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) info->dma = 0; } - /* Start sending the command to the drive. */ - return cdrom_start_packet_command(drive, rq->data_len, cdrom_do_newpc_cont); + /* start sending the command to the drive */ + return cdrom_start_packet_command(drive, rq->data_len, + cdrom_do_newpc_cont); } -/**************************************************************************** +/* * cdrom driver request routine. */ -static ide_startstop_t -ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block) +static ide_startstop_t ide_do_rw_cdrom(ide_drive_t *drive, struct request *rq, + sector_t block) { ide_startstop_t action; struct cdrom_info *info = drive->driver_data; @@ -1330,16 +1216,21 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block) if ((stat & SEEK_STAT) != SEEK_STAT) { if (elapsed < IDECD_SEEK_TIMEOUT) { - ide_stall_queue(drive, IDECD_SEEK_TIMER); + ide_stall_queue(drive, + IDECD_SEEK_TIMER); return ide_stopped; } - printk (KERN_ERR "%s: DSC timeout\n", drive->name); + printk(KERN_ERR "%s: DSC timeout\n", + drive->name); } info->cd_flags &= ~IDE_CD_FLAG_SEEKING; } - if ((rq_data_dir(rq) == READ) && IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) { + if (rq_data_dir(rq) == READ && + IDE_LARGE_SEEK(info->last_block, block, + IDECD_SEEK_THRESHOLD) && + drive->dsc_overlap) action = cdrom_start_seek(drive, block); - } else + else action = cdrom_start_rw(drive, rq); info->last_block = block; return action; @@ -1347,9 +1238,7 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block) rq->cmd_type == REQ_TYPE_ATA_PC) { return cdrom_do_block_pc(drive, rq); } else if (blk_special_request(rq)) { - /* - * right now this can only be a reset... - */ + /* right now this can only be a reset... */ cdrom_end_request(drive, 1); return ide_stopped; } @@ -1361,18 +1250,16 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block) -/**************************************************************************** +/* * Ioctl handling. * - * Routines which queue packet commands take as a final argument a pointer - * to a request_sense struct. If execution of the command results - * in an error with a CHECK CONDITION status, this structure will be filled - * with the results of the subsequent request sense command. The pointer - * can also be NULL, in which case no sense information is returned. + * Routines which queue packet commands take as a final argument a pointer to a + * request_sense struct. If execution of the command results in an error with a + * CHECK CONDITION status, this structure will be filled with the results of the + * subsequent request sense command. The pointer can also be NULL, in which case + * no sense information is returned. */ - -static -void msf_from_bcd (struct atapi_msf *msf) +static void msf_from_bcd(struct atapi_msf *msf) { msf->minute = BCD2BIN(msf->minute); msf->second = BCD2BIN(msf->second); @@ -1392,8 +1279,8 @@ int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense) req.cmd_flags |= REQ_QUIET; /* - * Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to - * switch CDs instead of supporting the LOAD_UNLOAD opcode. + * Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to switch CDs + * instead of supporting the LOAD_UNLOAD opcode. */ req.cmd[7] = cdi->sanyo_slot % 3; @@ -1469,36 +1356,39 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense) unsigned long sectors_per_frame = SECTORS_PER_FRAME; if (toc == NULL) { - /* Try to allocate space. */ + /* try to allocate space */ toc = kmalloc(sizeof(struct atapi_toc), GFP_KERNEL); if (toc == NULL) { - printk (KERN_ERR "%s: No cdrom TOC buffer!\n", drive->name); + printk(KERN_ERR "%s: No cdrom TOC buffer!\n", + drive->name); return -ENOMEM; } info->toc = toc; } - /* Check to see if the existing data is still valid. - If it is, just return. */ + /* + * Check to see if the existing data is still valid. If it is, + * just return. + */ (void) cdrom_check_status(drive, sense); if (info->cd_flags & IDE_CD_FLAG_TOC_VALID) return 0; - /* Try to get the total cdrom capacity and sector size. */ + /* try to get the total cdrom capacity and sector size */ stat = cdrom_read_capacity(drive, &toc->capacity, §ors_per_frame, sense); if (stat) toc->capacity = 0x1fffff; set_capacity(info->disk, toc->capacity * sectors_per_frame); - /* Save a private copy of te TOC capacity for error handling */ + /* save a private copy of the TOC capacity for error handling */ drive->probed_capacity = toc->capacity * sectors_per_frame; blk_queue_hardsect_size(drive->queue, sectors_per_frame << SECTOR_BITS); - /* First read just the header, so we know how long the TOC is. */ + /* first read just the header, so we know how long the TOC is */ stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr, sizeof(struct atapi_toc_header), sense); if (stat) @@ -1515,7 +1405,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense) if (ntracks > MAX_TRACKS) ntracks = MAX_TRACKS; - /* Now read the whole schmeer. */ + /* now read the whole schmeer */ stat = cdrom_read_tocentry(drive, toc->hdr.first_track, 1, 0, (char *)&toc->hdr, sizeof(struct atapi_toc_header) + @@ -1523,15 +1413,18 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense) sizeof(struct atapi_toc_entry), sense); if (stat && toc->hdr.first_track > 1) { - /* Cds with CDI tracks only don't have any TOC entries, - despite of this the returned values are - first_track == last_track = number of CDI tracks + 1, - so that this case is indistinguishable from the same - layout plus an additional audio track. - If we get an error for the regular case, we assume - a CDI without additional audio tracks. In this case - the readable TOC is empty (CDI tracks are not included) - and only holds the Leadout entry. Heiko Eißfeldt */ + /* + * Cds with CDI tracks only don't have any TOC entries, despite + * of this the returned values are + * first_track == last_track = number of CDI tracks + 1, + * so that this case is indistinguishable from the same layout + * plus an additional audio track. If we get an error for the + * regular case, we assume a CDI without additional audio + * tracks. In this case the readable TOC is empty (CDI tracks + * are not included) and only holds the Leadout entry. + * + * Heiko Eißfeldt. + */ ntracks = 0; stat = cdrom_read_tocentry(drive, CDROM_LEADOUT, 1, 0, (char *)&toc->hdr, @@ -1567,14 +1460,13 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense) toc->ent[i].track = BCD2BIN(toc->ent[i].track); msf_from_bcd(&toc->ent[i].addr.msf); } - toc->ent[i].addr.lba = msf_to_lba (toc->ent[i].addr.msf.minute, - toc->ent[i].addr.msf.second, - toc->ent[i].addr.msf.frame); + toc->ent[i].addr.lba = msf_to_lba(toc->ent[i].addr.msf.minute, + toc->ent[i].addr.msf.second, + toc->ent[i].addr.msf.frame); } - /* Read the multisession information. */ if (toc->hdr.first_track != CDROM_LEADOUT) { - /* Read the multisession information. */ + /* read the multisession information */ stat = cdrom_read_tocentry(drive, 0, 0, 1, (char *)&ms_tmp, sizeof(ms_tmp), sense); if (stat) @@ -1582,26 +1474,27 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense) toc->last_session_lba = be32_to_cpu(ms_tmp.ent.addr.lba); } else { - ms_tmp.hdr.first_track = ms_tmp.hdr.last_track = CDROM_LEADOUT; + ms_tmp.hdr.last_track = CDROM_LEADOUT; + ms_tmp.hdr.first_track = ms_tmp.hdr.last_track; toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */ } if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) { - /* Re-read multisession information using MSF format */ + /* re-read multisession information using MSF format */ stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp, sizeof(ms_tmp), sense); if (stat) return stat; - msf_from_bcd (&ms_tmp.ent.addr.msf); + msf_from_bcd(&ms_tmp.ent.addr.msf); toc->last_session_lba = msf_to_lba(ms_tmp.ent.addr.msf.minute, - ms_tmp.ent.addr.msf.second, + ms_tmp.ent.addr.msf.second, ms_tmp.ent.addr.msf.frame); } toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track); - /* Now try to get the total cdrom capacity. */ + /* now try to get the total cdrom capacity */ stat = cdrom_get_last_written(cdi, &last_written); if (!stat && (last_written > toc->capacity)) { toc->capacity = last_written; @@ -1626,7 +1519,8 @@ int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf) size -= ATAPI_CAPABILITIES_PAGE_PAD_SIZE; init_cdrom_command(&cgc, buf, size, CGC_DATA_UNKNOWN); - do { /* we seem to get stat=0x01,err=0x00 the first time (??) */ + do { + /* we seem to get stat=0x01,err=0x00 the first time (??) */ stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0); if (!stat) break; @@ -1677,7 +1571,7 @@ static struct cdrom_device_ops ide_cdrom_dops = { .generic_packet = ide_cdrom_packet, }; -static int ide_cdrom_register (ide_drive_t *drive, int nslots) +static int ide_cdrom_register(ide_drive_t *drive, int nslots) { struct cdrom_info *info = drive->driver_data; struct cdrom_device_info *devinfo = &info->devinfo; @@ -1695,8 +1589,7 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots) return register_cdrom(devinfo); } -static -int ide_cdrom_probe_capabilities (ide_drive_t *drive) +static int ide_cdrom_probe_capabilities(ide_drive_t *drive) { struct cdrom_info *cd = drive->driver_data; struct cdrom_device_info *cdi = &cd->devinfo; @@ -1710,7 +1603,8 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) if (drive->media == ide_optical) { cdi->mask &= ~(CDC_MO_DRIVE | CDC_RAM); - printk(KERN_ERR "%s: ATAPI magneto-optical drive\n", drive->name); + printk(KERN_ERR "%s: ATAPI magneto-optical drive\n", + drive->name); return nslots; } @@ -1721,11 +1615,10 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) } /* - * we have to cheat a little here. the packet will eventually - * be queued with ide_cdrom_packet(), which extracts the - * drive from cdi->handle. Since this device hasn't been - * registered with the Uniform layer yet, it can't do this. - * Same goes for cdi->ops. + * We have to cheat a little here. the packet will eventually be queued + * with ide_cdrom_packet(), which extracts the drive from cdi->handle. + * Since this device hasn't been registered with the Uniform layer yet, + * it can't do this. Same goes for cdi->ops. */ cdi->handle = drive; cdi->ops = &ide_cdrom_dops; @@ -1794,18 +1687,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) return nslots; } -#ifdef CONFIG_IDE_PROC_FS -static void ide_cdrom_add_settings(ide_drive_t *drive) -{ - ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); -} -#else -static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; } -#endif - -/* - * standard prep_rq_fn that builds 10 byte cmds - */ +/* standard prep_rq_fn that builds 10 byte cmds */ static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq) { int hard_sect = queue_hardsect_size(q); @@ -1844,9 +1726,7 @@ static int ide_cdrom_prep_pc(struct request *rq) { u8 *c = rq->cmd; - /* - * Transform 6-byte read/write commands to the 10-byte version - */ + /* transform 6-byte read/write commands to the 10-byte version */ if (c[0] == READ_6 || c[0] == WRITE_6) { c[8] = c[4]; c[5] = c[3]; @@ -1868,7 +1748,7 @@ static int ide_cdrom_prep_pc(struct request *rq) rq->errors = ILLEGAL_REQUEST; return BLKPREP_KILL; } - + return BLKPREP_OK; } @@ -1888,6 +1768,41 @@ struct cd_list_entry { unsigned int cd_flags; }; +#ifdef CONFIG_IDE_PROC_FS +static sector_t ide_cdrom_capacity(ide_drive_t *drive) +{ + unsigned long capacity, sectors_per_frame; + + if (cdrom_read_capacity(drive, &capacity, §ors_per_frame, NULL)) + return 0; + + return capacity * sectors_per_frame; +} + +static int proc_idecd_read_capacity(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + ide_drive_t *drive = data; + int len; + + len = sprintf(page, "%llu\n", (long long)ide_cdrom_capacity(drive)); + PROC_IDE_READ_RETURN(page, start, off, count, eof, len); +} + +static ide_proc_entry_t idecd_proc[] = { + { "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL }, + { NULL, 0, NULL, NULL } +}; + +static void ide_cdrom_add_settings(ide_drive_t *drive) +{ + ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, + &drive->dsc_overlap, NULL); +} +#else +static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; } +#endif + static const struct cd_list_entry ide_cd_quirks_list[] = { /* Limit transfer size per interrupt. */ { "SAMSUNG CD-ROM SCR-2430", NULL, IDE_CD_FLAG_LIMIT_NFRAMES }, @@ -1945,8 +1860,7 @@ static unsigned int ide_cd_flags(struct hd_driveid *id) return 0; } -static -int ide_cdrom_setup (ide_drive_t *drive) +static int ide_cdrom_setup(ide_drive_t *drive) { struct cdrom_info *cd = drive->driver_data; struct cdrom_device_info *cdi = &cd->devinfo; @@ -1975,21 +1889,19 @@ int ide_cdrom_setup (ide_drive_t *drive) id->fw_rev[4] == '1' && id->fw_rev[6] <= '2') cd->cd_flags |= IDE_CD_FLAG_TOCTRACKS_AS_BCD; else if (cd->cd_flags & IDE_CD_FLAG_SANYO_3CD) - cdi->sanyo_slot = 3; /* 3 => use CD in slot 0 */ + /* 3 => use CD in slot 0 */ + cdi->sanyo_slot = 3; - nslots = ide_cdrom_probe_capabilities (drive); + nslots = ide_cdrom_probe_capabilities(drive); - /* - * set correct block size - */ + /* 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: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name); + printk(KERN_ERR "%s: %s failed to register device with the" + " cdrom driver.\n", drive->name, __func__); cd->devinfo.handle = NULL; return 1; } @@ -1997,19 +1909,6 @@ int ide_cdrom_setup (ide_drive_t *drive) return 0; } -#ifdef CONFIG_IDE_PROC_FS -static -sector_t ide_cdrom_capacity (ide_drive_t *drive) -{ - unsigned long capacity, sectors_per_frame; - - if (cdrom_read_capacity(drive, &capacity, §ors_per_frame, NULL)) - return 0; - - return capacity * sectors_per_frame; -} -#endif - static void ide_cd_remove(ide_drive_t *drive) { struct cdrom_info *info = drive->driver_data; @@ -2028,11 +1927,9 @@ static void ide_cd_release(struct kref *kref) ide_drive_t *drive = info->drive; struct gendisk *g = info->disk; - kfree(info->buffer); kfree(info->toc); - if (devinfo->handle == drive && unregister_cdrom(devinfo)) - printk(KERN_ERR "%s: %s failed to unregister device from the cdrom " - "driver.\n", __FUNCTION__, drive->name); + if (devinfo->handle == drive) + unregister_cdrom(devinfo); drive->dsc_overlap = 0; drive->driver_data = NULL; blk_queue_prep_rq(drive->queue, NULL); @@ -2043,23 +1940,6 @@ static void ide_cd_release(struct kref *kref) static int ide_cd_probe(ide_drive_t *); -#ifdef CONFIG_IDE_PROC_FS -static int proc_idecd_read_capacity - (char *page, char **start, off_t off, int count, int *eof, void *data) -{ - ide_drive_t *drive = data; - int len; - - len = sprintf(page,"%llu\n", (long long)ide_cdrom_capacity(drive)); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - -static ide_proc_entry_t idecd_proc[] = { - { "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL }, - { NULL, 0, NULL, NULL } -}; -#endif - static ide_driver_t ide_cdrom_driver = { .gen_driver = { .owner = THIS_MODULE, @@ -2080,20 +1960,17 @@ static ide_driver_t ide_cdrom_driver = { #endif }; -static int idecd_open(struct inode * inode, struct file * file) +static int idecd_open(struct inode *inode, struct file *file) { struct gendisk *disk = inode->i_bdev->bd_disk; struct cdrom_info *info; int rc = -ENOMEM; - if (!(info = ide_cd_get(disk))) + info = ide_cd_get(disk); + if (!info) return -ENXIO; - if (!info->buffer) - info->buffer = kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL|__GFP_REPEAT); - - if (info->buffer) - rc = cdrom_open(&info->devinfo, inode, file); + rc = cdrom_open(&info->devinfo, inode, file); if (rc < 0) ide_cd_put(info); @@ -2101,12 +1978,12 @@ static int idecd_open(struct inode * inode, struct file * file) return rc; } -static int idecd_release(struct inode * inode, struct file * file) +static int idecd_release(struct inode *inode, struct file *file) { struct gendisk *disk = inode->i_bdev->bd_disk; struct cdrom_info *info = ide_cd_g(disk); - cdrom_release (&info->devinfo, file); + cdrom_release(&info->devinfo, file); ide_cd_put(info); @@ -2138,7 +2015,7 @@ static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg) struct packet_command cgc; char buffer[16]; int stat; - char spindown; + char spindown; init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN); @@ -2147,12 +2024,12 @@ static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg) return stat; spindown = buffer[11] & 0x0f; - if (copy_to_user((void __user *)arg, &spindown, sizeof (char))) + if (copy_to_user((void __user *)arg, &spindown, sizeof(char))) return -EFAULT; return 0; } -static int idecd_ioctl (struct inode *inode, struct file *file, +static int idecd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct block_device *bdev = inode->i_bdev; @@ -2160,13 +2037,13 @@ static int idecd_ioctl (struct inode *inode, struct file *file, int err; switch (cmd) { - case CDROMSETSPINDOWN: + case CDROMSETSPINDOWN: return idecd_set_spindown(&info->devinfo, arg); - case CDROMGETSPINDOWN: + case CDROMGETSPINDOWN: return idecd_get_spindown(&info->devinfo, arg); default: break; - } + } err = generic_ide_ioctl(info->drive, file, bdev, cmd, arg); if (err == -EINVAL) @@ -2192,16 +2069,16 @@ static int idecd_revalidate_disk(struct gendisk *disk) } static struct block_device_operations idecd_ops = { - .owner = THIS_MODULE, - .open = idecd_open, - .release = idecd_release, - .ioctl = idecd_ioctl, - .media_changed = idecd_media_changed, - .revalidate_disk= idecd_revalidate_disk + .owner = THIS_MODULE, + .open = idecd_open, + .release = idecd_release, + .ioctl = idecd_ioctl, + .media_changed = idecd_media_changed, + .revalidate_disk = idecd_revalidate_disk }; -/* options */ -static char *ignore = NULL; +/* module options */ +static char *ignore; module_param(ignore, charp, 0400); MODULE_DESCRIPTION("ATAPI CD-ROM Driver"); @@ -2221,17 +2098,20 @@ static int ide_cd_probe(ide_drive_t *drive) /* skip drives that we were told to ignore */ if (ignore != NULL) { if (strstr(ignore, drive->name)) { - printk(KERN_INFO "ide-cd: ignoring drive %s\n", drive->name); + printk(KERN_INFO "ide-cd: ignoring drive %s\n", + drive->name); goto failed; } } if (drive->scsi) { - printk(KERN_INFO "ide-cd: passing drive %s to ide-scsi emulation.\n", drive->name); + printk(KERN_INFO "ide-cd: passing drive %s to ide-scsi " + "emulation.\n", drive->name); goto failed; } info = kzalloc(sizeof(struct cdrom_info), GFP_KERNEL); if (info == NULL) { - printk(KERN_ERR "%s: Can't allocate a cdrom structure\n", drive->name); + printk(KERN_ERR "%s: Can't allocate a cdrom structure\n", + drive->name); goto failed; } diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h index 22e3751a681e..a58801c4484d 100644 --- a/drivers/ide/ide-cd.h +++ b/drivers/ide/ide-cd.h @@ -119,10 +119,6 @@ struct cdrom_info { struct atapi_toc *toc; - unsigned long sector_buffered; - unsigned long nsectors_buffered; - unsigned char *buffer; - /* The result of the last successful request sense command on this device. */ struct request_sense sense_data; diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 39501d130256..8e08d083fce9 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -16,8 +16,6 @@ #define IDEDISK_VERSION "1.18" -//#define DEBUG - #include <linux/module.h> #include <linux/types.h> #include <linux/string.h> @@ -88,7 +86,7 @@ static void ide_disk_put(struct ide_disk_obj *idkp) * * It is called only once for each drive. */ -static int lba_capacity_is_ok (struct hd_driveid *id) +static int lba_capacity_is_ok(struct hd_driveid *id) { unsigned long lba_sects, chs_sects, head, tail; @@ -176,7 +174,8 @@ static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma) * __ide_do_rw_disk() issues READ and WRITE commands to a disk, * using LBA if supported, or CHS otherwise, to address sectors. */ -static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, sector_t block) +static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, + sector_t block) { ide_hwif_t *hwif = HWIF(drive); unsigned int dma = drive->using_dma; @@ -228,7 +227,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, tf->device = (block >> 8) & 0xf; } } else { - unsigned int sect,head,cyl,track; + unsigned int sect, head, cyl, track; + track = (int)block / drive->sect; sect = (int)block % drive->sect + 1; head = track % drive->head; @@ -271,7 +271,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, * 1073741822 == 549756 MB or 48bit addressing fake drive */ -static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block) +static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq, + sector_t block) { ide_hwif_t *hwif = HWIF(drive); @@ -452,7 +453,7 @@ static void idedisk_check_hpa(ide_drive_t *drive) * in above order (i.e., if value of higher priority is available, * reset will be ignored). */ -static void init_idedisk_capacity (ide_drive_t *drive) +static void init_idedisk_capacity(ide_drive_t *drive) { struct hd_driveid *id = drive->id; /* @@ -479,7 +480,7 @@ static void init_idedisk_capacity (ide_drive_t *drive) } } -static sector_t idedisk_capacity (ide_drive_t *drive) +static sector_t idedisk_capacity(ide_drive_t *drive) { return drive->capacity64 - drive->sect0; } @@ -524,10 +525,11 @@ static int proc_idedisk_read_cache int len; if (drive->id_read) - len = sprintf(out,"%i\n", drive->id->buf_size / 2); + len = sprintf(out, "%i\n", drive->id->buf_size / 2); else - len = sprintf(out,"(none)\n"); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); + len = sprintf(out, "(none)\n"); + + PROC_IDE_READ_RETURN(page, start, off, count, eof, len); } static int proc_idedisk_read_capacity @@ -536,54 +538,52 @@ static int proc_idedisk_read_capacity ide_drive_t*drive = (ide_drive_t *)data; int len; - len = sprintf(page,"%llu\n", (long long)idedisk_capacity(drive)); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); + len = sprintf(page, "%llu\n", (long long)idedisk_capacity(drive)); + + PROC_IDE_READ_RETURN(page, start, off, count, eof, len); } -static int proc_idedisk_read_smart_thresholds - (char *page, char **start, off_t off, int count, int *eof, void *data) +static int proc_idedisk_read_smart(char *page, char **start, off_t off, + int count, int *eof, void *data, u8 sub_cmd) { ide_drive_t *drive = (ide_drive_t *)data; int len = 0, i = 0; - if (get_smart_data(drive, page, SMART_READ_THRESHOLDS) == 0) { + if (get_smart_data(drive, page, sub_cmd) == 0) { unsigned short *val = (unsigned short *) page; char *out = ((char *)val) + (SECTOR_WORDS * 4); page = out; do { - out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n'); + out += sprintf(out, "%04x%c", le16_to_cpu(*val), + (++i & 7) ? ' ' : '\n'); val += 1; } while (i < (SECTOR_WORDS * 2)); len = out - page; } - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); + + PROC_IDE_READ_RETURN(page, start, off, count, eof, len); } -static int proc_idedisk_read_smart_values +static int proc_idedisk_read_sv (char *page, char **start, off_t off, int count, int *eof, void *data) { - ide_drive_t *drive = (ide_drive_t *)data; - int len = 0, i = 0; + return proc_idedisk_read_smart(page, start, off, count, eof, data, + SMART_READ_VALUES); +} - if (get_smart_data(drive, page, SMART_READ_VALUES) == 0) { - unsigned short *val = (unsigned short *) page; - char *out = ((char *)val) + (SECTOR_WORDS * 4); - page = out; - do { - out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n'); - val += 1; - } while (i < (SECTOR_WORDS * 2)); - len = out - page; - } - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); +static int proc_idedisk_read_st + (char *page, char **start, off_t off, int count, int *eof, void *data) +{ + return proc_idedisk_read_smart(page, start, off, count, eof, data, + SMART_READ_THRESHOLDS); } static ide_proc_entry_t idedisk_proc[] = { - { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL }, - { "capacity", S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL }, - { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL }, - { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_smart_values, NULL }, - { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_smart_thresholds, NULL }, + { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL }, + { "capacity", S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL }, + { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL }, + { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_sv, NULL }, + { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st, NULL }, { NULL, 0, NULL, NULL } }; #endif /* CONFIG_IDE_PROC_FS */ @@ -625,12 +625,13 @@ static int set_multcount(ide_drive_t *drive, int arg) if (drive->special.b.set_multmode) return -EBUSY; - ide_init_drive_cmd (&rq); + ide_init_drive_cmd(&rq); rq.cmd_type = REQ_TYPE_ATA_TASKFILE; drive->mult_req = arg; drive->special.b.set_multmode = 1; - (void) ide_do_drive_cmd (drive, &rq, ide_wait); + (void)ide_do_drive_cmd(drive, &rq, ide_wait); + return (drive->mult_count == arg) ? 0 : -EIO; } @@ -706,7 +707,7 @@ static int write_cache(ide_drive_t *drive, int arg) return err; } -static int do_idedisk_flushcache (ide_drive_t *drive) +static int do_idedisk_flushcache(ide_drive_t *drive) { ide_task_t args; @@ -719,7 +720,7 @@ static int do_idedisk_flushcache (ide_drive_t *drive) return ide_no_data_taskfile(drive, &args); } -static int set_acoustic (ide_drive_t *drive, int arg) +static int set_acoustic(ide_drive_t *drive, int arg) { ide_task_t args; @@ -753,7 +754,7 @@ static int set_lba_addressing(ide_drive_t *drive, int arg) return 0; if (!idedisk_supports_lba48(drive->id)) - return -EIO; + return -EIO; drive->addressing = arg; return 0; } @@ -763,23 +764,35 @@ static void idedisk_add_settings(ide_drive_t *drive) { struct hd_driveid *id = drive->id; - ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->bios_cyl, NULL); - ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); - ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); - ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1, &drive->addressing, set_lba_addressing); - ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0, id->max_multsect, 1, 1, &drive->mult_count, set_multcount); - ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr); - ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL); - ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->wcache, write_cache); - ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1, &drive->acoustic, set_acoustic); - ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->failures, NULL); - ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL); + ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, + &drive->bios_cyl, NULL); + ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, + &drive->bios_head, NULL); + ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, + &drive->bios_sect, NULL); + ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1, + &drive->addressing, set_lba_addressing); + ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0, + id->max_multsect, 1, 1, &drive->mult_count, + set_multcount); + ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, + &drive->nowerr, set_nowerr); + ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1, + &drive->lun, NULL); + ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, + &drive->wcache, write_cache); + ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1, + &drive->acoustic, set_acoustic); + ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, + &drive->failures, NULL); + ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535, + 1, 1, &drive->max_failures, NULL); } #else static inline void idedisk_add_settings(ide_drive_t *drive) { ; } #endif -static void idedisk_setup (ide_drive_t *drive) +static void idedisk_setup(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; struct hd_driveid *id = drive->id; @@ -792,11 +805,10 @@ static void idedisk_setup (ide_drive_t *drive) if (drive->removable) { /* - * Removable disks (eg. SYQUEST); ignore 'WD' drives + * Removable disks (eg. SYQUEST); ignore 'WD' drives */ - if (id->model[0] != 'W' || id->model[1] != 'D') { + if (id->model[0] != 'W' || id->model[1] != 'D') drive->doorlocking = 1; - } } (void)set_lba_addressing(drive, 1); @@ -810,10 +822,11 @@ static void idedisk_setup (ide_drive_t *drive) blk_queue_max_sectors(drive->queue, max_s); } - printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name, drive->queue->max_sectors / 2); + printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name, + drive->queue->max_sectors / 2); /* calculate drive capacity, and select LBA if possible */ - init_idedisk_capacity (drive); + init_idedisk_capacity(drive); /* limit drive capacity to 137GB if LBA48 cannot be used */ if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) { @@ -826,9 +839,9 @@ static void idedisk_setup (ide_drive_t *drive) if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) { if (drive->capacity64 > 1ULL << 28) { - printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode will" - " be used for accessing sectors > %u\n", - drive->name, 1 << 28); + printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode" + " will be used for accessing sectors " + "> %u\n", drive->name, 1 << 28); } else drive->addressing = 0; } @@ -837,7 +850,8 @@ static void idedisk_setup (ide_drive_t *drive) * if possible, give fdisk access to more of the drive, * by correcting bios_cyls: */ - capacity = idedisk_capacity (drive); + capacity = idedisk_capacity(drive); + if (!drive->forced_geom) { if (idedisk_supports_lba48(drive->id)) { @@ -993,7 +1007,8 @@ static int idedisk_open(struct inode *inode, struct file *filp) struct ide_disk_obj *idkp; ide_drive_t *drive; - if (!(idkp = ide_disk_get(disk))) + idkp = ide_disk_get(disk); + if (idkp == NULL) return -ENXIO; drive = idkp->drive; @@ -1115,13 +1130,13 @@ static int idedisk_revalidate_disk(struct gendisk *disk) } static struct block_device_operations idedisk_ops = { - .owner = THIS_MODULE, - .open = idedisk_open, - .release = idedisk_release, - .ioctl = idedisk_ioctl, - .getgeo = idedisk_getgeo, - .media_changed = idedisk_media_changed, - .revalidate_disk= idedisk_revalidate_disk + .owner = THIS_MODULE, + .open = idedisk_open, + .release = idedisk_release, + .ioctl = idedisk_ioctl, + .getgeo = idedisk_getgeo, + .media_changed = idedisk_media_changed, + .revalidate_disk = idedisk_revalidate_disk }; MODULE_DESCRIPTION("ATA DISK Driver"); @@ -1184,7 +1199,7 @@ failed: return -ENODEV; } -static void __exit idedisk_exit (void) +static void __exit idedisk_exit(void) { driver_unregister(&idedisk_driver.gen_driver); } diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index d61e5788d310..653b1ade13d3 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -102,7 +102,7 @@ ide_startstop_t ide_dma_intr (ide_drive_t *drive) { u8 stat = 0, dma_stat = 0; - dma_stat = HWIF(drive)->ide_dma_end(drive); + dma_stat = drive->hwif->dma_ops->dma_end(drive); stat = ide_read_status(drive); if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) { @@ -394,7 +394,7 @@ void ide_dma_off_quietly(ide_drive_t *drive) drive->using_dma = 0; ide_toggle_bounce(drive, 0); - drive->hwif->dma_host_set(drive, 0); + drive->hwif->dma_ops->dma_host_set(drive, 0); } EXPORT_SYMBOL(ide_dma_off_quietly); @@ -427,7 +427,7 @@ void ide_dma_on(ide_drive_t *drive) drive->using_dma = 1; ide_toggle_bounce(drive, 1); - drive->hwif->dma_host_set(drive, 1); + drive->hwif->dma_ops->dma_host_set(drive, 1); } #ifdef CONFIG_BLK_DEV_IDEDMA_SFF @@ -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); @@ -482,11 +483,12 @@ int ide_dma_setup(ide_drive_t *drive) EXPORT_SYMBOL_GPL(ide_dma_setup); -static void ide_dma_exec_cmd(ide_drive_t *drive, u8 command) +void ide_dma_exec_cmd(ide_drive_t *drive, u8 command) { /* issue cmd to drive */ ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry); } +EXPORT_SYMBOL_GPL(ide_dma_exec_cmd); void ide_dma_start(ide_drive_t *drive) { @@ -532,7 +534,7 @@ int __ide_dma_end (ide_drive_t *drive) EXPORT_SYMBOL(__ide_dma_end); /* returns 1 if dma irq issued, 0 otherwise */ -static int __ide_dma_test_irq(ide_drive_t *drive) +int ide_dma_test_irq(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); u8 dma_stat = hwif->INB(hwif->dma_status); @@ -542,9 +544,10 @@ static int __ide_dma_test_irq(ide_drive_t *drive) return 1; if (!drive->waiting_for_dma) printk(KERN_WARNING "%s: (%s) called while not waiting\n", - drive->name, __FUNCTION__); + drive->name, __func__); return 0; } +EXPORT_SYMBOL_GPL(ide_dma_test_irq); #else static inline int config_drive_for_dma(ide_drive_t *drive) { return 0; } #endif /* CONFIG_BLK_DEV_IDEDMA_SFF */ @@ -574,6 +577,7 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode) { struct hd_driveid *id = drive->id; ide_hwif_t *hwif = drive->hwif; + const struct ide_port_ops *port_ops = hwif->port_ops; unsigned int mask = 0; switch(base) { @@ -581,8 +585,8 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode) if ((id->field_valid & 4) == 0) break; - if (hwif->udma_filter) - mask = hwif->udma_filter(drive); + if (port_ops && port_ops->udma_filter) + mask = port_ops->udma_filter(drive); else mask = hwif->ultra_mask; mask &= id->dma_ultra; @@ -598,8 +602,8 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode) case XFER_MW_DMA_0: if ((id->field_valid & 2) == 0) break; - if (hwif->mdma_filter) - mask = hwif->mdma_filter(drive); + if (port_ops && port_ops->mdma_filter) + mask = port_ops->mdma_filter(drive); else mask = hwif->mwdma_mask; mask &= id->dma_mword; @@ -703,17 +707,8 @@ static int ide_tune_dma(ide_drive_t *drive) speed = ide_max_dma_mode(drive); - if (!speed) { - /* is this really correct/needed? */ - if ((hwif->host_flags & IDE_HFLAG_CY82C693) && - ide_dma_good_drive(drive)) - return 1; - else - return 0; - } - - if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE) - return 1; + if (!speed) + return 0; if (ide_set_dma_mode(drive, speed)) return 0; @@ -810,15 +805,15 @@ void ide_dma_timeout (ide_drive_t *drive) printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name); - if (hwif->ide_dma_test_irq(drive)) + if (hwif->dma_ops->dma_test_irq(drive)) return; - hwif->ide_dma_end(drive); + hwif->dma_ops->dma_end(drive); } EXPORT_SYMBOL(ide_dma_timeout); -static void ide_release_dma_engine(ide_hwif_t *hwif) +void ide_release_dma_engine(ide_hwif_t *hwif) { if (hwif->dmatable_cpu) { struct pci_dev *pdev = to_pci_dev(hwif->dev); @@ -829,28 +824,7 @@ static void ide_release_dma_engine(ide_hwif_t *hwif) } } -static int ide_release_iomio_dma(ide_hwif_t *hwif) -{ - release_region(hwif->dma_base, 8); - if (hwif->extra_ports) - release_region(hwif->extra_base, hwif->extra_ports); - return 1; -} - -/* - * Needed for allowing full modular support of ide-driver - */ -int ide_release_dma(ide_hwif_t *hwif) -{ - ide_release_dma_engine(hwif); - - if (hwif->mmio) - return 1; - else - return ide_release_iomio_dma(hwif); -} - -static int ide_allocate_dma_engine(ide_hwif_t *hwif) +int ide_allocate_dma_engine(ide_hwif_t *hwif) { struct pci_dev *pdev = to_pci_dev(hwif->dev); @@ -862,99 +836,33 @@ static int ide_allocate_dma_engine(ide_hwif_t *hwif) return 0; printk(KERN_ERR "%s: -- Error, unable to allocate DMA table.\n", - hwif->cds->name); + hwif->name); return 1; } - -static int ide_mapped_mmio_dma(ide_hwif_t *hwif, unsigned long base) -{ - printk(KERN_INFO " %s: MMIO-DMA ", hwif->name); - - return 0; -} - -static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base) -{ - printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx", - hwif->name, base, base + 7); - - if (!request_region(base, 8, hwif->name)) { - printk(" -- Error, ports in use.\n"); - return 1; - } - - if (hwif->cds->extra) { - hwif->extra_base = base + (hwif->channel ? 8 : 16); - - if (!hwif->mate || !hwif->mate->extra_ports) { - if (!request_region(hwif->extra_base, - hwif->cds->extra, hwif->cds->name)) { - printk(" -- Error, extra ports in use.\n"); - release_region(base, 8); - return 1; - } - hwif->extra_ports = hwif->cds->extra; - } - } - - return 0; -} - -static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base) -{ - if (hwif->mmio) - return ide_mapped_mmio_dma(hwif, base); - - return ide_iomio_dma(hwif, base); -} +EXPORT_SYMBOL_GPL(ide_allocate_dma_engine); + +static const struct ide_dma_ops sff_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 = ide_dma_test_irq, + .dma_timeout = ide_dma_timeout, + .dma_lost_irq = ide_dma_lost_irq, +}; void ide_setup_dma(ide_hwif_t *hwif, unsigned long base) { - u8 dma_stat; - - if (ide_dma_iobase(hwif, base)) - return; - - if (ide_allocate_dma_engine(hwif)) { - ide_release_dma(hwif); - return; - } - hwif->dma_base = 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; - - if (!hwif->dma_host_set) - hwif->dma_host_set = &ide_dma_host_set; - if (!hwif->dma_setup) - hwif->dma_setup = &ide_dma_setup; - if (!hwif->dma_exec_cmd) - hwif->dma_exec_cmd = &ide_dma_exec_cmd; - if (!hwif->dma_start) - hwif->dma_start = &ide_dma_start; - if (!hwif->ide_dma_end) - hwif->ide_dma_end = &__ide_dma_end; - if (!hwif->ide_dma_test_irq) - hwif->ide_dma_test_irq = &__ide_dma_test_irq; - if (!hwif->dma_timeout) - hwif->dma_timeout = &ide_dma_timeout; - if (!hwif->dma_lost_irq) - hwif->dma_lost_irq = &ide_dma_lost_irq; - dma_stat = hwif->INB(hwif->dma_status); - printk(KERN_CONT ", BIOS settings: %s:%s, %s:%s\n", - hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "PIO", - hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "PIO"); + hwif->dma_ops = &sff_dma_ops; } EXPORT_SYMBOL_GPL(ide_setup_dma); diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index faf22d716f80..f05fbc2bd7a8 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -78,40 +78,6 @@ */ #define IDEFLOPPY_PC_STACK (10 + IDEFLOPPY_MAX_PC_RETRIES) -typedef struct idefloppy_packet_command_s { - u8 c[12]; /* Actual packet bytes */ - int retries; /* On each retry, we increment - retries */ - int error; /* Error code */ - int request_transfer; /* Bytes to transfer */ - int actually_transferred; /* Bytes actually transferred */ - int buffer_size; /* Size of our data buffer */ - int b_count; /* Missing/Available data on - the current buffer */ - struct request *rq; /* The corresponding request */ - u8 *buffer; /* Data buffer */ - u8 *current_position; /* Pointer into above buffer */ - void (*callback) (ide_drive_t *); /* Called when this packet - command is completed */ - u8 pc_buffer[IDEFLOPPY_PC_BUFFER_SIZE]; /* Temporary buffer */ - unsigned long flags; /* Status/Action bit flags: long - for set_bit */ -} idefloppy_pc_t; - -/* Packet command flag bits. */ -enum { - /* 1 when we prefer to use DMA if possible */ - PC_FLAG_DMA_RECOMMENDED = (1 << 0), - /* 1 while DMA in progress */ - PC_FLAG_DMA_IN_PROGRESS = (1 << 1), - /* 1 when encountered problem during DMA */ - PC_FLAG_DMA_ERROR = (1 << 2), - /* Data direction */ - PC_FLAG_WRITING = (1 << 3), - /* Suppress error reporting */ - PC_FLAG_SUPPRESS_ERROR = (1 << 4), -}; - /* format capacities descriptor codes */ #define CAPACITY_INVALID 0x00 #define CAPACITY_UNFORMATTED 0x01 @@ -131,11 +97,11 @@ typedef struct ide_floppy_obj { unsigned int openers; /* protected by BKL for now */ /* Current packet command */ - idefloppy_pc_t *pc; + struct ide_atapi_pc *pc; /* Last failed packet command */ - idefloppy_pc_t *failed_pc; + struct ide_atapi_pc *failed_pc; /* Packet command stack */ - idefloppy_pc_t pc_stack[IDEFLOPPY_PC_STACK]; + struct ide_atapi_pc pc_stack[IDEFLOPPY_PC_STACK]; /* Next free packet command storage space */ int pc_stack_index; struct request rq_stack[IDEFLOPPY_PC_STACK]; @@ -195,32 +161,6 @@ enum { #define IDEFLOPPY_ERROR_GENERAL 101 /* - * The following is used to format the general configuration word of the - * ATAPI IDENTIFY DEVICE command. - */ -struct idefloppy_id_gcw { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned packet_size :2; /* Packet Size */ - unsigned reserved234 :3; /* Reserved */ - unsigned drq_type :2; /* Command packet DRQ type */ - unsigned removable :1; /* Removable media */ - unsigned device_type :5; /* Device type */ - unsigned reserved13 :1; /* Reserved */ - unsigned protocol :2; /* Protocol type */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned protocol :2; /* Protocol type */ - unsigned reserved13 :1; /* Reserved */ - unsigned device_type :5; /* Device type */ - unsigned removable :1; /* Removable media */ - unsigned drq_type :2; /* Command packet DRQ type */ - unsigned reserved234 :3; /* Reserved */ - unsigned packet_size :2; /* Packet Size */ -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif -}; - -/* * Pages of the SELECT SENSE / MODE SENSE packet commands. * See SFF-8070i spec. */ @@ -256,27 +196,10 @@ static void ide_floppy_put(struct ide_floppy_obj *floppy) } /* - * Too bad. The drive wants to send us data which we are not ready to accept. - * Just throw it away. - */ -static void idefloppy_discard_data(ide_drive_t *drive, unsigned int bcount) -{ - while (bcount--) - (void) HWIF(drive)->INB(IDE_DATA_REG); -} - -static void idefloppy_write_zeros(ide_drive_t *drive, unsigned int bcount) -{ - while (bcount--) - HWIF(drive)->OUTB(0, IDE_DATA_REG); -} - - -/* * Used to finish servicing a request. For read/write requests, we will call * ide_end_request to pass to the next buffer. */ -static int idefloppy_do_end_request(ide_drive_t *drive, int uptodate, int nsecs) +static int idefloppy_end_request(ide_drive_t *drive, int uptodate, int nsecs) { idefloppy_floppy_t *floppy = drive->driver_data; struct request *rq = HWGROUP(drive)->rq; @@ -305,9 +228,10 @@ static int idefloppy_do_end_request(ide_drive_t *drive, int uptodate, int nsecs) return 0; } -static void ide_floppy_io_buffers(ide_drive_t *drive, idefloppy_pc_t *pc, +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; @@ -323,9 +247,9 @@ static void ide_floppy_io_buffers(ide_drive_t *drive, idefloppy_pc_t *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; @@ -333,26 +257,23 @@ static void ide_floppy_io_buffers(ide_drive_t *drive, idefloppy_pc_t *pc, done += count; } - idefloppy_do_end_request(drive, 1, done >> 9); + idefloppy_end_request(drive, 1, done >> 9); if (bcount) { printk(KERN_ERR "%s: leftover data in %s, bcount == %d\n", drive->name, __func__, bcount); - if (direction) - idefloppy_write_zeros(drive, bcount); - else - idefloppy_discard_data(drive, bcount); - + ide_pad_transfer(drive, direction, bcount); } } -static void idefloppy_update_buffers(ide_drive_t *drive, idefloppy_pc_t *pc) +static void idefloppy_update_buffers(ide_drive_t *drive, + struct ide_atapi_pc *pc) { struct request *rq = pc->rq; struct bio *bio = rq->bio; while ((bio = rq->bio) != NULL) - idefloppy_do_end_request(drive, 1, 0); + idefloppy_end_request(drive, 1, 0); } /* @@ -360,7 +281,7 @@ static void idefloppy_update_buffers(ide_drive_t *drive, idefloppy_pc_t *pc) * the current request so that it will be processed immediately, on the next * pass through the driver. */ -static void idefloppy_queue_pc_head(ide_drive_t *drive, idefloppy_pc_t *pc, +static void idefloppy_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc, struct request *rq) { struct ide_floppy_obj *floppy = drive->driver_data; @@ -372,7 +293,7 @@ static void idefloppy_queue_pc_head(ide_drive_t *drive, idefloppy_pc_t *pc, (void) ide_do_drive_cmd(drive, rq, ide_preempt); } -static idefloppy_pc_t *idefloppy_next_pc_storage(ide_drive_t *drive) +static struct ide_atapi_pc *idefloppy_next_pc_storage(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; @@ -393,7 +314,7 @@ static struct request *idefloppy_next_rq_storage(ide_drive_t *drive) static void idefloppy_request_sense_callback(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; - u8 *buf = floppy->pc->buffer; + u8 *buf = floppy->pc->buf; debug_log("Reached %s\n", __func__); @@ -418,11 +339,11 @@ static void idefloppy_request_sense_callback(ide_drive_t *drive) floppy->ascq); - idefloppy_do_end_request(drive, 1, 0); + idefloppy_end_request(drive, 1, 0); } else { printk(KERN_ERR "Error in REQUEST SENSE itself - Aborting" " request!\n"); - idefloppy_do_end_request(drive, 0, 0); + idefloppy_end_request(drive, 0, 0); } } @@ -433,27 +354,27 @@ static void idefloppy_pc_callback(ide_drive_t *drive) debug_log("Reached %s\n", __func__); - idefloppy_do_end_request(drive, floppy->pc->error ? 0 : 1, 0); + idefloppy_end_request(drive, floppy->pc->error ? 0 : 1, 0); } -static void idefloppy_init_pc(idefloppy_pc_t *pc) +static void idefloppy_init_pc(struct ide_atapi_pc *pc) { memset(pc->c, 0, 12); pc->retries = 0; pc->flags = 0; - pc->request_transfer = 0; - pc->buffer = pc->pc_buffer; - pc->buffer_size = IDEFLOPPY_PC_BUFFER_SIZE; - pc->callback = &idefloppy_pc_callback; + pc->req_xfer = 0; + pc->buf = pc->pc_buf; + pc->buf_size = IDEFLOPPY_PC_BUFFER_SIZE; + pc->idefloppy_callback = &idefloppy_pc_callback; } -static void idefloppy_create_request_sense_cmd(idefloppy_pc_t *pc) +static void idefloppy_create_request_sense_cmd(struct ide_atapi_pc *pc) { idefloppy_init_pc(pc); pc->c[0] = GPCMD_REQUEST_SENSE; pc->c[4] = 255; - pc->request_transfer = 18; - pc->callback = &idefloppy_request_sense_callback; + pc->req_xfer = 18; + pc->idefloppy_callback = &idefloppy_request_sense_callback; } /* @@ -462,7 +383,7 @@ static void idefloppy_create_request_sense_cmd(idefloppy_pc_t *pc) */ static void idefloppy_retry_pc(ide_drive_t *drive) { - idefloppy_pc_t *pc; + struct ide_atapi_pc *pc; struct request *rq; (void)ide_read_error(drive); @@ -473,11 +394,11 @@ static void idefloppy_retry_pc(ide_drive_t *drive) } /* The usual interrupt handler called during a packet command. */ -static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive) +static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; ide_hwif_t *hwif = drive->hwif; - idefloppy_pc_t *pc = floppy->pc; + struct ide_atapi_pc *pc = floppy->pc; struct request *rq = pc->rq; xfer_func_t *xferfunc; unsigned int temp; @@ -488,13 +409,13 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive) debug_log("Reached %s interrupt handler\n", __func__); if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { - dma_error = hwif->ide_dma_end(drive); + dma_error = hwif->dma_ops->dma_end(drive); if (dma_error) { printk(KERN_ERR "%s: DMA %s error\n", drive->name, rq_data_dir(rq) ? "write" : "read"); pc->flags |= PC_FLAG_DMA_ERROR; } else { - pc->actually_transferred = pc->request_transfer; + pc->xferred = pc->req_xfer; idefloppy_update_buffers(drive, pc); } debug_log("DMA finished\n"); @@ -506,7 +427,7 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive) /* No more interrupts */ if ((stat & DRQ_STAT) == 0) { debug_log("Packet command completed, %d bytes transferred\n", - pc->actually_transferred); + pc->xferred); pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; local_irq_enable_in_hardirq(); @@ -529,7 +450,7 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive) if (floppy->failed_pc == pc) floppy->failed_pc = NULL; /* Command finished - Call the callback function */ - pc->callback(drive); + pc->idefloppy_callback(drive); return ide_stopped; } @@ -542,10 +463,10 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive) } /* Get the number of bytes to transfer */ - bcount = (hwif->INB(IDE_BCOUNTH_REG) << 8) | - hwif->INB(IDE_BCOUNTL_REG); + bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) | + hwif->INB(hwif->io_ports.lbam_addr); /* on this interrupt */ - ireason = hwif->INB(IDE_IREASON_REG); + ireason = hwif->INB(hwif->io_ports.nsect_addr); if (ireason & CD) { printk(KERN_ERR "ide-floppy: CoD != 0 in %s\n", __func__); @@ -561,13 +482,13 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive) } if (!(pc->flags & PC_FLAG_WRITING)) { /* Reading - Check that we have enough space */ - temp = pc->actually_transferred + bcount; - if (temp > pc->request_transfer) { - if (temp > pc->buffer_size) { + temp = pc->xferred + bcount; + if (temp > pc->req_xfer) { + if (temp > pc->buf_size) { printk(KERN_ERR "ide-floppy: The floppy wants " "to send us more data than expected " "- discarding data\n"); - idefloppy_discard_data(drive, bcount); + ide_pad_transfer(drive, 0, bcount); ide_set_handler(drive, &idefloppy_pc_intr, @@ -580,19 +501,19 @@ 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->buffer) - xferfunc(drive, pc->current_position, bcount); + if (pc->buf) + xferfunc(drive, NULL, pc->cur_pos, bcount); else ide_floppy_io_buffers(drive, pc, bcount, !!(pc->flags & PC_FLAG_WRITING)); /* Update the current position */ - pc->actually_transferred += bcount; - pc->current_position += bcount; + pc->xferred += bcount; + pc->cur_pos += bcount; /* And set the interrupt handler again */ ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); @@ -606,6 +527,7 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive) */ static ide_startstop_t idefloppy_transfer_pc(ide_drive_t *drive) { + ide_hwif_t *hwif = drive->hwif; ide_startstop_t startstop; idefloppy_floppy_t *floppy = drive->driver_data; u8 ireason; @@ -615,7 +537,7 @@ static ide_startstop_t idefloppy_transfer_pc(ide_drive_t *drive) "initiated yet DRQ isn't asserted\n"); return startstop; } - ireason = drive->hwif->INB(IDE_IREASON_REG); + 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"); @@ -624,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; } @@ -645,13 +569,15 @@ 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; } static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive) { + ide_hwif_t *hwif = drive->hwif; idefloppy_floppy_t *floppy = drive->driver_data; ide_startstop_t startstop; u8 ireason; @@ -661,7 +587,7 @@ static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive) "initiated yet DRQ isn't asserted\n"); return startstop; } - ireason = drive->hwif->INB(IDE_IREASON_REG); + 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"); @@ -682,7 +608,7 @@ static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive) } static void ide_floppy_report_error(idefloppy_floppy_t *floppy, - idefloppy_pc_t *pc) + struct ide_atapi_pc *pc) { /* supress error messages resulting from Medium not present */ if (floppy->sense_key == 0x02 && @@ -698,7 +624,7 @@ static void ide_floppy_report_error(idefloppy_floppy_t *floppy, } static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive, - idefloppy_pc_t *pc) + struct ide_atapi_pc *pc) { idefloppy_floppy_t *floppy = drive->driver_data; ide_hwif_t *hwif = drive->hwif; @@ -719,7 +645,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive, pc->error = IDEFLOPPY_ERROR_GENERAL; floppy->failed_pc = NULL; - pc->callback(drive); + pc->idefloppy_callback(drive); return ide_stopped; } @@ -727,9 +653,9 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive, pc->retries++; /* We haven't transferred any data yet */ - pc->actually_transferred = 0; - pc->current_position = pc->buffer; - bcount = min(pc->request_transfer, 63 * 1024); + pc->xferred = 0; + pc->cur_pos = pc->buf; + bcount = min(pc->req_xfer, 63 * 1024); if (pc->flags & PC_FLAG_DMA_ERROR) { pc->flags &= ~PC_FLAG_DMA_ERROR; @@ -738,7 +664,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive, dma = 0; if ((pc->flags & PC_FLAG_DMA_RECOMMENDED) && drive->using_dma) - dma = !hwif->dma_setup(drive); + dma = !hwif->dma_ops->dma_setup(drive); ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK | IDE_TFLAG_OUT_DEVICE, bcount, dma); @@ -746,7 +672,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive, if (dma) { /* Begin DMA, if necessary */ pc->flags |= PC_FLAG_DMA_IN_PROGRESS; - hwif->dma_start(drive); + hwif->dma_ops->dma_start(drive); } /* Can we transfer the packet when we get the interrupt or wait? */ @@ -757,7 +683,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive, /* immediate */ pkt_xfer_routine = &idefloppy_transfer_pc; } - + if (floppy->flags & IDEFLOPPY_FLAG_DRQ_INTERRUPT) { /* Issue the packet command */ ide_execute_command(drive, WIN_PACKETCMD, @@ -767,7 +693,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive, return ide_started; } else { /* Issue the packet command */ - HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG); + ide_execute_pkt_cmd(drive); return (*pkt_xfer_routine) (drive); } } @@ -776,11 +702,11 @@ static void idefloppy_rw_callback(ide_drive_t *drive) { debug_log("Reached %s\n", __func__); - idefloppy_do_end_request(drive, 1, 0); + idefloppy_end_request(drive, 1, 0); return; } -static void idefloppy_create_prevent_cmd(idefloppy_pc_t *pc, int prevent) +static void idefloppy_create_prevent_cmd(struct ide_atapi_pc *pc, int prevent) { debug_log("creating prevent removal command, prevent = %d\n", prevent); @@ -789,39 +715,39 @@ static void idefloppy_create_prevent_cmd(idefloppy_pc_t *pc, int prevent) pc->c[4] = prevent; } -static void idefloppy_create_read_capacity_cmd(idefloppy_pc_t *pc) +static void idefloppy_create_read_capacity_cmd(struct ide_atapi_pc *pc) { idefloppy_init_pc(pc); pc->c[0] = GPCMD_READ_FORMAT_CAPACITIES; pc->c[7] = 255; pc->c[8] = 255; - pc->request_transfer = 255; + pc->req_xfer = 255; } -static void idefloppy_create_format_unit_cmd(idefloppy_pc_t *pc, int b, int l, - int flags) +static void idefloppy_create_format_unit_cmd(struct ide_atapi_pc *pc, int b, + int l, int flags) { idefloppy_init_pc(pc); pc->c[0] = GPCMD_FORMAT_UNIT; pc->c[1] = 0x17; - memset(pc->buffer, 0, 12); - pc->buffer[1] = 0xA2; + memset(pc->buf, 0, 12); + pc->buf[1] = 0xA2; /* Default format list header, u8 1: FOV/DCRT/IMM bits set */ if (flags & 1) /* Verify bit on... */ - pc->buffer[1] ^= 0x20; /* ... turn off DCRT bit */ - pc->buffer[3] = 8; + pc->buf[1] ^= 0x20; /* ... turn off DCRT bit */ + pc->buf[3] = 8; - put_unaligned(cpu_to_be32(b), (unsigned int *)(&pc->buffer[4])); - put_unaligned(cpu_to_be32(l), (unsigned int *)(&pc->buffer[8])); - pc->buffer_size = 12; + put_unaligned(cpu_to_be32(b), (unsigned int *)(&pc->buf[4])); + put_unaligned(cpu_to_be32(l), (unsigned int *)(&pc->buf[8])); + pc->buf_size = 12; pc->flags |= PC_FLAG_WRITING; } /* A mode sense command is used to "sense" floppy parameters. */ -static void idefloppy_create_mode_sense_cmd(idefloppy_pc_t *pc, u8 page_code, - u8 type) +static void idefloppy_create_mode_sense_cmd(struct ide_atapi_pc *pc, + u8 page_code, u8 type) { u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */ @@ -842,24 +768,24 @@ static void idefloppy_create_mode_sense_cmd(idefloppy_pc_t *pc, u8 page_code, "in create_mode_sense_cmd\n"); } put_unaligned(cpu_to_be16(length), (u16 *) &pc->c[7]); - pc->request_transfer = length; + pc->req_xfer = length; } -static void idefloppy_create_start_stop_cmd(idefloppy_pc_t *pc, int start) +static void idefloppy_create_start_stop_cmd(struct ide_atapi_pc *pc, int start) { idefloppy_init_pc(pc); pc->c[0] = GPCMD_START_STOP_UNIT; pc->c[4] = start; } -static void idefloppy_create_test_unit_ready_cmd(idefloppy_pc_t *pc) +static void idefloppy_create_test_unit_ready_cmd(struct ide_atapi_pc *pc) { idefloppy_init_pc(pc); pc->c[0] = GPCMD_TEST_UNIT_READY; } static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy, - idefloppy_pc_t *pc, struct request *rq, + struct ide_atapi_pc *pc, struct request *rq, unsigned long sector) { int block = sector / floppy->bs_factor; @@ -874,41 +800,41 @@ static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy, put_unaligned(cpu_to_be16(blocks), (unsigned short *)&pc->c[7]); put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[2]); - pc->callback = &idefloppy_rw_callback; + pc->idefloppy_callback = &idefloppy_rw_callback; pc->rq = rq; pc->b_count = cmd == READ ? 0 : rq->bio->bi_size; if (rq->cmd_flags & REQ_RW) pc->flags |= PC_FLAG_WRITING; - pc->buffer = NULL; - pc->request_transfer = pc->buffer_size = blocks * floppy->block_size; + pc->buf = NULL; + pc->req_xfer = pc->buf_size = blocks * floppy->block_size; pc->flags |= PC_FLAG_DMA_RECOMMENDED; } static void idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, - idefloppy_pc_t *pc, struct request *rq) + struct ide_atapi_pc *pc, struct request *rq) { idefloppy_init_pc(pc); - pc->callback = &idefloppy_rw_callback; + pc->idefloppy_callback = &idefloppy_rw_callback; memcpy(pc->c, rq->cmd, sizeof(pc->c)); pc->rq = rq; pc->b_count = rq->data_len; if (rq->data_len && rq_data_dir(rq) == WRITE) pc->flags |= PC_FLAG_WRITING; - pc->buffer = rq->data; + pc->buf = rq->data; if (rq->bio) pc->flags |= PC_FLAG_DMA_RECOMMENDED; /* * possibly problematic, doesn't look like ide-floppy correctly * handled scattered requests if dma fails... */ - pc->request_transfer = pc->buffer_size = rq->data_len; + pc->req_xfer = pc->buf_size = rq->data_len; } static ide_startstop_t idefloppy_do_request(ide_drive_t *drive, struct request *rq, sector_t block_s) { idefloppy_floppy_t *floppy = drive->driver_data; - idefloppy_pc_t *pc; + struct ide_atapi_pc *pc; unsigned long block = (unsigned long)block_s; debug_log("dev: %s, cmd_type: %x, errors: %d\n", @@ -924,7 +850,7 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive, else printk(KERN_ERR "ide-floppy: %s: I/O error\n", drive->name); - idefloppy_do_end_request(drive, 0, 0); + idefloppy_end_request(drive, 0, 0); return ide_stopped; } if (blk_fs_request(rq)) { @@ -932,20 +858,20 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive, (rq->nr_sectors % floppy->bs_factor)) { printk(KERN_ERR "%s: unsupported r/w request size\n", drive->name); - idefloppy_do_end_request(drive, 0, 0); + idefloppy_end_request(drive, 0, 0); return ide_stopped; } pc = idefloppy_next_pc_storage(drive); idefloppy_create_rw_cmd(floppy, pc, rq, block); } else if (blk_special_request(rq)) { - pc = (idefloppy_pc_t *) rq->buffer; + pc = (struct ide_atapi_pc *) rq->buffer; } else if (blk_pc_request(rq)) { pc = idefloppy_next_pc_storage(drive); idefloppy_blockpc_cmd(floppy, pc, rq); } else { blk_dump_rq_flags(rq, "ide-floppy: unsupported command in queue"); - idefloppy_do_end_request(drive, 0, 0); + idefloppy_end_request(drive, 0, 0); return ide_stopped; } @@ -957,7 +883,7 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive, * Add a special packet command request to the tail of the request queue, * and wait for it to be serviced. */ -static int idefloppy_queue_pc_tail(ide_drive_t *drive, idefloppy_pc_t *pc) +static int idefloppy_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc) { struct ide_floppy_obj *floppy = drive->driver_data; struct request rq; @@ -977,7 +903,7 @@ static int idefloppy_queue_pc_tail(ide_drive_t *drive, idefloppy_pc_t *pc) static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; - idefloppy_pc_t pc; + struct ide_atapi_pc pc; u8 *page; int capacity, lba_capacity; u16 transfer_rate, sector_size, cyls, rpm; @@ -991,16 +917,16 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive) " parameters\n"); return 1; } - floppy->wp = !!(pc.buffer[3] & 0x80); + floppy->wp = !!(pc.buf[3] & 0x80); set_disk_ro(floppy->disk, floppy->wp); - page = &pc.buffer[8]; + page = &pc.buf[8]; - transfer_rate = be16_to_cpu(*(u16 *)&pc.buffer[8 + 2]); - sector_size = be16_to_cpu(*(u16 *)&pc.buffer[8 + 6]); - cyls = be16_to_cpu(*(u16 *)&pc.buffer[8 + 8]); - rpm = be16_to_cpu(*(u16 *)&pc.buffer[8 + 28]); - heads = pc.buffer[8 + 4]; - sectors = pc.buffer[8 + 5]; + transfer_rate = be16_to_cpu(*(u16 *)&pc.buf[8 + 2]); + sector_size = be16_to_cpu(*(u16 *)&pc.buf[8 + 6]); + cyls = be16_to_cpu(*(u16 *)&pc.buf[8 + 8]); + rpm = be16_to_cpu(*(u16 *)&pc.buf[8 + 28]); + heads = pc.buf[8 + 4]; + sectors = pc.buf[8 + 5]; capacity = cyls * heads * sectors * sector_size; @@ -1029,7 +955,7 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive) static int idefloppy_get_sfrp_bit(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; - idefloppy_pc_t pc; + struct ide_atapi_pc pc; floppy->srfp = 0; idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE, @@ -1039,7 +965,7 @@ static int idefloppy_get_sfrp_bit(ide_drive_t *drive) if (idefloppy_queue_pc_tail(drive, &pc)) return 1; - floppy->srfp = pc.buffer[8 + 2] & 0x40; + floppy->srfp = pc.buf[8 + 2] & 0x40; return (0); } @@ -1050,7 +976,7 @@ static int idefloppy_get_sfrp_bit(ide_drive_t *drive) static int ide_floppy_get_capacity(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; - idefloppy_pc_t pc; + struct ide_atapi_pc pc; u8 *cap_desc; u8 header_len, desc_cnt; int i, rc = 1, blocks, length; @@ -1066,15 +992,15 @@ static int ide_floppy_get_capacity(ide_drive_t *drive) printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n"); return 1; } - header_len = pc.buffer[3]; - cap_desc = &pc.buffer[4]; + header_len = pc.buf[3]; + cap_desc = &pc.buf[4]; desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */ for (i = 0; i < desc_cnt; i++) { unsigned int desc_start = 4 + i*8; - blocks = be32_to_cpu(*(u32 *)&pc.buffer[desc_start]); - length = be16_to_cpu(*(u16 *)&pc.buffer[desc_start + 6]); + blocks = be32_to_cpu(*(u32 *)&pc.buf[desc_start]); + length = be16_to_cpu(*(u16 *)&pc.buf[desc_start + 6]); debug_log("Descriptor %d: %dkB, %d blocks, %d sector size\n", i, blocks * length / 1024, blocks, length); @@ -1085,7 +1011,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive) * the code below is valid only for the 1st descriptor, ie i=0 */ - switch (pc.buffer[desc_start + 4] & 0x03) { + switch (pc.buf[desc_start + 4] & 0x03) { /* Clik! drive returns this instead of CAPACITY_CURRENT */ case CAPACITY_UNFORMATTED: if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) @@ -1130,7 +1056,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive) break; } debug_log("Descriptor 0 Code: %d\n", - pc.buffer[desc_start + 4] & 0x03); + pc.buf[desc_start + 4] & 0x03); } /* Clik! disk does not support get_flexible_disk_page */ @@ -1162,7 +1088,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive) static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) { - idefloppy_pc_t pc; + struct ide_atapi_pc pc; u8 header_len, desc_cnt; int i, blocks, length, u_array_size, u_index; int __user *argp; @@ -1178,7 +1104,7 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n"); return (-EIO); } - header_len = pc.buffer[3]; + header_len = pc.buf[3]; desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */ u_index = 0; @@ -1195,8 +1121,8 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) if (u_index >= u_array_size) break; /* User-supplied buffer too small */ - blocks = be32_to_cpu(*(u32 *)&pc.buffer[desc_start]); - length = be16_to_cpu(*(u16 *)&pc.buffer[desc_start + 6]); + blocks = be32_to_cpu(*(u32 *)&pc.buf[desc_start]); + length = be16_to_cpu(*(u16 *)&pc.buf[desc_start + 6]); if (put_user(blocks, argp)) return(-EFAULT); @@ -1227,7 +1153,7 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg) { idefloppy_floppy_t *floppy = drive->driver_data; - idefloppy_pc_t pc; + struct ide_atapi_pc pc; int progress_indication = 0x10000; if (floppy->srfp) { @@ -1271,33 +1197,39 @@ static sector_t idefloppy_capacity(ide_drive_t *drive) */ static int idefloppy_identify_device(ide_drive_t *drive, struct hd_driveid *id) { - struct idefloppy_id_gcw gcw; + u8 gcw[2]; + u8 device_type, protocol, removable, drq_type, packet_size; *((u16 *) &gcw) = id->config; + device_type = gcw[1] & 0x1F; + removable = (gcw[0] & 0x80) >> 7; + protocol = (gcw[1] & 0xC0) >> 6; + drq_type = (gcw[0] & 0x60) >> 5; + packet_size = gcw[0] & 0x03; + #ifdef CONFIG_PPC /* kludge for Apple PowerBook internal zip */ - if ((gcw.device_type == 5) && - !strstr(id->model, "CD-ROM") && - strstr(id->model, "ZIP")) - gcw.device_type = 0; + if (device_type == 5 && + !strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP")) + device_type = 0; #endif - if (gcw.protocol != 2) + if (protocol != 2) printk(KERN_ERR "ide-floppy: Protocol (0x%02x) is not ATAPI\n", - gcw.protocol); - else if (gcw.device_type != 0) + protocol); + else if (device_type != 0) printk(KERN_ERR "ide-floppy: Device type (0x%02x) is not set " - "to floppy\n", gcw.device_type); - else if (!gcw.removable) + "to floppy\n", device_type); + else if (!removable) printk(KERN_ERR "ide-floppy: The removable flag is not set\n"); - else if (gcw.drq_type == 3) { + else if (drq_type == 3) printk(KERN_ERR "ide-floppy: Sorry, DRQ type (0x%02x) not " - "supported\n", gcw.drq_type); - } else if (gcw.packet_size != 0) { + "supported\n", drq_type); + else if (packet_size != 0) printk(KERN_ERR "ide-floppy: Packet size (0x%02x) is not 12 " - "bytes long\n", gcw.packet_size); - } else + "bytes\n", packet_size); + else return 1; return 0; } @@ -1322,11 +1254,12 @@ static inline void idefloppy_add_settings(ide_drive_t *drive) { ; } static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy) { - struct idefloppy_id_gcw gcw; + u8 gcw[2]; *((u16 *) &gcw) = drive->id->config; floppy->pc = floppy->pc_stack; - if (gcw.drq_type == 1) + + if (((gcw[0] & 0x60) >> 5) == 1) floppy->flags |= IDEFLOPPY_FLAG_DRQ_INTERRUPT; /* * We used to check revisions here. At this point however I'm giving up. @@ -1413,7 +1346,7 @@ static ide_driver_t idefloppy_driver = { .media = ide_floppy, .supports_dsc_overlap = 0, .do_request = idefloppy_do_request, - .end_request = idefloppy_do_end_request, + .end_request = idefloppy_end_request, .error = __ide_error, .abort = __ide_abort, #ifdef CONFIG_IDE_PROC_FS @@ -1426,7 +1359,7 @@ static int idefloppy_open(struct inode *inode, struct file *filp) struct gendisk *disk = inode->i_bdev->bd_disk; struct ide_floppy_obj *floppy; ide_drive_t *drive; - idefloppy_pc_t pc; + struct ide_atapi_pc pc; int ret = 0; debug_log("Reached %s\n", __func__); @@ -1489,7 +1422,7 @@ static int idefloppy_release(struct inode *inode, struct file *filp) struct gendisk *disk = inode->i_bdev->bd_disk; struct ide_floppy_obj *floppy = ide_floppy_g(disk); ide_drive_t *drive = floppy->drive; - idefloppy_pc_t pc; + struct ide_atapi_pc pc; debug_log("Reached %s\n", __func__); @@ -1521,8 +1454,8 @@ static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo) return 0; } -static int ide_floppy_lockdoor(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, - unsigned long arg, unsigned int cmd) +static int ide_floppy_lockdoor(idefloppy_floppy_t *floppy, + struct ide_atapi_pc *pc, unsigned long arg, unsigned int cmd) { if (floppy->openers > 1) return -EBUSY; @@ -1551,7 +1484,7 @@ static int ide_floppy_format_unit(idefloppy_floppy_t *floppy, int __user *arg) { int blocks, length, flags, err = 0; - idefloppy_pc_t pc; + struct ide_atapi_pc pc; if (floppy->openers > 1) { /* Don't format if someone is using the disk */ @@ -1602,7 +1535,7 @@ static int idefloppy_ioctl(struct inode *inode, struct file *file, struct block_device *bdev = inode->i_bdev; struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk); ide_drive_t *drive = floppy->drive; - idefloppy_pc_t pc; + struct ide_atapi_pc pc; void __user *argp = (void __user *)arg; int err; @@ -1664,13 +1597,13 @@ static int idefloppy_revalidate_disk(struct gendisk *disk) } static struct block_device_operations idefloppy_ops = { - .owner = THIS_MODULE, - .open = idefloppy_open, - .release = idefloppy_release, - .ioctl = idefloppy_ioctl, - .getgeo = idefloppy_getgeo, - .media_changed = idefloppy_media_changed, - .revalidate_disk= idefloppy_revalidate_disk + .owner = THIS_MODULE, + .open = idefloppy_open, + .release = idefloppy_release, + .ioctl = idefloppy_ioctl, + .getgeo = idefloppy_getgeo, + .media_changed = idefloppy_media_changed, + .revalidate_disk = idefloppy_revalidate_disk }; static int ide_floppy_probe(ide_drive_t *drive) diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c index 9ebec08eefd9..a6073e248f45 100644 --- a/drivers/ide/ide-generic.c +++ b/drivers/ide/ide-generic.c @@ -1,33 +1,142 @@ /* * generic/default IDE host driver * - * Copyright (C) 2004 Bartlomiej Zolnierkiewicz + * Copyright (C) 2004, 2008 Bartlomiej Zolnierkiewicz * This code was split off from ide.c. See it for original copyrights. * * May be copied or modified under the terms of the GNU General Public License. */ +/* + * For special cases new interfaces may be added using sysfs, i.e. + * + * echo -n "0x168:0x36e:10" > /sys/class/ide_generic/add + * + * will add an interface using I/O ports 0x168-0x16f/0x36e and IRQ 10. + */ + #include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/ide.h> +#define DRV_NAME "ide_generic" + +static ssize_t store_add(struct class *cls, const char *buf, size_t n) +{ + ide_hwif_t *hwif; + unsigned int base, ctl; + int irq; + hw_regs_t hw; + u8 idx[] = { 0xff, 0xff, 0xff, 0xff }; + + if (sscanf(buf, "%x:%x:%d", &base, &ctl, &irq) != 3) + return -EINVAL; + + hwif = ide_find_port(); + if (hwif == NULL) + return -ENOENT; + + memset(&hw, 0, sizeof(hw)); + ide_std_init_ports(&hw, base, ctl); + hw.irq = irq; + hw.chipset = ide_generic; + + ide_init_port_hw(hwif, &hw); + + idx[0] = hwif->index; + + ide_device_add(idx, NULL); + + return n; +}; + +static struct class_attribute ide_generic_class_attrs[] = { + __ATTR(add, S_IWUSR, NULL, store_add), + __ATTR_NULL +}; + +static void ide_generic_class_release(struct class *cls) +{ + kfree(cls); +} + +static int __init ide_generic_sysfs_init(void) +{ + struct class *cls; + int rc; + + cls = kzalloc(sizeof(*cls), GFP_KERNEL); + if (!cls) + return -ENOMEM; + + cls->name = DRV_NAME; + cls->owner = THIS_MODULE; + cls->class_release = ide_generic_class_release; + cls->class_attrs = ide_generic_class_attrs; + + rc = class_register(cls); + if (rc) { + kfree(cls); + return rc; + } + + return 0; +} + static int __init ide_generic_init(void) { u8 idx[MAX_HWIFS]; int i; for (i = 0; i < MAX_HWIFS; i++) { - ide_hwif_t *hwif = &ide_hwifs[i]; + ide_hwif_t *hwif; + unsigned long io_addr = ide_default_io_base(i); + hw_regs_t hw; + + idx[i] = 0xff; + + if (io_addr) { + if (!request_region(io_addr, 8, DRV_NAME)) { + printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX " + "not free.\n", + DRV_NAME, io_addr, io_addr + 7); + continue; + } + + if (!request_region(io_addr + 0x206, 1, DRV_NAME)) { + printk(KERN_ERR "%s: I/O resource 0x%lX " + "not free.\n", + DRV_NAME, io_addr + 0x206); + release_region(io_addr, 8); + continue; + } + + /* + * Skip probing if the corresponding + * slot is already occupied. + */ + hwif = ide_find_port(); + if (hwif == NULL || hwif->index != i) { + idx[i] = 0xff; + continue; + } + + memset(&hw, 0, sizeof(hw)); + ide_std_init_ports(&hw, io_addr, io_addr + 0x206); + hw.irq = ide_default_irq(io_addr); + ide_init_port_hw(hwif, &hw); - if (hwif->io_ports[IDE_DATA_OFFSET] && !hwif->present) idx[i] = i; - else - idx[i] = 0xff; + } } ide_device_add_all(idx, NULL); + if (ide_generic_sysfs_init()) + printk(KERN_ERR DRV_NAME ": failed to create ide_generic " + "class\n"); + return 0; } diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 715379605a7b..788783da9025 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -218,7 +218,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * * we could be smarter and check for current xfer_speed * in struct drive etc... */ - if (drive->hwif->dma_host_set == NULL) + if (drive->hwif->dma_ops == NULL) break; /* * TODO: respect ->using_dma setting @@ -295,48 +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(IDE_DATA_REG); - - 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, IDE_CONTROL_REG); - - if (task->tf_flags & IDE_TFLAG_IN_NSECT) - tf->nsect = hwif->INB(IDE_NSECTOR_REG); - if (task->tf_flags & IDE_TFLAG_IN_LBAL) - tf->lbal = hwif->INB(IDE_SECTOR_REG); - if (task->tf_flags & IDE_TFLAG_IN_LBAM) - tf->lbam = hwif->INB(IDE_LCYL_REG); - if (task->tf_flags & IDE_TFLAG_IN_LBAH) - tf->lbah = hwif->INB(IDE_HCYL_REG); - if (task->tf_flags & IDE_TFLAG_IN_DEVICE) - tf->device = hwif->INB(IDE_SELECT_REG); - - if (task->tf_flags & IDE_TFLAG_LBA48) { - hwif->OUTB(drive->ctl | 0x80, IDE_CONTROL_REG); - - if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) - tf->hob_feature = hwif->INB(IDE_FEATURE_REG); - if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) - tf->hob_nsect = hwif->INB(IDE_NSECTOR_REG); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) - tf->hob_lbal = hwif->INB(IDE_SECTOR_REG); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) - tf->hob_lbam = hwif->INB(IDE_LCYL_REG); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) - tf->hob_lbah = hwif->INB(IDE_HCYL_REG); - } -} - /** * ide_end_drive_cmd - end an explicit drive command * @drive: command @@ -372,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); @@ -421,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); } } @@ -448,7 +406,8 @@ 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(IDE_COMMAND_REG) == WIN_SPECIFY) + hwif->INB(hwif->io_ports.command_addr) == + WIN_SPECIFY) return ide_stopped; } else if ((err & BAD_CRC) == BAD_CRC) { /* UDMA crc error, just retry the operation */ @@ -500,7 +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, IDE_COMMAND_REG); + hwif->OUTBSYNC(drive, WIN_IDLEIMMEDIATE, + hwif->io_ports.command_addr); if (rq->errors >= ERROR_MAX) { ide_kill_rq(drive, rq); @@ -713,15 +673,12 @@ static ide_startstop_t do_special (ide_drive_t *drive) #endif if (s->b.set_tune) { ide_hwif_t *hwif = drive->hwif; + const struct ide_port_ops *port_ops = hwif->port_ops; u8 req_pio = drive->tune_req; s->b.set_tune = 0; if (set_pio_mode_abuse(drive->hwif, req_pio)) { - - if (hwif->set_pio_mode == NULL) - return ide_stopped; - /* * take ide_lock for drive->[no_]unmask/[no_]io_32bit */ @@ -729,10 +686,10 @@ static ide_startstop_t do_special (ide_drive_t *drive) unsigned long flags; spin_lock_irqsave(&ide_lock, flags); - hwif->set_pio_mode(drive, req_pio); + port_ops->set_pio_mode(drive, req_pio); spin_unlock_irqrestore(&ide_lock, flags); } else - hwif->set_pio_mode(drive, req_pio); + port_ops->set_pio_mode(drive, req_pio); } else { int keep_dma = drive->using_dma; @@ -1233,12 +1190,12 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error) if (error < 0) { printk(KERN_WARNING "%s: DMA timeout error\n", drive->name); - (void)HWIF(drive)->ide_dma_end(drive); + (void)hwif->dma_ops->dma_end(drive); ret = ide_error(drive, "dma timeout error", ide_read_status(drive)); } else { printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name); - hwif->dma_timeout(drive); + hwif->dma_ops->dma_timeout(drive); } /* @@ -1350,7 +1307,7 @@ void ide_timer_expiry (unsigned long data) startstop = handler(drive); } else if (drive_is_ready(drive)) { if (drive->waiting_for_dma) - hwgroup->hwif->dma_lost_irq(drive); + hwif->dma_ops->dma_lost_irq(drive); (void)ide_ack_intr(hwif); printk(KERN_WARNING "%s: lost interrupt\n", drive->name); startstop = handler(drive); @@ -1416,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; @@ -1506,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); @@ -1680,7 +1637,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 e77cee0e5d65..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,49 +73,151 @@ 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); void SELECT_DRIVE (ide_drive_t *drive) { - if (HWIF(drive)->selectproc) - HWIF(drive)->selectproc(drive); - HWIF(drive)->OUTB(drive->select.all, IDE_SELECT_REG); + ide_hwif_t *hwif = drive->hwif; + const struct ide_port_ops *port_ops = hwif->port_ops; + + if (port_ops && port_ops->selectproc) + port_ops->selectproc(drive); + + hwif->OUTB(drive->select.all, hwif->io_ports.device_addr); } void SELECT_MASK (ide_drive_t *drive, int mask) { - if (HWIF(drive)->maskproc) - HWIF(drive)->maskproc(drive, mask); + const struct ide_port_ops *port_ops = drive->hwif->port_ops; + + if (port_ops && port_ops->maskproc) + port_ops->maskproc(drive, mask); +} + +static void ide_tf_load(ide_drive_t *drive, ide_task_t *task) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + struct ide_taskfile *tf = &task->tf; + void (*tf_outb)(u8 addr, unsigned long port); + u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; + u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; + + if (mmio) + tf_outb = ide_mm_outb; + else + tf_outb = ide_outb; + + if (task->tf_flags & IDE_TFLAG_FLAGGED) + HIHI = 0xFF; + + ide_set_irq(drive, 1); + + if ((task->tf_flags & IDE_TFLAG_NO_SELECT_MASK) == 0) + SELECT_MASK(drive, 0); + + if (task->tf_flags & IDE_TFLAG_OUT_DATA) { + u16 data = (tf->hob_data << 8) | tf->data; + + if (mmio) + writew(data, (void __iomem *)io_ports->data_addr); + else + outw(data, io_ports->data_addr); + } + + if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) + tf_outb(tf->hob_feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) + tf_outb(tf->hob_nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) + tf_outb(tf->hob_lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) + tf_outb(tf->hob_lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) + tf_outb(tf->hob_lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) + tf_outb(tf->feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_NSECT) + tf_outb(tf->nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAL) + tf_outb(tf->lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAM) + tf_outb(tf->lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAH) + tf_outb(tf->lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) + tf_outb((tf->device & HIHI) | drive->select.all, + io_ports->device_addr); +} + +static void ide_tf_read(ide_drive_t *drive, ide_task_t *task) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + struct ide_taskfile *tf = &task->tf; + void (*tf_outb)(u8 addr, unsigned long port); + u8 (*tf_inb)(unsigned long port); + u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; + + if (mmio) { + tf_outb = ide_mm_outb; + tf_inb = ide_mm_inb; + } else { + tf_outb = ide_outb; + tf_inb = ide_inb; + } + + if (task->tf_flags & IDE_TFLAG_IN_DATA) { + u16 data; + + if (mmio) + data = readw((void __iomem *)io_ports->data_addr); + else + data = inw(io_ports->data_addr); + + tf->data = data & 0xff; + tf->hob_data = (data >> 8) & 0xff; + } + + /* be sure we're looking at the low order bits */ + tf_outb(drive->ctl & ~0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_NSECT) + tf->nsect = tf_inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAL) + tf->lbal = tf_inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAM) + tf->lbam = tf_inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAH) + tf->lbah = tf_inb(io_ports->lbah_addr); + if (task->tf_flags & IDE_TFLAG_IN_DEVICE) + tf->device = tf_inb(io_ports->device_addr); + + if (task->tf_flags & IDE_TFLAG_LBA48) { + tf_outb(drive->ctl | 0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) + tf->hob_feature = tf_inb(io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) + tf->hob_nsect = tf_inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) + tf->hob_lbal = tf_inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) + tf->hob_lbam = tf_inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) + tf->hob_lbah = tf_inb(io_ports->lbah_addr); + } } /* @@ -176,105 +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, IDE_NSECTOR_REG); - hwif->INSL(IDE_DATA_REG, 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(IDE_DATA_REG, buffer, wcount); + + 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 { - hwif->INSW(IDE_DATA_REG, buffer, wcount<<1); + 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; - local_irq_save(flags); - ata_vlb_sync(drive, IDE_NSECTOR_REG); - hwif->OUTSL(IDE_DATA_REG, buffer, wcount); - local_irq_restore(flags); - } else - hwif->OUTSL(IDE_DATA_REG, buffer, wcount); - } else { - hwif->OUTSW(IDE_DATA_REG, 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. - */ + unsigned long uninitialized_var(flags); -static void atapi_input_bytes(ide_drive_t *drive, void *buffer, u32 bytecount) -{ - ide_hwif_t *hwif = HWIF(drive); + if ((io_32bit & 2) && !mmio) { + local_irq_save(flags); + 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(IDE_DATA_REG, buffer, bytecount / 2); - return; - } -#endif /* CONFIG_ATARI || CONFIG_Q40 */ - hwif->ata_input_data(drive, buffer, bytecount / 4); - if ((bytecount & 0x03) >= 2) - hwif->INSW(IDE_DATA_REG, ((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(IDE_DATA_REG, 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(IDE_DATA_REG, ((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) @@ -416,7 +474,7 @@ int drive_is_ready (ide_drive_t *drive) u8 stat = 0; if (drive->waiting_for_dma) - return hwif->ide_dma_test_irq(drive); + return hwif->dma_ops->dma_test_irq(drive); #if 0 /* need to guarantee 400ns since last command was issued */ @@ -429,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 (IDE_CONTROL_REG) + if (hwif->io_ports.ctl_addr) stat = ide_read_altstatus(drive); else /* Note: this may clear a pending IRQ!! */ @@ -567,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 } }; @@ -631,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, IDE_COMMAND_REG); + hwif->OUTBSYNC(drive, WIN_IDENTIFY, hwif->io_ports.command_addr); timeout = jiffies + WAIT_WORSTCASE; do { if (time_after(jiffies, timeout)) { @@ -658,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); @@ -680,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; @@ -687,8 +748,8 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) // msleep(50); #ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_host_set) /* check if host supports DMA */ - hwif->dma_host_set(drive, 0); + if (hwif->dma_ops) /* check if host supports DMA */ + hwif->dma_ops->dma_host_set(drive, 0); #endif /* Skip setting PIO flow-control modes on pre-EIDE drives */ @@ -718,9 +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, IDE_NSECTOR_REG); - hwif->OUTB(SETFEATURES_XFER, IDE_FEATURE_REG); - hwif->OUTBSYNC(drive, WIN_SETFEATURES, IDE_COMMAND_REG); + 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); @@ -745,8 +806,8 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) #ifdef CONFIG_BLK_DEV_IDEDMA if ((speed >= XFER_SW_DMA_0 || (hwif->host_flags & IDE_HFLAG_VDMA)) && drive->using_dma) - hwif->dma_host_set(drive, 1); - else if (hwif->dma_host_set) /* check if host supports DMA */ + hwif->dma_ops->dma_host_set(drive, 1); + else if (hwif->dma_ops) /* check if host supports DMA */ ide_dma_off_quietly(drive); #endif @@ -828,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, IDE_COMMAND_REG); + hwif->OUTBSYNC(drive, cmd, hwif->io_ports.command_addr); /* * Drive takes 400nS to respond, we must avoid the IRQ being * serviced before that. @@ -838,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); @@ -891,10 +962,11 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive) { ide_hwgroup_t *hwgroup = HWGROUP(drive); ide_hwif_t *hwif = HWIF(drive); + const struct ide_port_ops *port_ops = hwif->port_ops; u8 tmp; - if (hwif->reset_poll != NULL) { - if (hwif->reset_poll(drive)) { + if (port_ops && port_ops->reset_poll) { + if (port_ops->reset_poll(drive)) { printk(KERN_ERR "%s: host reset_poll failure for %s.\n", hwif->name, drive->name); return ide_stopped; @@ -960,6 +1032,8 @@ static void ide_disk_pre_reset(ide_drive_t *drive) static void pre_reset(ide_drive_t *drive) { + const struct ide_port_ops *port_ops = drive->hwif->port_ops; + if (drive->media == ide_disk) ide_disk_pre_reset(drive); else @@ -980,8 +1054,8 @@ static void pre_reset(ide_drive_t *drive) return; } - if (HWIF(drive)->pre_reset != NULL) - HWIF(drive)->pre_reset(drive); + if (port_ops && port_ops->pre_reset) + port_ops->pre_reset(drive); if (drive->current_speed != 0xff) drive->desired_speed = drive->current_speed; @@ -1009,11 +1083,16 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) unsigned long flags; ide_hwif_t *hwif; ide_hwgroup_t *hwgroup; - + struct ide_io_ports *io_ports; + const struct ide_port_ops *port_ops; + u8 ctl; + spin_lock_irqsave(&ide_lock, flags); hwif = HWIF(drive); hwgroup = HWGROUP(drive); + io_ports = &hwif->io_ports; + /* We must not reset with running handlers */ BUG_ON(hwgroup->handler != NULL); @@ -1023,7 +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, IDE_COMMAND_REG); + hwif->OUTBSYNC(drive, WIN_SRST, io_ports->command_addr); ndelay(400); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; hwgroup->polling = 1; @@ -1039,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 (!IDE_CONTROL_REG) { + if (io_ports->ctl_addr == 0) { spin_unlock_irqrestore(&ide_lock, flags); return ide_stopped; } @@ -1054,16 +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,IDE_CONTROL_REG); + hwif->OUTBSYNC(drive, drive->ctl|6, io_ports->ctl_addr); /* more than enough time */ udelay(10); - if (drive->quirk_list == 2) { - /* clear SRST and nIEN */ - hwif->OUTBSYNC(drive, drive->ctl, IDE_CONTROL_REG); - } else { - /* clear SRST, leave nIEN */ - hwif->OUTBSYNC(drive, drive->ctl|2, IDE_CONTROL_REG); - } + 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, io_ports->ctl_addr); /* more than enough time */ udelay(10); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; @@ -1075,8 +1152,9 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) * state when the disks are reset this way. At least, the Winbond * 553 documentation says that */ - if (hwif->resetproc) - hwif->resetproc(drive); + port_ops = hwif->port_ops; + if (port_ops && port_ops->resetproc) + port_ops->resetproc(drive); spin_unlock_irqrestore(&ide_lock, flags); return ide_started; @@ -1107,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 7031a8dcf692..47af80df6872 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -85,7 +85,7 @@ static u8 ide_rate_filter(ide_drive_t *drive, u8 speed) mode = XFER_PIO_4; } -// printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed); +/* printk("%s: mode 0x%02x, speed 0x%02x\n", __func__, mode, speed); */ return min(speed, mode); } @@ -274,16 +274,6 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode) if (overridden) printk(KERN_INFO "%s: tPIO > 2, assuming tPIO = 2\n", drive->name); - - /* - * Conservative "downgrade" for all pre-ATA2 drives - */ - if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_DOWNGRADE) == 0 && - pio_mode && pio_mode < 4) { - pio_mode--; - printk(KERN_INFO "%s: applying conservative " - "PIO \"downgrade\"\n", drive->name); - } } if (pio_mode > max_mode) @@ -298,9 +288,11 @@ EXPORT_SYMBOL_GPL(ide_get_best_pio_mode); void ide_set_pio(ide_drive_t *drive, u8 req_pio) { ide_hwif_t *hwif = drive->hwif; + const struct ide_port_ops *port_ops = hwif->port_ops; u8 host_pio, pio; - if (hwif->set_pio_mode == NULL) + if (port_ops == NULL || port_ops->set_pio_mode == NULL || + (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) return; BUG_ON(hwif->pio_mask == 0x00); @@ -352,26 +344,30 @@ void ide_toggle_bounce(ide_drive_t *drive, int on) int ide_set_pio_mode(ide_drive_t *drive, const u8 mode) { ide_hwif_t *hwif = drive->hwif; + const struct ide_port_ops *port_ops = hwif->port_ops; + + if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE) + return 0; - if (hwif->set_pio_mode == NULL) + if (port_ops == NULL || port_ops->set_pio_mode == NULL) return -1; /* * TODO: temporary hack for some legacy host drivers that didn't * set transfer mode on the device in ->set_pio_mode method... */ - if (hwif->set_dma_mode == NULL) { - hwif->set_pio_mode(drive, mode - XFER_PIO_0); + if (port_ops->set_dma_mode == NULL) { + port_ops->set_pio_mode(drive, mode - XFER_PIO_0); return 0; } if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) { if (ide_config_drive_speed(drive, mode)) return -1; - hwif->set_pio_mode(drive, mode - XFER_PIO_0); + port_ops->set_pio_mode(drive, mode - XFER_PIO_0); return 0; } else { - hwif->set_pio_mode(drive, mode - XFER_PIO_0); + port_ops->set_pio_mode(drive, mode - XFER_PIO_0); return ide_config_drive_speed(drive, mode); } } @@ -379,17 +375,21 @@ int ide_set_pio_mode(ide_drive_t *drive, const u8 mode) int ide_set_dma_mode(ide_drive_t *drive, const u8 mode) { ide_hwif_t *hwif = drive->hwif; + const struct ide_port_ops *port_ops = hwif->port_ops; + + if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE) + return 0; - if (hwif->set_dma_mode == NULL) + if (port_ops == NULL || port_ops->set_dma_mode == NULL) return -1; if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) { if (ide_config_drive_speed(drive, mode)) return -1; - hwif->set_dma_mode(drive, mode); + port_ops->set_dma_mode(drive, mode); return 0; } else { - hwif->set_dma_mode(drive, mode); + port_ops->set_dma_mode(drive, mode); return ide_config_drive_speed(drive, mode); } } @@ -409,8 +409,10 @@ EXPORT_SYMBOL_GPL(ide_set_dma_mode); int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) { ide_hwif_t *hwif = drive->hwif; + const struct ide_port_ops *port_ops = hwif->port_ops; - if (hwif->set_dma_mode == NULL) + if (port_ops == NULL || port_ops->set_dma_mode == NULL || + (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) return -1; rate = ide_rate_filter(drive, rate); @@ -485,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 c14bb5380c25..6a8953f68e9f 100644 --- a/drivers/ide/ide-pnp.c +++ b/drivers/ide/ide-pnp.c @@ -11,34 +11,52 @@ * * You should have received a copy of the GNU General Public License * (for example /usr/src/linux/COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/init.h> #include <linux/pnp.h> #include <linux/ide.h> +#define DRV_NAME "ide-pnp" + /* Add your devices here :)) */ static struct pnp_device_id idepnp_devices[] = { - /* Generic ESDI/IDE/ATA compatible hard disk controller */ + /* Generic ESDI/IDE/ATA compatible hard disk controller */ {.id = "PNP0600", .driver_data = 0}, {.id = ""} }; -static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id) +static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) { hw_regs_t hw; ide_hwif_t *hwif; + unsigned long base, ctl; if (!(pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && pnp_irq_valid(dev, 0))) return -1; + base = pnp_port_start(dev, 0); + ctl = pnp_port_start(dev, 1); + + if (!request_region(base, 8, DRV_NAME)) { + printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", + DRV_NAME, base, base + 7); + return -EBUSY; + } + + if (!request_region(ctl, 1, DRV_NAME)) { + printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n", + DRV_NAME, ctl); + release_region(base, 8); + return -EBUSY; + } + memset(&hw, 0, sizeof(hw)); - ide_std_init_ports(&hw, pnp_port_start(dev, 0), - pnp_port_start(dev, 1)); + ide_std_init_ports(&hw, base, ctl); hw.irq = pnp_irq(dev, 0); - hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]); + hwif = ide_find_port(); if (hwif) { u8 index = hwif->index; u8 idx[4] = { index, 0xff, 0xff, 0xff }; @@ -47,24 +65,27 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id ide_init_port_hw(hwif, &hw); printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index); - pnp_set_drvdata(dev,hwif); + pnp_set_drvdata(dev, hwif); ide_device_add(idx, NULL); return 0; } + release_region(ctl, 1); + release_region(base, 8); + return -1; } -static void idepnp_remove(struct pnp_dev * dev) +static void idepnp_remove(struct pnp_dev *dev) { ide_hwif_t *hwif = pnp_get_drvdata(dev); - if (hwif) - ide_unregister(hwif->index, 0, 0); - 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); } static struct pnp_driver idepnp_driver = { diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 47a114927c31..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 (IDE_CONTROL_REG) { + 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, IDE_FEATURE_REG); + hwif->OUTB(0, io_ports->feature_addr); /* ask drive for ID */ - hwif->OUTB(cmd, IDE_COMMAND_REG); + 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 (IDE_CONTROL_REG) { + 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,8 @@ static int do_probe (ide_drive_t *drive, u8 cmd) msleep(50); SELECT_DRIVE(drive); msleep(50); - if (hwif->INB(IDE_SELECT_REG) != drive->select.all && !drive->present) { + if (hwif->INB(io_ports->device_addr) != drive->select.all && + !drive->present) { if (drive->select.b.unit != 0) { /* exit with drive0 selected */ SELECT_DRIVE(&hwif->drives[0]); @@ -471,15 +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, IDE_SELECT_REG); + hwif->OUTB(drive->select.all, io_ports->device_addr); msleep(50); - hwif->OUTB(WIN_SRST, IDE_COMMAND_REG); + hwif->OUTBSYNC(drive, WIN_SRST, io_ports->command_addr); (void)ide_busy_sleep(hwif); rc = try_to_identify(drive, cmd); } @@ -515,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, IDE_COMMAND_REG); + hwif->OUTBSYNC(drive, EXABYTE_ENABLE_NEST, hwif->io_ports.command_addr); if (ide_busy_sleep(hwif)) { printk(KERN_CONT "failed (timeout)\n"); @@ -623,7 +624,7 @@ static void hwif_release_dev (struct device *dev) complete(&hwif->gendev_rel_comp); } -static void ide_register_port(ide_hwif_t *hwif) +static int ide_register_port(ide_hwif_t *hwif) { int ret; @@ -639,9 +640,23 @@ static void ide_register_port(ide_hwif_t *hwif) } hwif->gendev.release = hwif_release_dev; ret = device_register(&hwif->gendev); - if (ret < 0) + if (ret < 0) { printk(KERN_WARNING "IDE: %s: device_register error: %d\n", - __FUNCTION__, ret); + __func__, ret); + goto out; + } + + get_device(&hwif->gendev); + + hwif->portdev = device_create(ide_port_class, &hwif->gendev, + MKDEV(0, 0), hwif->name); + if (IS_ERR(hwif->portdev)) { + ret = PTR_ERR(hwif->portdev); + device_unregister(&hwif->gendev); + } + dev_set_drvdata(hwif->portdev, hwif); +out: + return ret; } /** @@ -756,8 +771,7 @@ static int ide_probe_port(ide_hwif_t *hwif) BUG_ON(hwif->present); - if (hwif->noprobe || - (hwif->drives[0].noprobe && hwif->drives[1].noprobe)) + if (hwif->drives[0].noprobe && hwif->drives[1].noprobe) return -EACCES; /* @@ -784,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 @@ -804,29 +813,25 @@ static int ide_probe_port(ide_hwif_t *hwif) static void ide_port_tune_devices(ide_hwif_t *hwif) { + const struct ide_port_ops *port_ops = hwif->port_ops; int unit; for (unit = 0; unit < MAX_DRIVES; unit++) { ide_drive_t *drive = &hwif->drives[unit]; - if (drive->present && hwif->quirkproc) - hwif->quirkproc(drive); + if (drive->present && port_ops && port_ops->quirkproc) + port_ops->quirkproc(drive); } for (unit = 0; unit < MAX_DRIVES; ++unit) { 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; - if (hwif->dma_host_set) + if (hwif->dma_ops) ide_set_dma(drive); } } @@ -949,6 +954,7 @@ static void ide_port_setup_devices(ide_hwif_t *hwif) { int i; + mutex_lock(&ide_cfg_mtx); for (i = 0; i < MAX_DRIVES; i++) { ide_drive_t *drive = &hwif->drives[i]; @@ -963,6 +969,7 @@ static void ide_port_setup_devices(ide_hwif_t *hwif) ide_add_drive_to_hwgroup(drive); } + mutex_unlock(&ide_cfg_mtx); } /* @@ -975,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; @@ -1058,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; @@ -1076,20 +1084,17 @@ 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)", hwif->sharing_irq ? "shar" : "serializ", match->name); printk("\n"); - ide_port_setup_devices(hwif); - mutex_unlock(&ide_cfg_mtx); return 0; out_unlink: @@ -1199,6 +1204,8 @@ static void drive_release_dev (struct device *dev) { ide_drive_t *drive = container_of(dev, ide_drive_t, gendev); + ide_proc_unregister_device(drive); + spin_lock_irq(&ide_lock); ide_remove_drive_from_hwgroup(drive); kfree(drive->id); @@ -1214,24 +1221,21 @@ static void drive_release_dev (struct device *dev) complete(&drive->gendev_rel_comp); } +#ifndef ide_default_irq +#define ide_default_irq(irq) 0 +#endif + 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; } } -#ifdef CONFIG_BLK_DEV_HD - if (hwif->irq == HD_IRQ && hwif->io_ports[IDE_DATA_OFFSET] != HD_DATA) { - printk("%s: CANNOT SHARE IRQ WITH OLD " - "HARDDISK DRIVER (hd.c)\n", hwif->name); - return 0; - } -#endif /* CONFIG_BLK_DEV_HD */ if (register_blkdev(hwif->major, hwif->name)) return 0; @@ -1256,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; @@ -1308,6 +1313,7 @@ static void hwif_register_devices(ide_hwif_t *hwif) static void ide_port_init_devices(ide_hwif_t *hwif) { + const struct ide_port_ops *port_ops = hwif->port_ops; int i; for (i = 0; i < MAX_DRIVES; i++) { @@ -1319,12 +1325,10 @@ 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 (hwif->port_init_devs) - hwif->port_init_devs(hwif); + if (port_ops && port_ops->port_init_devs) + port_ops->port_init_devs(hwif); } static void ide_init_port(ide_hwif_t *hwif, unsigned int port, @@ -1339,9 +1343,6 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port, if (d->init_iops) d->init_iops(hwif); - if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) - ide_hwif_setup_dma(hwif, d); - if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) hwif->irq = port ? 15 : 14; @@ -1349,16 +1350,36 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port, hwif->host_flags = d->host_flags; hwif->pio_mask = d->pio_mask; - if ((d->host_flags & IDE_HFLAG_SERIALIZE) && hwif->mate) - hwif->mate->serialized = hwif->serialized = 1; + /* ->set_pio_mode for DTC2278 is currently limited to port 0 */ + if (hwif->chipset != ide_dtc2278 || hwif->channel == 0) + hwif->port_ops = d->port_ops; + + if ((d->host_flags & IDE_HFLAG_SERIALIZE) || + ((d->host_flags & IDE_HFLAG_SERIALIZE_DMA) && hwif->dma_base)) { + if (hwif->mate) + hwif->mate->serialized = hwif->serialized = 1; + } hwif->swdma_mask = d->swdma_mask; hwif->mwdma_mask = d->mwdma_mask; hwif->ultra_mask = d->udma_mask; - /* reset DMA masks only for SFF-style DMA controllers */ - if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0 && hwif->dma_base == 0) - hwif->swdma_mask = hwif->mwdma_mask = hwif->ultra_mask = 0; + if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) { + int rc; + + if (d->init_dma) + rc = d->init_dma(hwif, d); + else + rc = ide_hwif_setup_dma(hwif, d); + + if (rc < 0) { + printk(KERN_INFO "%s: DMA disabled\n", hwif->name); + hwif->swdma_mask = 0; + hwif->mwdma_mask = 0; + hwif->ultra_mask = 0; + } else if (d->dma_ops) + hwif->dma_ops = d->dma_ops; + } if (d->host_flags & IDE_HFLAG_RQSIZE_256) hwif->rqsize = 256; @@ -1366,26 +1387,138 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port, /* call chipset specific routine for each enabled port */ if (d->init_hwif) d->init_hwif(hwif); +} - if (hwif->cable_detect && (hwif->ultra_mask & 0x78)) { +static void ide_port_cable_detect(ide_hwif_t *hwif) +{ + const struct ide_port_ops *port_ops = hwif->port_ops; + + if (port_ops && port_ops->cable_detect && (hwif->ultra_mask & 0x78)) { if (hwif->cbl != ATA_CBL_PATA40_SHORT) - hwif->cbl = hwif->cable_detect(hwif); + hwif->cbl = port_ops->cable_detect(hwif); } } +static ssize_t store_delete_devices(struct device *portdev, + struct device_attribute *attr, + const char *buf, size_t n) +{ + ide_hwif_t *hwif = dev_get_drvdata(portdev); + + if (strncmp(buf, "1", n)) + return -EINVAL; + + ide_port_unregister_devices(hwif); + + return n; +}; + +static DEVICE_ATTR(delete_devices, S_IWUSR, NULL, store_delete_devices); + +static ssize_t store_scan(struct device *portdev, + struct device_attribute *attr, + const char *buf, size_t n) +{ + ide_hwif_t *hwif = dev_get_drvdata(portdev); + + if (strncmp(buf, "1", n)) + return -EINVAL; + + ide_port_unregister_devices(hwif); + ide_port_scan(hwif); + + return n; +}; + +static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan); + +static struct device_attribute *ide_port_attrs[] = { + &dev_attr_delete_devices, + &dev_attr_scan, + NULL +}; + +static int ide_sysfs_register_port(ide_hwif_t *hwif) +{ + int i, rc; + + for (i = 0; ide_port_attrs[i]; i++) { + rc = device_create_file(hwif->portdev, ide_port_attrs[i]); + if (rc) + break; + } + + return rc; +} + +/** + * ide_find_port_slot - find free ide_hwifs[] slot + * @d: IDE port info + * + * Return the new hwif. If we are out of free slots return NULL. + */ + +ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d) +{ + ide_hwif_t *hwif; + int i; + u8 bootable = (d && (d->host_flags & IDE_HFLAG_NON_BOOTABLE)) ? 0 : 1; + + /* + * Claim an unassigned slot. + * + * Give preference to claiming other slots before claiming ide0/ide1, + * just in case there's another interface yet-to-be-scanned + * which uses ports 0x1f0/0x170 (the ide0/ide1 defaults). + * + * Unless there is a bootable card that does not use the standard + * ports 0x1f0/0x170 (the ide0/ide1 defaults). + */ + if (bootable) { + i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0; + + for (; i < MAX_HWIFS; i++) { + hwif = &ide_hwifs[i]; + if (hwif->chipset == ide_unknown) + return hwif; + } + } else { + for (i = 2; i < MAX_HWIFS; i++) { + hwif = &ide_hwifs[i]; + if (hwif->chipset == ide_unknown) + return hwif; + } + for (i = 0; i < 2 && i < MAX_HWIFS; i++) { + hwif = &ide_hwifs[i]; + if (hwif->chipset == ide_unknown) + return hwif; + } + } + + return NULL; +} +EXPORT_SYMBOL_GPL(ide_find_port_slot); + int ide_device_add_all(u8 *idx, const struct ide_port_info *d) { ide_hwif_t *hwif, *mate = NULL; 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; @@ -1394,6 +1527,7 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) mate = (i & 1) ? NULL : hwif; ide_init_port(hwif, i & 1, d); + ide_port_cable_detect(hwif); ide_port_init_devices(hwif); } @@ -1403,25 +1537,15 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) hwif = &ide_hwifs[idx[i]]; - if ((hwif->chipset != ide_4drives || !hwif->mate || - !hwif->mate->present) && ide_hwif_request_regions(hwif)) { - printk(KERN_ERR "%s: ports already in use, " - "skipping probe\n", hwif->name); - continue; - } - - if (ide_probe_port(hwif) < 0) { - ide_hwif_release_regions(hwif); - continue; - } - - hwif->present = 1; + if (ide_probe_port(hwif) == 0) + hwif->present = 1; if (hwif->chipset != ide_4drives || !hwif->mate || !hwif->mate->present) ide_register_port(hwif); - ide_port_tune_devices(hwif); + if (hwif->present) + ide_port_tune_devices(hwif); } for (i = 0; i < MAX_HWIFS; i++) { @@ -1430,9 +1554,6 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) hwif = &ide_hwifs[idx[i]]; - if (!hwif->present) - continue; - if (hwif_init(hwif) == 0) { printk(KERN_INFO "%s: failed to initialize IDE " "interface\n", hwif->name); @@ -1441,8 +1562,13 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) continue; } + if (hwif->present) + ide_port_setup_devices(hwif); + ide_acpi_init(hwif); - ide_acpi_port_init_devices(hwif); + + if (hwif->present) + ide_acpi_port_init_devices(hwif); } for (i = 0; i < MAX_HWIFS; i++) { @@ -1451,12 +1577,11 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) hwif = &ide_hwifs[idx[i]]; - if (hwif->present) { - if (hwif->chipset == ide_unknown || - hwif->chipset == ide_forced) - hwif->chipset = ide_generic; + if (hwif->chipset == ide_unknown) + hwif->chipset = ide_generic; + + if (hwif->present) hwif_register_devices(hwif); - } } for (i = 0; i < MAX_HWIFS; i++) { @@ -1465,10 +1590,11 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) hwif = &ide_hwifs[idx[i]]; - if (hwif->present) { - ide_proc_register_port(hwif); + ide_sysfs_register_port(hwif); + ide_proc_register_port(hwif); + + if (hwif->present) ide_proc_port_register_devices(hwif); - } } return rc; @@ -1486,3 +1612,86 @@ int ide_device_add(u8 idx[4], const struct ide_port_info *d) return ide_device_add_all(idx_all, d); } 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); + + if (ide_probe_port(hwif) < 0) + return; + + hwif->present = 1; + + ide_port_tune_devices(hwif); + ide_acpi_port_init_devices(hwif); + ide_port_setup_devices(hwif); + hwif_register_devices(hwif); + ide_proc_port_register_devices(hwif); +} +EXPORT_SYMBOL_GPL(ide_port_scan); + +static void ide_legacy_init_one(u8 *idx, hw_regs_t *hw, u8 port_no, + const struct ide_port_info *d, + unsigned long config) +{ + ide_hwif_t *hwif; + unsigned long base, ctl; + int irq; + + if (port_no == 0) { + base = 0x1f0; + ctl = 0x3f6; + irq = 14; + } else { + base = 0x170; + ctl = 0x376; + irq = 15; + } + + if (!request_region(base, 8, d->name)) { + printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", + d->name, base, base + 7); + return; + } + + if (!request_region(ctl, 1, d->name)) { + printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n", + d->name, ctl); + release_region(base, 8); + return; + } + + ide_std_init_ports(hw, base, ctl); + hw->irq = irq; + + hwif = ide_find_port_slot(d); + if (hwif) { + ide_init_port_hw(hwif, hw); + if (config) + hwif->config_data = config; + idx[port_no] = hwif->index; + } +} + +int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config) +{ + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; + hw_regs_t hw[2]; + + memset(&hw, 0, sizeof(hw)); + + if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0) + ide_legacy_init_one(idx, &hw[0], 0, d, config); + ide_legacy_init_one(idx, &hw[1], 1, d, config); + + if (idx[0] == 0xff && idx[1] == 0xff && + (d->host_flags & IDE_HFLAG_SINGLE)) + return -ENOENT; + + ide_device_add(idx, d); + + return 0; +} +EXPORT_SYMBOL_GPL(ide_legacy_device_add); diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index bab88ca7f7ec..7b2f3815a838 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -46,32 +46,29 @@ static int proc_ide_read_imodel int len; const char *name; - /* - * Neither ide_unknown nor ide_forced should be set at this point. - */ switch (hwif->chipset) { - case ide_generic: name = "generic"; break; - case ide_pci: name = "pci"; break; - case ide_cmd640: name = "cmd640"; break; - case ide_dtc2278: name = "dtc2278"; break; - case ide_ali14xx: name = "ali14xx"; break; - case ide_qd65xx: name = "qd65xx"; break; - case ide_umc8672: name = "umc8672"; break; - case ide_ht6560b: name = "ht6560b"; break; - case ide_rz1000: name = "rz1000"; break; - case ide_trm290: name = "trm290"; break; - case ide_cmd646: name = "cmd646"; break; - case ide_cy82c693: name = "cy82c693"; break; - case ide_4drives: name = "4drives"; break; - case ide_pmac: name = "mac-io"; break; - case ide_au1xxx: name = "au1xxx"; break; - case ide_palm3710: name = "palm3710"; break; - case ide_etrax100: name = "etrax100"; break; - case ide_acorn: name = "acorn"; break; - default: name = "(unknown)"; break; + case ide_generic: name = "generic"; break; + case ide_pci: name = "pci"; break; + case ide_cmd640: name = "cmd640"; break; + case ide_dtc2278: name = "dtc2278"; break; + case ide_ali14xx: name = "ali14xx"; break; + case ide_qd65xx: name = "qd65xx"; break; + case ide_umc8672: name = "umc8672"; break; + case ide_ht6560b: name = "ht6560b"; break; + case ide_rz1000: name = "rz1000"; break; + case ide_trm290: name = "trm290"; break; + case ide_cmd646: name = "cmd646"; break; + case ide_cy82c693: name = "cy82c693"; break; + case ide_4drives: name = "4drives"; break; + case ide_pmac: name = "mac-io"; break; + case ide_au1xxx: name = "au1xxx"; break; + case ide_palm3710: name = "palm3710"; break; + case ide_etrax100: name = "etrax100"; break; + case ide_acorn: name = "acorn"; break; + default: name = "(unknown)"; break; } len = sprintf(page, "%s\n", name); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); + PROC_IDE_READ_RETURN(page, start, off, count, eof, len); } static int proc_ide_read_mate @@ -84,7 +81,7 @@ static int proc_ide_read_mate len = sprintf(page, "%s\n", hwif->mate->name); else len = sprintf(page, "(none)\n"); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); + PROC_IDE_READ_RETURN(page, start, off, count, eof, len); } static int proc_ide_read_channel @@ -96,7 +93,7 @@ static int proc_ide_read_channel page[0] = hwif->channel ? '1' : '0'; page[1] = '\n'; len = 2; - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); + PROC_IDE_READ_RETURN(page, start, off, count, eof, len); } static int proc_ide_read_identify @@ -123,7 +120,7 @@ static int proc_ide_read_identify len = out - page; } } - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); + PROC_IDE_READ_RETURN(page, start, off, count, eof, len); } /** @@ -200,7 +197,7 @@ EXPORT_SYMBOL(ide_add_setting); * The caller must hold the setting semaphore. */ -static void __ide_remove_setting (ide_drive_t *drive, char *name) +static void __ide_remove_setting(ide_drive_t *drive, char *name) { ide_settings_t **p, *setting; @@ -208,7 +205,8 @@ static void __ide_remove_setting (ide_drive_t *drive, char *name) while ((*p) && strcmp((*p)->name, name)) p = &((*p)->next); - if ((setting = (*p)) == NULL) + setting = (*p); + if (setting == NULL) return; (*p) = setting->next; @@ -226,7 +224,7 @@ static void __ide_remove_setting (ide_drive_t *drive, char *name) * caller must hold ide_setting_mtx. */ -static void auto_remove_settings (ide_drive_t *drive) +static void auto_remove_settings(ide_drive_t *drive) { ide_settings_t *setting; repeat: @@ -282,16 +280,16 @@ static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting) if ((setting->rw & SETTING_READ)) { spin_lock_irqsave(&ide_lock, flags); - switch(setting->data_type) { - case TYPE_BYTE: - val = *((u8 *) setting->data); - break; - case TYPE_SHORT: - val = *((u16 *) setting->data); - break; - case TYPE_INT: - val = *((u32 *) setting->data); - break; + switch (setting->data_type) { + case TYPE_BYTE: + val = *((u8 *) setting->data); + break; + case TYPE_SHORT: + val = *((u16 *) setting->data); + break; + case TYPE_INT: + val = *((u32 *) setting->data); + break; } spin_unlock_irqrestore(&ide_lock, flags); } @@ -329,15 +327,15 @@ static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int va if (ide_spin_wait_hwgroup(drive)) return -EBUSY; switch (setting->data_type) { - case TYPE_BYTE: - *((u8 *) setting->data) = val; - break; - case TYPE_SHORT: - *((u16 *) setting->data) = val; - break; - case TYPE_INT: - *((u32 *) setting->data) = val; - break; + case TYPE_BYTE: + *((u8 *) setting->data) = val; + break; + case TYPE_SHORT: + *((u16 *) setting->data) = val; + break; + case TYPE_INT: + *((u32 *) setting->data) = val; + break; } spin_unlock_irq(&ide_lock); return 0; @@ -393,7 +391,7 @@ void ide_add_generic_settings (ide_drive_t *drive) static void proc_ide_settings_warn(void) { - static int warned = 0; + static int warned; if (warned) return; @@ -416,11 +414,12 @@ static int proc_ide_read_settings mutex_lock(&ide_setting_mtx); out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n"); out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n"); - while(setting) { + while (setting) { mul_factor = setting->mul_factor; div_factor = setting->div_factor; out += sprintf(out, "%-24s", setting->name); - if ((rc = ide_read_setting(drive, setting)) >= 0) + rc = ide_read_setting(drive, setting); + if (rc >= 0) out += sprintf(out, "%-16d", rc * mul_factor / div_factor); else out += sprintf(out, "%-16s", "write-only"); @@ -434,7 +433,7 @@ static int proc_ide_read_settings } len = out - page; mutex_unlock(&ide_setting_mtx); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); + PROC_IDE_READ_RETURN(page, start, off, count, eof, len); } #define MAX_LEN 30 @@ -515,8 +514,7 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer, mutex_lock(&ide_setting_mtx); setting = ide_find_setting_by_name(drive, name); - if (!setting) - { + if (!setting) { mutex_unlock(&ide_setting_mtx); goto parse_error; } @@ -536,8 +534,8 @@ parse_error: int proc_ide_read_capacity (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = sprintf(page,"%llu\n", (long long)0x7fffffff); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); + int len = sprintf(page, "%llu\n", (long long)0x7fffffff); + PROC_IDE_READ_RETURN(page, start, off, count, eof, len); } EXPORT_SYMBOL_GPL(proc_ide_read_capacity); @@ -549,13 +547,13 @@ int proc_ide_read_geometry char *out = page; int len; - out += sprintf(out,"physical %d/%d/%d\n", + out += sprintf(out, "physical %d/%d/%d\n", drive->cyl, drive->head, drive->sect); - out += sprintf(out,"logical %d/%d/%d\n", + out += sprintf(out, "logical %d/%d/%d\n", drive->bios_cyl, drive->bios_head, drive->bios_sect); len = out - page; - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); + PROC_IDE_READ_RETURN(page, start, off, count, eof, len); } EXPORT_SYMBOL(proc_ide_read_geometry); @@ -569,7 +567,7 @@ static int proc_ide_read_dmodel len = sprintf(page, "%.40s\n", (id && id->model[0]) ? (char *)id->model : "(none)"); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); + PROC_IDE_READ_RETURN(page, start, off, count, eof, len); } static int proc_ide_read_driver @@ -586,7 +584,7 @@ static int proc_ide_read_driver dev->driver->name, ide_drv->version); } else len = sprintf(page, "ide-default version 0.9.newide\n"); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); + PROC_IDE_READ_RETURN(page, start, off, count, eof, len); } static int ide_replace_subdriver(ide_drive_t *drive, const char *driver) @@ -601,14 +599,14 @@ static int ide_replace_subdriver(ide_drive_t *drive, const char *driver) err = device_attach(dev); if (err < 0) printk(KERN_WARNING "IDE: %s: device_attach error: %d\n", - __FUNCTION__, err); + __func__, err); drive->driver_req[0] = 0; if (dev->driver == NULL) { err = device_attach(dev); if (err < 0) printk(KERN_WARNING "IDE: %s: device_attach(2) error: %d\n", - __FUNCTION__, err); + __func__, err); } if (dev->driver && !strcmp(dev->driver->name, driver)) ret = 0; @@ -642,30 +640,26 @@ static int proc_ide_read_media int len; switch (drive->media) { - case ide_disk: media = "disk\n"; - break; - case ide_cdrom: media = "cdrom\n"; - break; - case ide_tape: media = "tape\n"; - break; - case ide_floppy:media = "floppy\n"; - break; - case ide_optical:media = "optical\n"; - break; - default: media = "UNKNOWN\n"; - break; + case ide_disk: media = "disk\n"; break; + case ide_cdrom: media = "cdrom\n"; break; + case ide_tape: media = "tape\n"; break; + case ide_floppy: media = "floppy\n"; break; + case ide_optical: media = "optical\n"; break; + default: media = "UNKNOWN\n"; break; } - strcpy(page,media); + strcpy(page, media); len = strlen(media); - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); + PROC_IDE_READ_RETURN(page, start, off, count, eof, len); } static ide_proc_entry_t generic_drive_entries[] = { - { "driver", S_IFREG|S_IRUGO, proc_ide_read_driver, proc_ide_write_driver }, - { "identify", S_IFREG|S_IRUSR, proc_ide_read_identify, NULL }, - { "media", S_IFREG|S_IRUGO, proc_ide_read_media, NULL }, - { "model", S_IFREG|S_IRUGO, proc_ide_read_dmodel, NULL }, - { "settings", S_IFREG|S_IRUSR|S_IWUSR,proc_ide_read_settings, proc_ide_write_settings }, + { "driver", S_IFREG|S_IRUGO, proc_ide_read_driver, + proc_ide_write_driver }, + { "identify", S_IFREG|S_IRUSR, proc_ide_read_identify, NULL }, + { "media", S_IFREG|S_IRUGO, proc_ide_read_media, NULL }, + { "model", S_IFREG|S_IRUGO, proc_ide_read_dmodel, NULL }, + { "settings", S_IFREG|S_IRUSR|S_IWUSR, proc_ide_read_settings, + proc_ide_write_settings }, { NULL, 0, NULL, NULL } }; @@ -737,7 +731,6 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver) spin_unlock_irqrestore(&ide_lock, flags); mutex_unlock(&ide_setting_mtx); } - EXPORT_SYMBOL(ide_proc_unregister_driver); void ide_proc_port_register_devices(ide_hwif_t *hwif) @@ -758,33 +751,22 @@ void ide_proc_port_register_devices(ide_hwif_t *hwif) drive->proc = proc_mkdir(drive->name, parent); if (drive->proc) ide_add_proc_entries(drive->proc, generic_drive_entries, drive); - sprintf(name,"ide%d/%s", (drive->name[2]-'a')/2, drive->name); + sprintf(name, "ide%d/%s", (drive->name[2]-'a')/2, drive->name); ent = proc_symlink(drive->name, proc_ide_root, name); if (!ent) return; } } -static void destroy_proc_ide_device(ide_hwif_t *hwif, ide_drive_t *drive) +void ide_proc_unregister_device(ide_drive_t *drive) { if (drive->proc) { ide_remove_proc_entries(drive->proc, generic_drive_entries); remove_proc_entry(drive->name, proc_ide_root); - remove_proc_entry(drive->name, hwif->proc); + remove_proc_entry(drive->name, drive->hwif->proc); drive->proc = NULL; } } -static void destroy_proc_ide_drives(ide_hwif_t *hwif) -{ - int d; - - for (d = 0; d < MAX_DRIVES; d++) { - ide_drive_t *drive = &hwif->drives[d]; - if (drive->proc) - destroy_proc_ide_device(hwif, drive); - } -} - static ide_proc_entry_t hwif_entries[] = { { "channel", S_IFREG|S_IRUGO, proc_ide_read_channel, NULL }, { "mate", S_IFREG|S_IRUGO, proc_ide_read_mate, NULL }, @@ -804,19 +786,9 @@ 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) { - destroy_proc_ide_drives(hwif); ide_remove_proc_entries(hwif->proc, hwif_entries); remove_proc_entry(hwif->name, proc_ide_root); hwif->proc = NULL; @@ -840,7 +812,7 @@ static int ide_drivers_show(struct seq_file *s, void *p) err = bus_for_each_drv(&ide_bus_type, NULL, s, proc_print_driver); if (err < 0) printk(KERN_WARNING "IDE: %s: bus_for_each_drv error: %d\n", - __FUNCTION__, err); + __func__, err); return 0; } diff --git a/drivers/ide/ide-scan-pci.c b/drivers/ide/ide-scan-pci.c index 93d2e41be853..0e79efff1deb 100644 --- a/drivers/ide/ide-scan-pci.c +++ b/drivers/ide/ide-scan-pci.c @@ -88,13 +88,8 @@ static int __init ide_scan_pcibus(void) struct list_head *l, *n; pre_init = 0; - if (!ide_scan_direction) - while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev))) - ide_scan_pcidev(dev); - else - while ((dev = pci_get_device_reverse(PCI_ANY_ID, PCI_ANY_ID, - dev))) - ide_scan_pcidev(dev); + while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev))) + ide_scan_pcidev(dev); /* * Hand the drivers over to the PCI layer now we @@ -107,7 +102,7 @@ static int __init ide_scan_pcibus(void) if (__pci_register_driver(d, d->driver.owner, d->driver.mod_name)) printk(KERN_ERR "%s: failed to register %s driver\n", - __FUNCTION__, d->driver.mod_name); + __func__, d->driver.mod_name); } return 0; diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 0598ecfd5f37..54a43b044608 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. @@ -181,56 +161,59 @@ struct idetape_bh { char *b_data; }; -typedef struct idetape_packet_command_s { - /* Actual packet bytes */ - u8 c[12]; - /* On each retry, we increment retries */ - int retries; - /* Error code */ - int error; - /* Bytes to transfer */ - int request_transfer; - /* Bytes actually transferred */ - int actually_transferred; - /* Size of our data buffer */ - int buffer_size; - struct idetape_bh *bh; - char *b_data; - int b_count; - /* Data buffer */ - u8 *buffer; - /* Pointer into the above buffer */ - u8 *current_position; - /* Called when this packet command is completed */ - ide_startstop_t (*callback) (ide_drive_t *); - /* Temporary buffer */ - u8 pc_buffer[IDETAPE_PC_BUFFER_SIZE]; - /* Status/Action bit flags: long for set_bit */ - unsigned long flags; -} idetape_pc_t; +/* Tape door status */ +#define DOOR_UNLOCKED 0 +#define DOOR_LOCKED 1 +#define DOOR_EXPLICITLY_LOCKED 2 + +/* Some defines for the SPACE command */ +#define IDETAPE_SPACE_OVER_FILEMARK 1 +#define IDETAPE_SPACE_TO_EOD 3 + +/* Some defines for the LOAD UNLOAD command */ +#define IDETAPE_LU_LOAD_MASK 1 +#define IDETAPE_LU_RETENSION_MASK 2 +#define IDETAPE_LU_EOT_MASK 4 /* - * Packet command flag bits. + * Special requests for our block device strategy routine. + * + * In order to service a character device command, we add special requests to + * the tail of our block device request queue and wait for their completion. */ -/* Set when an error is considered normal - We won't retry */ -#define PC_ABORT 0 -/* 1 When polling for DSC on a media access command */ -#define PC_WAIT_FOR_DSC 1 -/* 1 when we prefer to use DMA if possible */ -#define PC_DMA_RECOMMENDED 2 -/* 1 while DMA in progress */ -#define PC_DMA_IN_PROGRESS 3 -/* 1 when encountered problem during DMA */ -#define PC_DMA_ERROR 4 -/* Data direction */ -#define PC_WRITING 5 - -/* 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; + +enum { + REQ_IDETAPE_PC1 = (1 << 0), /* packet command (first stage) */ + REQ_IDETAPE_PC2 = (1 << 1), /* packet command (second stage) */ + REQ_IDETAPE_READ = (1 << 2), + REQ_IDETAPE_WRITE = (1 << 3), +}; + +/* Error codes returned in rq->errors to the higher part of the driver. */ +#define IDETAPE_ERROR_GENERAL 101 +#define IDETAPE_ERROR_FILEMARK 102 +#define IDETAPE_ERROR_EOD 103 + +/* Structures related to the SELECT SENSE / MODE SENSE packet commands. */ +#define IDETAPE_BLOCK_DESCRIPTOR 0 +#define IDETAPE_CAPABILITIES_PAGE 0x2a + +/* Tape flag bits values. */ +enum { + IDETAPE_FLAG_IGNORE_DSC = (1 << 0), + /* 0 When the tape position is unknown */ + IDETAPE_FLAG_ADDRESS_VALID = (1 << 1), + /* Device already opened */ + IDETAPE_FLAG_BUSY = (1 << 2), + /* Attempt to auto-detect the current user block size */ + IDETAPE_FLAG_DETECT_BS = (1 << 3), + /* Currently on a filemark */ + IDETAPE_FLAG_FILEMARK = (1 << 4), + /* DRQ interrupt device */ + IDETAPE_FLAG_DRQ_INTERRUPT = (1 << 5), + /* 0 = no tape is loaded, so we don't rewind after ejecting */ + IDETAPE_FLAG_MEDIUM_PRESENT = (1 << 6), +}; /* * Most of our global data which we need to save even as we leave the driver due @@ -258,11 +241,11 @@ typedef struct ide_tape_obj { * retry, to get detailed information on what went wrong. */ /* Current packet command */ - idetape_pc_t *pc; + struct ide_atapi_pc *pc; /* Last failed packet command */ - idetape_pc_t *failed_pc; + struct ide_atapi_pc *failed_pc; /* Packet command stack */ - idetape_pc_t pc_stack[IDETAPE_PC_STACK]; + struct ide_atapi_pc pc_stack[IDETAPE_PC_STACK]; /* Next free packet command storage space */ int pc_stack_index; struct request rq_stack[IDETAPE_PC_STACK]; @@ -275,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 */ @@ -317,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; @@ -374,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; @@ -446,58 +365,6 @@ static void ide_tape_put(struct ide_tape_obj *tape) mutex_unlock(&idetape_ref_mutex); } -/* Tape door status */ -#define DOOR_UNLOCKED 0 -#define DOOR_LOCKED 1 -#define DOOR_EXPLICITLY_LOCKED 2 - -/* - * Tape flag bits values. - */ -#define IDETAPE_IGNORE_DSC 0 -#define IDETAPE_ADDRESS_VALID 1 /* 0 When the tape position is unknown */ -#define IDETAPE_BUSY 2 /* Device already opened */ -#define IDETAPE_PIPELINE_ERROR 3 /* Error detected in a pipeline stage */ -#define IDETAPE_DETECT_BS 4 /* Attempt to auto-detect the current user block size */ -#define IDETAPE_FILEMARK 5 /* Currently on a filemark */ -#define IDETAPE_DRQ_INTERRUPT 6 /* DRQ interrupt device */ -#define IDETAPE_READ_ERROR 7 -#define IDETAPE_PIPELINE_ACTIVE 8 /* pipeline active */ -/* 0 = no tape is loaded, so we don't rewind after ejecting */ -#define IDETAPE_MEDIUM_PRESENT 9 - -/* Some defines for the SPACE command */ -#define IDETAPE_SPACE_OVER_FILEMARK 1 -#define IDETAPE_SPACE_TO_EOD 3 - -/* Some defines for the LOAD UNLOAD command */ -#define IDETAPE_LU_LOAD_MASK 1 -#define IDETAPE_LU_RETENSION_MASK 2 -#define IDETAPE_LU_EOT_MASK 4 - -/* - * Special requests for our block device strategy routine. - * - * In order to service a character device command, we add special requests to - * the tail of our block device request queue and wait for their completion. - */ - -enum { - REQ_IDETAPE_PC1 = (1 << 0), /* packet command (first stage) */ - REQ_IDETAPE_PC2 = (1 << 1), /* packet command (second stage) */ - REQ_IDETAPE_READ = (1 << 2), - REQ_IDETAPE_WRITE = (1 << 3), -}; - -/* Error codes returned in rq->errors to the higher part of the driver. */ -#define IDETAPE_ERROR_GENERAL 101 -#define IDETAPE_ERROR_FILEMARK 102 -#define IDETAPE_ERROR_EOD 103 - -/* Structures related to the SELECT SENSE / MODE SENSE packet commands. */ -#define IDETAPE_BLOCK_DESCRIPTOR 0 -#define IDETAPE_CAPABILITIES_PAGE 0x2a - /* * The variables below are used for the character device interface. Additional * state variables are defined in our ide_drive_t structure. @@ -518,17 +385,7 @@ static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i) return tape; } -/* - * Too bad. The drive wants to send us data which we are not ready to accept. - * Just throw it away. - */ -static void idetape_discard_data(ide_drive_t *drive, unsigned int bcount) -{ - while (bcount--) - (void) HWIF(drive)->INB(IDE_DATA_REG); -} - -static void idetape_input_buffers(ide_drive_t *drive, idetape_pc_t *pc, +static void idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, unsigned int bcount) { struct idetape_bh *bh = pc->bh; @@ -538,13 +395,13 @@ static void idetape_input_buffers(ide_drive_t *drive, idetape_pc_t *pc, if (bh == NULL) { printk(KERN_ERR "ide-tape: bh == NULL in " "idetape_input_buffers\n"); - idetape_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); @@ -557,7 +414,7 @@ static void idetape_input_buffers(ide_drive_t *drive, idetape_pc_t *pc, pc->bh = bh; } -static void idetape_output_buffers(ide_drive_t *drive, idetape_pc_t *pc, +static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, unsigned int bcount) { struct idetape_bh *bh = pc->bh; @@ -570,7 +427,7 @@ static void idetape_output_buffers(ide_drive_t *drive, idetape_pc_t *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; @@ -585,13 +442,13 @@ static void idetape_output_buffers(ide_drive_t *drive, idetape_pc_t *pc, } } -static void idetape_update_buffers(idetape_pc_t *pc) +static void idetape_update_buffers(struct ide_atapi_pc *pc) { struct idetape_bh *bh = pc->bh; int count; - unsigned int bcount = pc->actually_transferred; + unsigned int bcount = pc->xferred; - if (test_bit(PC_WRITING, &pc->flags)) + if (pc->flags & PC_FLAG_WRITING) return; while (bcount) { if (bh == NULL) { @@ -614,7 +471,7 @@ static void idetape_update_buffers(idetape_pc_t *pc) * driver. A storage space for a maximum of IDETAPE_PC_STACK packet * commands is allocated at initialization time. */ -static idetape_pc_t *idetape_next_pc_storage(ide_drive_t *drive) +static struct ide_atapi_pc *idetape_next_pc_storage(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; @@ -649,14 +506,14 @@ static struct request *idetape_next_rq_storage(ide_drive_t *drive) return (&tape->rq_stack[tape->rq_stack_index++]); } -static void idetape_init_pc(idetape_pc_t *pc) +static void idetape_init_pc(struct ide_atapi_pc *pc) { memset(pc->c, 0, 12); pc->retries = 0; pc->flags = 0; - pc->request_transfer = 0; - pc->buffer = pc->pc_buffer; - pc->buffer_size = IDETAPE_PC_BUFFER_SIZE; + pc->req_xfer = 0; + pc->buf = pc->pc_buf; + pc->buf_size = IDETAPE_PC_BUFFER_SIZE; pc->bh = NULL; pc->b_data = NULL; } @@ -668,7 +525,7 @@ static void idetape_init_pc(idetape_pc_t *pc) static void idetape_analyze_error(ide_drive_t *drive, u8 *sense) { idetape_tape_t *tape = drive->driver_data; - idetape_pc_t *pc = tape->failed_pc; + struct ide_atapi_pc *pc = tape->failed_pc; tape->sense_key = sense[2] & 0xF; tape->asc = sense[12]; @@ -677,9 +534,9 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense) debug_log(DBG_ERR, "pc = %x, sense key = %x, asc = %x, ascq = %x\n", pc->c[0], tape->sense_key, tape->asc, tape->ascq); - /* Correct pc->actually_transferred by asking the tape. */ - if (test_bit(PC_DMA_ERROR, &pc->flags)) { - pc->actually_transferred = pc->request_transfer - + /* Correct pc->xferred by asking the tape. */ + if (pc->flags & PC_FLAG_DMA_ERROR) { + pc->xferred = pc->req_xfer - tape->blk_size * be32_to_cpu(get_unaligned((u32 *)&sense[3])); idetape_update_buffers(pc); @@ -697,153 +554,61 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense) /* don't report an error, everything's ok */ pc->error = 0; /* don't retry read/write */ - set_bit(PC_ABORT, &pc->flags); + pc->flags |= PC_FLAG_ABORT; } } if (pc->c[0] == READ_6 && (sense[2] & 0x80)) { pc->error = IDETAPE_ERROR_FILEMARK; - set_bit(PC_ABORT, &pc->flags); + pc->flags |= PC_FLAG_ABORT; } if (pc->c[0] == WRITE_6) { if ((sense[2] & 0x40) || (tape->sense_key == 0xd && tape->asc == 0x0 && tape->ascq == 0x2)) { pc->error = IDETAPE_ERROR_EOD; - set_bit(PC_ABORT, &pc->flags); + pc->flags |= PC_FLAG_ABORT; } } if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) { if (tape->sense_key == 8) { pc->error = IDETAPE_ERROR_EOD; - set_bit(PC_ABORT, &pc->flags); + pc->flags |= PC_FLAG_ABORT; } - if (!test_bit(PC_ABORT, &pc->flags) && - pc->actually_transferred) + if (!(pc->flags & PC_FLAG_ABORT) && + pc->xferred) pc->retries = IDETAPE_MAX_PC_RETRIES + 1; } } -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"); - } -} - -/* - * 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; + kfree(tape->merge_bh); } -/* - * 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__); @@ -863,56 +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_PIPELINE_ERROR, &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_PIPELINE_ERROR, &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_PIPELINE_ACTIVE, &tape->flags); spin_unlock_irqrestore(&tape->lock, flags); return 0; } @@ -924,7 +641,7 @@ static ide_startstop_t idetape_request_sense_callback(ide_drive_t *drive) debug_log(DBG_PROCS, "Enter %s\n", __func__); if (!tape->pc->error) { - idetape_analyze_error(drive, tape->pc->buffer); + idetape_analyze_error(drive, tape->pc->buf); idetape_end_request(drive, 1, 0); } else { printk(KERN_ERR "ide-tape: Error in REQUEST SENSE itself - " @@ -934,13 +651,13 @@ static ide_startstop_t idetape_request_sense_callback(ide_drive_t *drive) return ide_stopped; } -static void idetape_create_request_sense_cmd(idetape_pc_t *pc) +static void idetape_create_request_sense_cmd(struct ide_atapi_pc *pc) { idetape_init_pc(pc); pc->c[0] = REQUEST_SENSE; pc->c[4] = 20; - pc->request_transfer = 20; - pc->callback = &idetape_request_sense_callback; + pc->req_xfer = 20; + pc->idetape_callback = &idetape_request_sense_callback; } static void idetape_init_rq(struct request *rq, u8 cmd) @@ -965,7 +682,7 @@ static void idetape_init_rq(struct request *rq, u8 cmd) * handling functions should queue request to the lower level part and wait for * their completion using idetape_queue_pc_tail or idetape_queue_rw_tail. */ -static void idetape_queue_pc_head(ide_drive_t *drive, idetape_pc_t *pc, +static void idetape_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc, struct request *rq) { struct ide_tape_obj *tape = drive->driver_data; @@ -984,14 +701,14 @@ static void idetape_queue_pc_head(ide_drive_t *drive, idetape_pc_t *pc, static ide_startstop_t idetape_retry_pc (ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; - idetape_pc_t *pc; + struct ide_atapi_pc *pc; struct request *rq; (void)ide_read_error(drive); pc = idetape_next_pc_storage(drive); rq = idetape_next_rq_storage(drive); idetape_create_request_sense_cmd(pc); - set_bit(IDETAPE_IGNORE_DSC, &tape->flags); + set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags); idetape_queue_pc_head(drive, pc, rq); return ide_stopped; } @@ -1010,7 +727,7 @@ static void idetape_postpone_request(ide_drive_t *drive) ide_stall_queue(drive, tape->dsc_poll_freq); } -typedef void idetape_io_buf(ide_drive_t *, idetape_pc_t *, unsigned int); +typedef void idetape_io_buf(ide_drive_t *, struct ide_atapi_pc *, unsigned int); /* * This is the usual interrupt handler which will be called during a packet @@ -1023,7 +740,7 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; idetape_tape_t *tape = drive->driver_data; - idetape_pc_t *pc = tape->pc; + struct ide_atapi_pc *pc = tape->pc; xfer_func_t *xferfunc; idetape_io_buf *iobuf; unsigned int temp; @@ -1038,8 +755,8 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive) /* Clear the interrupt */ stat = ide_read_status(drive); - if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { - if (hwif->ide_dma_end(drive) || (stat & ERR_STAT)) { + if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { + if (hwif->dma_ops->dma_end(drive) || (stat & ERR_STAT)) { /* * A DMA error is sometimes expected. For example, * if the tape is crossing a filemark during a @@ -1061,9 +778,9 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive) * data transfer will occur, but no DMA error. * (AS, 19 Apr 2001) */ - set_bit(PC_DMA_ERROR, &pc->flags); + pc->flags |= PC_FLAG_DMA_ERROR; } else { - pc->actually_transferred = pc->request_transfer; + pc->xferred = pc->req_xfer; idetape_update_buffers(pc); } debug_log(DBG_PROCS, "DMA finished\n"); @@ -1073,9 +790,9 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive) /* No more interrupts */ if ((stat & DRQ_STAT) == 0) { debug_log(DBG_SENSE, "Packet command completed, %d bytes" - " transferred\n", pc->actually_transferred); + " transferred\n", pc->xferred); - clear_bit(PC_DMA_IN_PROGRESS, &pc->flags); + pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; local_irq_enable(); #if SIMULATE_ERRORS @@ -1088,7 +805,7 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive) #endif if ((stat & ERR_STAT) && pc->c[0] == REQUEST_SENSE) stat &= ~ERR_STAT; - if ((stat & ERR_STAT) || test_bit(PC_DMA_ERROR, &pc->flags)) { + if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) { /* Error detected */ debug_log(DBG_ERR, "%s: I/O error\n", tape->name); @@ -1104,7 +821,7 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive) return idetape_retry_pc(drive); } pc->error = 0; - if (test_bit(PC_WAIT_FOR_DSC, &pc->flags) && + if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & SEEK_STAT) == 0) { /* Media access command */ tape->dsc_polling_start = jiffies; @@ -1117,9 +834,11 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive) if (tape->failed_pc == pc) tape->failed_pc = NULL; /* Command finished - Call the callback function */ - return pc->callback(drive); + return pc->idetape_callback(drive); } - if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { + + if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { + pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; printk(KERN_ERR "ide-tape: The tape wants to issue more " "interrupts in DMA mode\n"); printk(KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n"); @@ -1127,16 +846,16 @@ 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(IDE_BCOUNTH_REG) << 8) | - hwif->INB(IDE_BCOUNTL_REG); + bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) | + hwif->INB(hwif->io_ports.lbam_addr); - ireason = hwif->INB(IDE_IREASON_REG); + ireason = hwif->INB(hwif->io_ports.nsect_addr); if (ireason & CD) { printk(KERN_ERR "ide-tape: CoD != 0 in %s\n", __func__); return ide_do_reset(drive); } - if (((ireason & IO) == IO) == test_bit(PC_WRITING, &pc->flags)) { + if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) { /* Hopefully, we will never get here */ printk(KERN_ERR "ide-tape: We wanted to %s, ", (ireason & IO) ? "Write" : "Read"); @@ -1144,15 +863,15 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive) (ireason & IO) ? "Read" : "Write"); return ide_do_reset(drive); } - if (!test_bit(PC_WRITING, &pc->flags)) { + if (!(pc->flags & PC_FLAG_WRITING)) { /* Reading - Check that we have enough space */ - temp = pc->actually_transferred + bcount; - if (temp > pc->request_transfer) { - if (temp > pc->buffer_size) { + temp = pc->xferred + bcount; + if (temp > pc->req_xfer) { + if (temp > pc->buf_size) { printk(KERN_ERR "ide-tape: The tape wants to " "send us more data than expected " "- discarding data\n"); - idetape_discard_data(drive, bcount); + ide_pad_transfer(drive, 0, bcount); ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); return ide_started; @@ -1161,20 +880,20 @@ 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->current_position, bcount); + xferfunc(drive, NULL, pc->cur_pos, bcount); /* Update the current position */ - pc->actually_transferred += bcount; - pc->current_position += bcount; + pc->xferred += bcount; + pc->cur_pos += bcount; debug_log(DBG_SENSE, "[cmd %x] transferred %d bytes on that intr.\n", pc->c[0], bcount); @@ -1224,7 +943,7 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; idetape_tape_t *tape = drive->driver_data; - idetape_pc_t *pc = tape->pc; + struct ide_atapi_pc *pc = tape->pc; int retries = 100; ide_startstop_t startstop; u8 ireason; @@ -1234,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(IDE_IREASON_REG); + 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(IDE_IREASON_REG); + 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"); @@ -1256,15 +975,17 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive) ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); #ifdef CONFIG_BLK_DEV_IDEDMA /* Begin DMA, if necessary */ - if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) - hwif->dma_start(drive); + if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) + 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; } -static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, idetape_pc_t *pc) +static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, + struct ide_atapi_pc *pc) { ide_hwif_t *hwif = drive->hwif; idetape_tape_t *tape = drive->driver_data; @@ -1283,13 +1004,13 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, idetape_pc_t *pc) tape->pc = pc; if (pc->retries > IDETAPE_MAX_PC_RETRIES || - test_bit(PC_ABORT, &pc->flags)) { + (pc->flags & PC_FLAG_ABORT)) { /* * We will "abort" retrying a packet command in case legitimate * error code was received (crossing a filemark, or end of the * media, for example). */ - if (!test_bit(PC_ABORT, &pc->flags)) { + if (!(pc->flags & PC_FLAG_ABORT)) { if (!(pc->c[0] == TEST_UNIT_READY && tape->sense_key == 2 && tape->asc == 4 && (tape->ascq == 1 || tape->ascq == 8))) { @@ -1304,36 +1025,38 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, idetape_pc_t *pc) pc->error = IDETAPE_ERROR_GENERAL; } tape->failed_pc = NULL; - return pc->callback(drive); + return pc->idetape_callback(drive); } debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]); pc->retries++; /* We haven't transferred any data yet */ - pc->actually_transferred = 0; - pc->current_position = pc->buffer; + pc->xferred = 0; + pc->cur_pos = pc->buf; /* Request to transfer the entire buffer at once */ - bcount = pc->request_transfer; + bcount = pc->req_xfer; - if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) { + if (pc->flags & PC_FLAG_DMA_ERROR) { + pc->flags &= ~PC_FLAG_DMA_ERROR; printk(KERN_WARNING "ide-tape: DMA disabled, " "reverting to PIO\n"); ide_dma_off(drive); } - if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) - dma_ok = !hwif->dma_setup(drive); + if ((pc->flags & PC_FLAG_DMA_RECOMMENDED) && drive->using_dma) + dma_ok = !hwif->dma_ops->dma_setup(drive); ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK | IDE_TFLAG_OUT_DEVICE, bcount, dma_ok); - if (dma_ok) /* Will begin DMA later */ - set_bit(PC_DMA_IN_PROGRESS, &pc->flags); - if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) { + if (dma_ok) + /* Will begin DMA later */ + pc->flags |= PC_FLAG_DMA_IN_PROGRESS; + if (test_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags)) { ide_execute_command(drive, WIN_PACKETCMD, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL); return ide_started; } else { - hwif->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG); + ide_execute_pkt_cmd(drive); return idetape_transfer_pc(drive); } } @@ -1349,7 +1072,7 @@ static ide_startstop_t idetape_pc_callback(ide_drive_t *drive) } /* A mode sense command is used to "sense" tape parameters. */ -static void idetape_create_mode_sense_cmd(idetape_pc_t *pc, u8 page_code) +static void idetape_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code) { idetape_init_pc(pc); pc->c[0] = MODE_SENSE; @@ -1368,81 +1091,18 @@ static void idetape_create_mode_sense_cmd(idetape_pc_t *pc, u8 page_code) /* We will just discard data in that case */ pc->c[4] = 255; if (page_code == IDETAPE_BLOCK_DESCRIPTOR) - pc->request_transfer = 12; + pc->req_xfer = 12; else if (page_code == IDETAPE_CAPABILITIES_PAGE) - pc->request_transfer = 24; + pc->req_xfer = 24; else - pc->request_transfer = 50; - pc->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); + pc->req_xfer = 50; + pc->idetape_callback = &idetape_pc_callback; } static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; - idetape_pc_t *pc = tape->pc; + struct ide_atapi_pc *pc = tape->pc; u8 stat; stat = ide_read_status(drive); @@ -1463,27 +1123,17 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive) pc->error = IDETAPE_ERROR_GENERAL; tape->failed_pc = NULL; } - return pc->callback(drive); + return pc->idetape_callback(drive); } static ide_startstop_t idetape_rw_callback(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; struct request *rq = HWGROUP(drive)->rq; - int blocks = tape->pc->actually_transferred / tape->blk_size; + 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; @@ -1502,47 +1152,49 @@ static ide_startstop_t idetape_rw_callback(ide_drive_t *drive) return ide_stopped; } -static void idetape_create_read_cmd(idetape_tape_t *tape, idetape_pc_t *pc, +static void idetape_create_read_cmd(idetape_tape_t *tape, + struct ide_atapi_pc *pc, unsigned int length, struct idetape_bh *bh) { idetape_init_pc(pc); pc->c[0] = READ_6; put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]); pc->c[1] = 1; - pc->callback = &idetape_rw_callback; + pc->idetape_callback = &idetape_rw_callback; pc->bh = bh; atomic_set(&bh->b_count, 0); - pc->buffer = NULL; - pc->buffer_size = length * tape->blk_size; - pc->request_transfer = pc->buffer_size; - if (pc->request_transfer == tape->stage_size) - set_bit(PC_DMA_RECOMMENDED, &pc->flags); + pc->buf = NULL; + pc->buf_size = length * tape->blk_size; + pc->req_xfer = pc->buf_size; + if (pc->req_xfer == tape->buffer_size) + pc->flags |= PC_FLAG_DMA_RECOMMENDED; } -static void idetape_create_write_cmd(idetape_tape_t *tape, idetape_pc_t *pc, +static void idetape_create_write_cmd(idetape_tape_t *tape, + struct ide_atapi_pc *pc, unsigned int length, struct idetape_bh *bh) { idetape_init_pc(pc); pc->c[0] = WRITE_6; put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]); pc->c[1] = 1; - pc->callback = &idetape_rw_callback; - set_bit(PC_WRITING, &pc->flags); + pc->idetape_callback = &idetape_rw_callback; + pc->flags |= PC_FLAG_WRITING; pc->bh = bh; pc->b_data = bh->b_data; pc->b_count = atomic_read(&bh->b_count); - pc->buffer = NULL; - pc->buffer_size = length * tape->blk_size; - pc->request_transfer = pc->buffer_size; - if (pc->request_transfer == tape->stage_size) - set_bit(PC_DMA_RECOMMENDED, &pc->flags); + pc->buf = NULL; + pc->buf_size = length * tape->blk_size; + pc->req_xfer = pc->buf_size; + if (pc->req_xfer == tape->buffer_size) + pc->flags |= PC_FLAG_DMA_RECOMMENDED; } static ide_startstop_t idetape_do_request(ide_drive_t *drive, struct request *rq, sector_t block) { idetape_tape_t *tape = drive->driver_data; - idetape_pc_t *pc = NULL; + struct ide_atapi_pc *pc = NULL; struct request *postponed_rq = tape->postponed_rq; u8 stat; @@ -1579,18 +1231,14 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, stat = ide_read_status(drive); if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2)) - set_bit(IDETAPE_IGNORE_DSC, &tape->flags); + set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags); if (drive->post_reset == 1) { - set_bit(IDETAPE_IGNORE_DSC, &tape->flags); + set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags); 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_IGNORE_DSC, &tape->flags) && + if (!test_and_clear_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags) && (stat & SEEK_STAT) == 0) { if (postponed_rq == NULL) { tape->dsc_polling_start = jiffies; @@ -1613,23 +1261,19 @@ 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); goto out; } if (rq->cmd[0] & REQ_IDETAPE_PC1) { - pc = (idetape_pc_t *) rq->buffer; + pc = (struct ide_atapi_pc *) rq->buffer; rq->cmd[0] &= ~(REQ_IDETAPE_PC1); rq->cmd[0] |= REQ_IDETAPE_PC2; goto out; @@ -1643,111 +1287,91 @@ out: return idetape_issue_pc(drive, pc); } -/* Pipeline related functions */ -static inline int idetape_pipeline_active(idetape_tape_t *tape) -{ - int rc1, rc2; - - rc1 = test_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags); - rc2 = (tape->active_data_rq != NULL); - return rc1; -} - /* - * 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; @@ -1779,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; @@ -1810,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 { @@ -1823,65 +1447,10 @@ 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; - u8 *readpos = tape->pc->buffer; + u8 *readpos = tape->pc->buf; debug_log(DBG_PROCS, "Enter %s\n", __func__); @@ -1894,7 +1463,7 @@ static ide_startstop_t idetape_read_position_callback(ide_drive_t *drive) if (readpos[0] & 0x4) { printk(KERN_INFO "ide-tape: Block location is unknown" "to the tape\n"); - clear_bit(IDETAPE_ADDRESS_VALID, &tape->flags); + clear_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags); idetape_end_request(drive, 0, 0); } else { debug_log(DBG_SENSE, "Block Location - %u\n", @@ -1903,7 +1472,7 @@ static ide_startstop_t idetape_read_position_callback(ide_drive_t *drive) tape->partition = readpos[1]; tape->first_frame = be32_to_cpu(*(u32 *)&readpos[4]); - set_bit(IDETAPE_ADDRESS_VALID, &tape->flags); + set_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags); idetape_end_request(drive, 1, 0); } } else { @@ -1917,20 +1486,20 @@ static ide_startstop_t idetape_read_position_callback(ide_drive_t *drive) * writing a filemark otherwise. */ static void idetape_create_write_filemark_cmd(ide_drive_t *drive, - idetape_pc_t *pc, int write_filemark) + struct ide_atapi_pc *pc, int write_filemark) { idetape_init_pc(pc); pc->c[0] = WRITE_FILEMARKS; pc->c[4] = write_filemark; - set_bit(PC_WAIT_FOR_DSC, &pc->flags); - pc->callback = &idetape_pc_callback; + pc->flags |= PC_FLAG_WAIT_FOR_DSC; + pc->idetape_callback = &idetape_pc_callback; } -static void idetape_create_test_unit_ready_cmd(idetape_pc_t *pc) +static void idetape_create_test_unit_ready_cmd(struct ide_atapi_pc *pc) { idetape_init_pc(pc); pc->c[0] = TEST_UNIT_READY; - pc->callback = &idetape_pc_callback; + pc->idetape_callback = &idetape_pc_callback; } /* @@ -1946,7 +1515,7 @@ static void idetape_create_test_unit_ready_cmd(idetape_pc_t *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, idetape_pc_t *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; @@ -1957,28 +1526,28 @@ static int __idetape_queue_pc_tail(ide_drive_t *drive, idetape_pc_t *pc) return ide_do_drive_cmd(drive, &rq, ide_wait); } -static void idetape_create_load_unload_cmd(ide_drive_t *drive, idetape_pc_t *pc, - int cmd) +static void idetape_create_load_unload_cmd(ide_drive_t *drive, + struct ide_atapi_pc *pc, int cmd) { idetape_init_pc(pc); pc->c[0] = START_STOP; pc->c[4] = cmd; - set_bit(PC_WAIT_FOR_DSC, &pc->flags); - pc->callback = &idetape_pc_callback; + pc->flags |= PC_FLAG_WAIT_FOR_DSC; + pc->idetape_callback = &idetape_pc_callback; } static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout) { idetape_tape_t *tape = drive->driver_data; - idetape_pc_t pc; + struct ide_atapi_pc pc; int load_attempted = 0; /* Wait for the tape to become ready */ - set_bit(IDETAPE_MEDIUM_PRESENT, &tape->flags); + set_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags); 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)) { @@ -1987,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 && @@ -1998,14 +1567,9 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout) return -EIO; } -static int idetape_queue_pc_tail(ide_drive_t *drive, idetape_pc_t *pc) -{ - return __idetape_queue_pc_tail(drive, pc); -} - static int idetape_flush_tape_buffers(ide_drive_t *drive) { - idetape_pc_t pc; + struct ide_atapi_pc pc; int rc; idetape_create_write_filemark_cmd(drive, &pc, 0); @@ -2016,18 +1580,18 @@ static int idetape_flush_tape_buffers(ide_drive_t *drive) return 0; } -static void idetape_create_read_position_cmd(idetape_pc_t *pc) +static void idetape_create_read_position_cmd(struct ide_atapi_pc *pc) { idetape_init_pc(pc); pc->c[0] = READ_POSITION; - pc->request_transfer = 20; - pc->callback = &idetape_read_position_callback; + pc->req_xfer = 20; + pc->idetape_callback = &idetape_read_position_callback; } static int idetape_read_position(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; - idetape_pc_t pc; + struct ide_atapi_pc pc; int position; debug_log(DBG_PROCS, "Enter %s\n", __func__); @@ -2039,7 +1603,8 @@ static int idetape_read_position(ide_drive_t *drive) return position; } -static void idetape_create_locate_cmd(ide_drive_t *drive, idetape_pc_t *pc, +static void idetape_create_locate_cmd(ide_drive_t *drive, + struct ide_atapi_pc *pc, unsigned int block, u8 partition, int skip) { idetape_init_pc(pc); @@ -2047,12 +1612,12 @@ static void idetape_create_locate_cmd(ide_drive_t *drive, idetape_pc_t *pc, pc->c[1] = 2; put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[3]); pc->c[8] = partition; - set_bit(PC_WAIT_FOR_DSC, &pc->flags); - pc->callback = &idetape_pc_callback; + pc->flags |= PC_FLAG_WAIT_FOR_DSC; + pc->idetape_callback = &idetape_pc_callback; } -static int idetape_create_prevent_cmd(ide_drive_t *drive, idetape_pc_t *pc, - int prevent) +static int idetape_create_prevent_cmd(ide_drive_t *drive, + struct ide_atapi_pc *pc, int prevent) { idetape_tape_t *tape = drive->driver_data; @@ -2063,54 +1628,25 @@ static int idetape_create_prevent_cmd(ide_drive_t *drive, idetape_pc_t *pc, idetape_init_pc(pc); pc->c[0] = ALLOW_MEDIUM_REMOVAL; pc->c[4] = prevent; - pc->callback = &idetape_pc_callback; + pc->idetape_callback = &idetape_pc_callback; 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_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_PIPELINE_ERROR, &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 (idetape_pipeline_active(tape)) - 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; } /* @@ -2124,10 +1660,10 @@ static int idetape_position_tape(ide_drive_t *drive, unsigned int block, { idetape_tape_t *tape = drive->driver_data; int retval; - idetape_pc_t pc; + 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); @@ -2138,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; } } @@ -2169,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 (idetape_pipeline_active(tape)) { - 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; @@ -2186,192 +1715,83 @@ 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 (!idetape_pipeline_active(tape)) { - set_bit(IDETAPE_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(idetape_pc_t *pc) +static void idetape_create_inquiry_cmd(struct ide_atapi_pc *pc) { idetape_init_pc(pc); pc->c[0] = INQUIRY; pc->c[4] = 254; - pc->request_transfer = 254; - pc->callback = &idetape_pc_callback; + pc->req_xfer = 254; + pc->idetape_callback = &idetape_pc_callback; } -static void idetape_create_rewind_cmd(ide_drive_t *drive, idetape_pc_t *pc) +static void idetape_create_rewind_cmd(ide_drive_t *drive, + struct ide_atapi_pc *pc) { idetape_init_pc(pc); pc->c[0] = REZERO_UNIT; - set_bit(PC_WAIT_FOR_DSC, &pc->flags); - pc->callback = &idetape_pc_callback; + pc->flags |= PC_FLAG_WAIT_FOR_DSC; + pc->idetape_callback = &idetape_pc_callback; } -static void idetape_create_erase_cmd(idetape_pc_t *pc) +static void idetape_create_erase_cmd(struct ide_atapi_pc *pc) { idetape_init_pc(pc); pc->c[0] = ERASE; pc->c[1] = 1; - set_bit(PC_WAIT_FOR_DSC, &pc->flags); - pc->callback = &idetape_pc_callback; + pc->flags |= PC_FLAG_WAIT_FOR_DSC; + pc->idetape_callback = &idetape_pc_callback; } -static void idetape_create_space_cmd(idetape_pc_t *pc, int count, u8 cmd) +static void idetape_create_space_cmd(struct ide_atapi_pc *pc, int count, u8 cmd) { idetape_init_pc(pc); pc->c[0] = SPACE; put_unaligned(cpu_to_be32(count), (unsigned int *) &pc->c[1]); pc->c[1] = cmd; - set_bit(PC_WAIT_FOR_DSC, &pc->flags); - pc->callback = &idetape_pc_callback; + pc->flags |= PC_FLAG_WAIT_FOR_DSC; + 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 (idetape_pipeline_active(tape)) { - 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 (idetape_pipeline_active(tape)) - 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 (!idetape_pipeline_active(tape)) { - 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_PIPELINE_ERROR, &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 || idetape_pipeline_active(tape)) { - idetape_plug_pipeline(drive); - spin_lock_irqsave(&tape->lock, flags); - if (idetape_pipeline_active(tape)) - 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) { @@ -2395,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_PIPELINE_ERROR, &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; @@ -2475,94 +1854,34 @@ 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_PIPELINE_ERROR, &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 (!idetape_pipeline_active(tape)) { - 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); /* If we are at a filemark, return a read length of 0 */ - if (test_bit(IDETAPE_FILEMARK, &tape->flags)) + 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_PIPELINE_ERROR, &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_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) @@ -2574,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) { @@ -2586,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; } /* @@ -2618,7 +1916,7 @@ static int idetape_pipeline_size(ide_drive_t *drive) static int idetape_rewind_tape(ide_drive_t *drive) { int retval; - idetape_pc_t pc; + struct ide_atapi_pc pc; idetape_tape_t *tape; tape = drive->driver_data; @@ -2656,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; @@ -2670,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; - idetape_pc_t pc; - unsigned long flags; + struct ide_atapi_pc pc; int retval, count = 0; int sprev = !!(tape->caps[4] & 0x20); @@ -2695,47 +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; - if (test_and_clear_bit(IDETAPE_FILEMARK, &tape->flags)) + 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_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: @@ -2786,32 +2040,30 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf, debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count); if (tape->chrdev_dir != IDETAPE_DIR_READ) { - if (test_bit(IDETAPE_DETECT_BS, &tape->flags)) + if (test_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags)) if (count > tape->blk_size && (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; @@ -2822,14 +2074,13 @@ 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_FILEMARK, &tape->flags)) { + if (!actually_read && test_bit(IDETAPE_FLAG_FILEMARK, &tape->flags)) { debug_log(DBG_SENSE, "%s: spacing over filemark\n", tape->name); idetape_space_over_filemarks(drive, MTFSF, 1); @@ -2857,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 @@ -2878,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; } @@ -2889,56 +2140,51 @@ 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; } static int idetape_write_filemark(ide_drive_t *drive) { - idetape_pc_t pc; + struct ide_atapi_pc pc; /* Write a filemark */ idetape_create_write_filemark_cmd(drive, &pc, 1); @@ -2955,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: * @@ -2966,13 +2211,12 @@ static int idetape_write_filemark(ide_drive_t *drive) static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) { idetape_tape_t *tape = drive->driver_data; - idetape_pc_t pc; + struct ide_atapi_pc pc; int i, retval; 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: @@ -2989,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) @@ -2997,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); @@ -3017,18 +2261,18 @@ 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); if (!retval) - clear_bit(IDETAPE_MEDIUM_PRESENT, &tape->flags); + 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); @@ -3045,16 +2289,16 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) mt_count % tape->blk_size) return -EIO; tape->user_bs_factor = mt_count / tape->blk_size; - clear_bit(IDETAPE_DETECT_BS, &tape->flags); + clear_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags); } else - set_bit(IDETAPE_DETECT_BS, &tape->flags); + 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: @@ -3099,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) @@ -3137,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); } } @@ -3149,7 +2392,7 @@ static int idetape_chrdev_ioctl(struct inode *inode, struct file *file, static void ide_tape_get_bsize_from_bdesc(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; - idetape_pc_t pc; + struct ide_atapi_pc pc; idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR); if (idetape_queue_pc_tail(drive, &pc)) { @@ -3161,10 +2404,10 @@ static void ide_tape_get_bsize_from_bdesc(ide_drive_t *drive) } return; } - tape->blk_size = (pc.buffer[4 + 5] << 16) + - (pc.buffer[4 + 6] << 8) + - pc.buffer[4 + 7]; - tape->drv_write_prot = (pc.buffer[2] & 0x80) >> 7; + tape->blk_size = (pc.buf[4 + 5] << 16) + + (pc.buf[4 + 6] << 8) + + pc.buf[4 + 7]; + tape->drv_write_prot = (pc.buf[2] & 0x80) >> 7; } static int idetape_chrdev_open(struct inode *inode, struct file *filp) @@ -3172,7 +2415,7 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp) unsigned int minor = iminor(inode), i = minor & ~0xc0; ide_drive_t *drive; idetape_tape_t *tape; - idetape_pc_t pc; + struct ide_atapi_pc pc; int retval; if (i >= MAX_HWIFS * MAX_DRIVES) @@ -3195,25 +2438,22 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp) filp->private_data = tape; - if (test_and_set_bit(IDETAPE_BUSY, &tape->flags)) { + if (test_and_set_bit(IDETAPE_FLAG_BUSY, &tape->flags)) { retval = -EBUSY; goto out_put_tape; } retval = idetape_wait_ready(drive, 60 * HZ); if (retval) { - clear_bit(IDETAPE_BUSY, &tape->flags); + clear_bit(IDETAPE_FLAG_BUSY, &tape->flags); printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name); goto out_put_tape; } idetape_read_position(drive); - if (!test_bit(IDETAPE_ADDRESS_VALID, &tape->flags)) + if (!test_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags)) (void)idetape_rewind_tape(drive); - if (tape->chrdev_dir != IDETAPE_DIR_READ) - clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); - /* Read block size and write protect status from drive. */ ide_tape_get_bsize_from_bdesc(drive); @@ -3227,7 +2467,7 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp) if (tape->write_prot) { if ((filp->f_flags & O_ACCMODE) == O_WRONLY || (filp->f_flags & O_ACCMODE) == O_RDWR) { - clear_bit(IDETAPE_BUSY, &tape->flags); + clear_bit(IDETAPE_FLAG_BUSY, &tape->flags); retval = -EROFS; goto out_put_tape; } @@ -3242,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: @@ -3255,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); @@ -3272,7 +2510,7 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp) { struct ide_tape_obj *tape = ide_tape_f(filp); ide_drive_t *drive = tape->drive; - idetape_pc_t pc; + struct ide_atapi_pc pc; unsigned int minor = iminor(inode); lock_kernel(); @@ -3284,15 +2522,10 @@ 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_MEDIUM_PRESENT, &tape->flags)) + + if (minor < 128 && test_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags)) (void) idetape_rewind_tape(drive); if (tape->chrdev_dir == IDETAPE_DIR_NONE) { if (tape->door_locked == DOOR_LOCKED) { @@ -3302,7 +2535,7 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp) } } } - clear_bit(IDETAPE_BUSY, &tape->flags); + clear_bit(IDETAPE_FLAG_BUSY, &tape->flags); ide_tape_put(tape); unlock_kernel(); return 0; @@ -3350,7 +2583,7 @@ static int idetape_identify_device(ide_drive_t *drive) static void idetape_get_inquiry_results(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; - idetape_pc_t pc; + struct ide_atapi_pc pc; char fw_rev[6], vendor_id[10], product_id[18]; idetape_create_inquiry_cmd(&pc); @@ -3359,9 +2592,9 @@ static void idetape_get_inquiry_results(ide_drive_t *drive) tape->name); return; } - memcpy(vendor_id, &pc.buffer[8], 8); - memcpy(product_id, &pc.buffer[16], 16); - memcpy(fw_rev, &pc.buffer[32], 4); + memcpy(vendor_id, &pc.buf[8], 8); + memcpy(product_id, &pc.buf[16], 16); + memcpy(fw_rev, &pc.buf[32], 4); ide_fixstring(vendor_id, 10, 0); ide_fixstring(product_id, 18, 0); @@ -3378,7 +2611,7 @@ static void idetape_get_inquiry_results(ide_drive_t *drive) static void idetape_get_mode_sense_results(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; - idetape_pc_t pc; + struct ide_atapi_pc pc; u8 *caps; u8 speed, max_speed; @@ -3392,7 +2625,7 @@ static void idetape_get_mode_sense_results(ide_drive_t *drive) put_unaligned(6*52, (u16 *)&tape->caps[16]); return; } - caps = pc.buffer + 4 + pc.buffer[3]; + caps = pc.buf + 4 + pc.buf[3]; /* convert to host order and save for later use */ speed = be16_to_cpu(*(u16 *)&caps[14]); @@ -3428,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, @@ -3477,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); @@ -3500,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_DRQ_INTERRUPT, &tape->flags); - - tape->min_pipeline = 10; - tape->max_pipeline = 10; - tape->max_stages = 10; + set_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags); 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 @@ -3568,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":""); @@ -3596,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 4c86a8d84b4c..9a846a0cd5a4 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -33,58 +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, IDE_DATA_REG); - - if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) - hwif->OUTB(tf->hob_feature, IDE_FEATURE_REG); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) - hwif->OUTB(tf->hob_nsect, IDE_NSECTOR_REG); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) - hwif->OUTB(tf->hob_lbal, IDE_SECTOR_REG); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) - hwif->OUTB(tf->hob_lbam, IDE_LCYL_REG); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) - hwif->OUTB(tf->hob_lbah, IDE_HCYL_REG); - - if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) - hwif->OUTB(tf->feature, IDE_FEATURE_REG); - if (task->tf_flags & IDE_TFLAG_OUT_NSECT) - hwif->OUTB(tf->nsect, IDE_NSECTOR_REG); - if (task->tf_flags & IDE_TFLAG_OUT_LBAL) - hwif->OUTB(tf->lbal, IDE_SECTOR_REG); - if (task->tf_flags & IDE_TFLAG_OUT_LBAM) - hwif->OUTB(tf->lbam, IDE_LCYL_REG); - if (task->tf_flags & IDE_TFLAG_OUT_LBAH) - hwif->OUTB(tf->lbah, IDE_HCYL_REG); - - if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) - hwif->OUTB((tf->device & HIHI) | drive->select.all, IDE_SELECT_REG); } int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf) @@ -133,6 +93,7 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) ide_hwif_t *hwif = HWIF(drive); struct ide_taskfile *tf = &task->tf; ide_handler_t *handler = NULL; + const struct ide_dma_ops *dma_ops = hwif->dma_ops; if (task->data_phase == TASKFILE_MULTI_IN || task->data_phase == TASKFILE_MULTI_OUT) { @@ -146,13 +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, IDE_COMMAND_REG); + 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: @@ -175,10 +138,10 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) return ide_started; default: if (task_dma_ok(task) == 0 || drive->using_dma == 0 || - hwif->dma_setup(drive)) + dma_ops->dma_setup(drive)) return ide_stopped; - hwif->dma_exec_cmd(drive, tf->command); - hwif->dma_start(drive); + dma_ops->dma_exec_cmd(drive, tf->command); + dma_ops->dma_start(drive); return ide_started; } } @@ -280,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; @@ -320,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 @@ -330,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, @@ -359,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; } @@ -452,7 +417,7 @@ static ide_startstop_t task_in_intr(ide_drive_t *drive) /* Error? */ if (stat & ERR_STAT) - return task_error(drive, rq, __FUNCTION__, stat); + return task_error(drive, rq, __func__, stat); /* Didn't want any data? Odd. */ if (!(stat & DRQ_STAT)) @@ -464,7 +429,7 @@ static ide_startstop_t task_in_intr(ide_drive_t *drive) if (!hwif->nleft) { stat = wait_drive_not_busy(drive); if (!OK_STAT(stat, 0, BAD_STAT)) - return task_error(drive, rq, __FUNCTION__, stat); + return task_error(drive, rq, __func__, stat); task_end_request(drive, rq, stat); return ide_stopped; } @@ -485,11 +450,11 @@ static ide_startstop_t task_out_intr (ide_drive_t *drive) u8 stat = ide_read_status(drive); if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat)) - return task_error(drive, rq, __FUNCTION__, stat); + return task_error(drive, rq, __func__, stat); /* Deal with unexpected ATA data phase. */ if (((stat & DRQ_STAT) == 0) ^ !hwif->nleft) - return task_error(drive, rq, __FUNCTION__, stat); + return task_error(drive, rq, __func__, stat); if (!hwif->nleft) { task_end_request(drive, rq, stat); @@ -672,7 +637,7 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) /* (hs): give up if multcount is not set */ printk(KERN_ERR "%s: %s Multimode Write " \ "multcount is not set\n", - drive->name, __FUNCTION__); + drive->name, __func__); err = -EPERM; goto abort; } @@ -689,7 +654,7 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) /* (hs): give up if multcount is not set */ printk(KERN_ERR "%s: %s Multimode Read failure " \ "multcount is not set\n", - drive->name, __FUNCTION__); + drive->name, __func__); err = -EPERM; goto abort; } diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index fc69fe2e3ec0..999584c03d97 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -78,6 +78,8 @@ /* default maximum number of failures */ #define IDE_DEFAULT_MAX_FAILURES 1 +struct class *ide_port_class; + static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE5_MAJOR, @@ -90,32 +92,17 @@ static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */ DEFINE_MUTEX(ide_cfg_mtx); __cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock); -#ifdef CONFIG_IDEPCI_PCIBUS_ORDER -int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */ -#endif - int noautodma = 0; -#ifdef CONFIG_BLK_DEV_IDEACPI -int ide_noacpi = 0; -int ide_noacpitfs = 1; -int ide_noacpionboot = 1; -#endif - -/* - * This is declared extern in ide.h, for access by other IDE modules: - */ ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */ -EXPORT_SYMBOL(ide_hwifs); +static void ide_port_init_devices_data(ide_hwif_t *); /* * Do not even *think* about calling this! */ void ide_init_port_data(ide_hwif_t *hwif, unsigned int index) { - unsigned int unit; - /* bulk initialize hwif & drive info with zeros */ memset(hwif, 0, sizeof(ide_hwif_t)); @@ -134,8 +121,20 @@ void ide_init_port_data(ide_hwif_t *hwif, unsigned int index) default_hwif_iops(hwif); default_hwif_transport(hwif); + + ide_port_init_devices_data(hwif); +} +EXPORT_SYMBOL_GPL(ide_init_port_data); + +static void ide_port_init_devices_data(ide_hwif_t *hwif) +{ + int unit; + for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; + u8 j = (hwif->index * MAX_DRIVES) + unit; + + memset(drive, 0, sizeof(*drive)); drive->media = ide_disk; drive->select.all = (unit<<4)|0xa0; @@ -147,32 +146,13 @@ void ide_init_port_data(ide_hwif_t *hwif, unsigned int index) drive->special.b.set_geometry = 1; drive->name[0] = 'h'; drive->name[1] = 'd'; - drive->name[2] = 'a' + (index * MAX_DRIVES) + unit; + drive->name[2] = 'a' + j; drive->max_failures = IDE_DEFAULT_MAX_FAILURES; - drive->using_dma = 0; - drive->vdma = 0; + INIT_LIST_HEAD(&drive->list); init_completion(&drive->gendev_rel_comp); } } -EXPORT_SYMBOL_GPL(ide_init_port_data); - -static void init_hwif_default(ide_hwif_t *hwif, unsigned int index) -{ - hw_regs_t hw; - - memset(&hw, 0, sizeof(hw_regs_t)); - - ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &hwif->irq); - - memcpy(hwif->io_ports, hw.io_ports, sizeof(hw.io_ports)); - - hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; -#ifdef CONFIG_BLK_DEV_HD - if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) - hwif->noprobe = 1; /* may be overridden by ide_setup() */ -#endif -} /* * init_ide_data() sets reasonable default values into all fields @@ -194,7 +174,6 @@ static void init_hwif_default(ide_hwif_t *hwif, unsigned int index) #define MAGIC_COOKIE 0x12345678 static void __init init_ide_data (void) { - ide_hwif_t *hwif; unsigned int index; static unsigned long magic_cookie = MAGIC_COOKIE; @@ -204,13 +183,9 @@ static void __init init_ide_data (void) /* Initialise all interface structures */ for (index = 0; index < MAX_HWIFS; ++index) { - hwif = &ide_hwifs[index]; + ide_hwif_t *hwif = &ide_hwifs[index]; + ide_init_port_data(hwif, index); - init_hwif_default(hwif, index); -#if !defined(CONFIG_PPC32) || !defined(CONFIG_PCI) - hwif->irq = - ide_init_default_irq(hwif->io_ports[IDE_DATA_OFFSET]); -#endif } } @@ -246,219 +221,6 @@ static int ide_system_bus_speed(void) return pci_dev_present(pci_default) ? 33 : 50; } -ide_hwif_t * ide_find_port(unsigned long base) -{ - ide_hwif_t *hwif; - int i; - - for (i = 0; i < MAX_HWIFS; i++) { - hwif = &ide_hwifs[i]; - if (hwif->io_ports[IDE_DATA_OFFSET] == base) - goto found; - } - - for (i = 0; i < MAX_HWIFS; i++) { - hwif = &ide_hwifs[i]; - if (hwif->io_ports[IDE_DATA_OFFSET] == 0) - goto found; - } - - hwif = NULL; -found: - return hwif; -} - -EXPORT_SYMBOL_GPL(ide_find_port); - -static struct resource* hwif_request_region(ide_hwif_t *hwif, - unsigned long addr, int num) -{ - struct resource *res = request_region(addr, num, hwif->name); - - if (!res) - printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", - hwif->name, addr, addr+num-1); - return res; -} - -/** - * ide_hwif_request_regions - request resources for IDE - * @hwif: interface to use - * - * Requests all the needed resources for an interface. - * Right now core IDE code does this work which is deeply wrong. - * MMIO leaves it to the controller driver, - * PIO will migrate this way over time. - */ - -int ide_hwif_request_regions(ide_hwif_t *hwif) -{ - unsigned long addr; - unsigned int i; - - if (hwif->mmio) - return 0; - addr = hwif->io_ports[IDE_CONTROL_OFFSET]; - if (addr && !hwif_request_region(hwif, addr, 1)) - goto control_region_busy; - hwif->straight8 = 0; - addr = hwif->io_ports[IDE_DATA_OFFSET]; - if ((addr | 7) == hwif->io_ports[IDE_STATUS_OFFSET]) { - if (!hwif_request_region(hwif, addr, 8)) - goto data_region_busy; - hwif->straight8 = 1; - return 0; - } - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - addr = hwif->io_ports[i]; - if (!hwif_request_region(hwif, addr, 1)) { - while (--i) - release_region(addr, 1); - goto data_region_busy; - } - } - return 0; - -data_region_busy: - addr = hwif->io_ports[IDE_CONTROL_OFFSET]; - if (addr) - release_region(addr, 1); -control_region_busy: - /* If any errors are return, we drop the hwif interface. */ - return -EBUSY; -} - -/** - * ide_hwif_release_regions - free IDE resources - * - * Note that we only release the standard ports, - * and do not even try to handle any extra ports - * allocated for weird IDE interface chipsets. - * - * Note also that we don't yet handle mmio resources here. More - * importantly our caller should be doing this so we need to - * restructure this as a helper function for drivers. - */ - -void ide_hwif_release_regions(ide_hwif_t *hwif) -{ - u32 i = 0; - - if (hwif->mmio) - return; - if (hwif->io_ports[IDE_CONTROL_OFFSET]) - release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1); - if (hwif->straight8) { - release_region(hwif->io_ports[IDE_DATA_OFFSET], 8); - return; - } - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) - if (hwif->io_ports[i]) - release_region(hwif->io_ports[i], 1); -} - -/** - * ide_hwif_restore - restore hwif to template - * @hwif: hwif to update - * @tmp_hwif: template - * - * Restore hwif to a previous state by copying most settings - * from the template. - */ - -static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) -{ - hwif->hwgroup = tmp_hwif->hwgroup; - - hwif->gendev.parent = tmp_hwif->gendev.parent; - - hwif->proc = tmp_hwif->proc; - - hwif->major = tmp_hwif->major; - hwif->straight8 = tmp_hwif->straight8; - hwif->bus_state = tmp_hwif->bus_state; - - hwif->host_flags = tmp_hwif->host_flags; - - hwif->pio_mask = tmp_hwif->pio_mask; - - hwif->ultra_mask = tmp_hwif->ultra_mask; - hwif->mwdma_mask = tmp_hwif->mwdma_mask; - hwif->swdma_mask = tmp_hwif->swdma_mask; - - hwif->cbl = tmp_hwif->cbl; - - hwif->chipset = tmp_hwif->chipset; - hwif->hold = tmp_hwif->hold; - - hwif->dev = tmp_hwif->dev; - -#ifdef CONFIG_BLK_DEV_IDEPCI - hwif->cds = tmp_hwif->cds; -#endif - - hwif->set_pio_mode = tmp_hwif->set_pio_mode; - hwif->set_dma_mode = tmp_hwif->set_dma_mode; - hwif->mdma_filter = tmp_hwif->mdma_filter; - hwif->udma_filter = tmp_hwif->udma_filter; - hwif->selectproc = tmp_hwif->selectproc; - hwif->reset_poll = tmp_hwif->reset_poll; - hwif->pre_reset = tmp_hwif->pre_reset; - hwif->resetproc = tmp_hwif->resetproc; - hwif->maskproc = tmp_hwif->maskproc; - hwif->quirkproc = tmp_hwif->quirkproc; - hwif->busproc = tmp_hwif->busproc; - - hwif->ata_input_data = tmp_hwif->ata_input_data; - hwif->ata_output_data = tmp_hwif->ata_output_data; - hwif->atapi_input_bytes = tmp_hwif->atapi_input_bytes; - hwif->atapi_output_bytes = tmp_hwif->atapi_output_bytes; - - hwif->dma_host_set = tmp_hwif->dma_host_set; - hwif->dma_setup = tmp_hwif->dma_setup; - hwif->dma_exec_cmd = tmp_hwif->dma_exec_cmd; - hwif->dma_start = tmp_hwif->dma_start; - hwif->ide_dma_end = tmp_hwif->ide_dma_end; - hwif->ide_dma_test_irq = tmp_hwif->ide_dma_test_irq; - hwif->ide_dma_clear_irq = tmp_hwif->ide_dma_clear_irq; - hwif->dma_lost_irq = tmp_hwif->dma_lost_irq; - hwif->dma_timeout = tmp_hwif->dma_timeout; - - hwif->OUTB = tmp_hwif->OUTB; - hwif->OUTBSYNC = tmp_hwif->OUTBSYNC; - hwif->OUTW = tmp_hwif->OUTW; - hwif->OUTSW = tmp_hwif->OUTSW; - hwif->OUTSL = tmp_hwif->OUTSL; - - hwif->INB = tmp_hwif->INB; - hwif->INW = tmp_hwif->INW; - hwif->INSW = tmp_hwif->INSW; - hwif->INSL = tmp_hwif->INSL; - - hwif->sg_max_nents = tmp_hwif->sg_max_nents; - - hwif->mmio = tmp_hwif->mmio; - hwif->rqsize = tmp_hwif->rqsize; - -#ifndef CONFIG_BLK_DEV_IDECS - hwif->irq = tmp_hwif->irq; -#endif - - hwif->dma_base = tmp_hwif->dma_base; - hwif->dma_command = tmp_hwif->dma_command; - hwif->dma_vendor1 = tmp_hwif->dma_vendor1; - hwif->dma_status = tmp_hwif->dma_status; - hwif->dma_vendor3 = tmp_hwif->dma_vendor3; - hwif->dma_prdtable = tmp_hwif->dma_prdtable; - - hwif->config_data = tmp_hwif->config_data; - hwif->select_data = tmp_hwif->select_data; - hwif->extra_base = tmp_hwif->extra_base; - hwif->extra_ports = tmp_hwif->extra_ports; - - hwif->hwif_data = tmp_hwif->hwif_data; -} - void ide_remove_port_from_hwgroup(ide_hwif_t *hwif) { ide_hwgroup_t *hwgroup = hwif->hwgroup; @@ -494,11 +256,38 @@ void ide_remove_port_from_hwgroup(ide_hwif_t *hwif) spin_unlock_irq(&ide_lock); } +/* Called with ide_lock held. */ +static void __ide_port_unregister_devices(ide_hwif_t *hwif) +{ + int i; + + for (i = 0; i < MAX_DRIVES; i++) { + ide_drive_t *drive = &hwif->drives[i]; + + if (drive->present) { + spin_unlock_irq(&ide_lock); + device_unregister(&drive->gendev); + wait_for_completion(&drive->gendev_rel_comp); + spin_lock_irq(&ide_lock); + } + } +} + +void ide_port_unregister_devices(ide_hwif_t *hwif) +{ + mutex_lock(&ide_cfg_mtx); + spin_lock_irq(&ide_lock); + __ide_port_unregister_devices(hwif); + hwif->present = 0; + ide_port_init_devices_data(hwif); + spin_unlock_irq(&ide_lock); + mutex_unlock(&ide_cfg_mtx); +} +EXPORT_SYMBOL_GPL(ide_port_unregister_devices); + /** * ide_unregister - free an IDE interface - * @index: index of interface (will change soon to a pointer) - * @init_default: init default hwif flag - * @restore: restore hwif flag + * @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. @@ -518,32 +307,19 @@ void ide_remove_port_from_hwgroup(ide_hwif_t *hwif) * This is raving bonkers. */ -void ide_unregister(unsigned int index, int init_default, int restore) +void ide_unregister(ide_hwif_t *hwif) { - ide_drive_t *drive; - ide_hwif_t *hwif, *g; - static ide_hwif_t tmp_hwif; /* protected by ide_cfg_mtx */ + ide_hwif_t *g; ide_hwgroup_t *hwgroup; - int irq_count = 0, unit; - - BUG_ON(index >= MAX_HWIFS); + int irq_count = 0; 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; - for (unit = 0; unit < MAX_DRIVES; ++unit) { - drive = &hwif->drives[unit]; - if (!drive->present) - continue; - spin_unlock_irq(&ide_lock); - device_unregister(&drive->gendev); - wait_for_completion(&drive->gendev_rel_comp); - spin_lock_irq(&ide_lock); - } + __ide_port_unregister_devices(hwif); hwif->present = 0; spin_unlock_irq(&ide_lock); @@ -565,6 +341,7 @@ void ide_unregister(unsigned int index, int init_default, int restore) ide_remove_port_from_hwgroup(hwif); + device_unregister(hwif->portdev); device_unregister(&hwif->gendev); wait_for_completion(&hwif->gendev_rel_comp); @@ -576,33 +353,11 @@ void ide_unregister(unsigned int index, int init_default, int restore) unregister_blkdev(hwif->major, hwif->name); spin_lock_irq(&ide_lock); - if (hwif->dma_base) { - (void) ide_release_dma(hwif); - - hwif->dma_base = 0; - hwif->dma_command = 0; - hwif->dma_vendor1 = 0; - hwif->dma_status = 0; - hwif->dma_vendor3 = 0; - hwif->dma_prdtable = 0; - - hwif->extra_base = 0; - hwif->extra_ports = 0; - } - - ide_hwif_release_regions(hwif); - - /* copy original settings */ - tmp_hwif = *hwif; + if (hwif->dma_base) + ide_release_dma_engine(hwif); /* restore hwif data to pristine status */ - ide_init_port_data(hwif, index); - - if (init_default) - init_hwif_default(hwif, index); - - if (restore) - ide_hwif_restore(hwif, &tmp_hwif); + ide_init_port_data(hwif, hwif->index); abort: spin_unlock_irq(&ide_lock); @@ -613,88 +368,14 @@ 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->noprobe = 0; hwif->chipset = hw->chipset; hwif->gendev.parent = hw->dev; hwif->ack_intr = hw->ack_intr; } EXPORT_SYMBOL_GPL(ide_init_port_hw); -ide_hwif_t *ide_deprecated_find_port(unsigned long base) -{ - ide_hwif_t *hwif; - int i; - - for (i = 0; i < MAX_HWIFS; i++) { - hwif = &ide_hwifs[i]; - if (hwif->io_ports[IDE_DATA_OFFSET] == base) - goto found; - } - - for (i = 0; i < MAX_HWIFS; i++) { - hwif = &ide_hwifs[i]; - if (hwif->hold) - continue; - if (!hwif->present && hwif->mate == NULL) - goto found; - } - - hwif = NULL; -found: - return hwif; -} -EXPORT_SYMBOL_GPL(ide_deprecated_find_port); - -/** - * ide_register_hw - register IDE interface - * @hw: hardware registers - * @quirkproc: quirkproc function - * @hwifp: pointer to returned hwif - * - * Register an IDE interface, specifying exactly the registers etc. - * - * Returns -1 on error. - */ - -int ide_register_hw(hw_regs_t *hw, void (*quirkproc)(ide_drive_t *), - ide_hwif_t **hwifp) -{ - int index, retry = 1; - ide_hwif_t *hwif; - u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; - - do { - hwif = ide_deprecated_find_port(hw->io_ports[IDE_DATA_OFFSET]); - if (hwif) - goto found; - for (index = 0; index < MAX_HWIFS; index++) - ide_unregister(index, 1, 1); - } while (retry--); - return -1; -found: - index = hwif->index; - if (hwif->present) - ide_unregister(index, 0, 1); - else if (!hwif->hold) - ide_init_port_data(hwif, index); - - ide_init_port_hw(hwif, hw); - hwif->quirkproc = quirkproc; - - idx[0] = index; - - ide_device_add(idx, NULL); - - if (hwifp) - *hwifp = hwif; - - return hwif->present ? index : -1; -} - -EXPORT_SYMBOL(ide_register_hw); - /* * Locks for IDE setting functionality */ @@ -779,7 +460,7 @@ int set_using_dma(ide_drive_t *drive, int arg) if (!drive->id || !(drive->id->capability & 1)) goto out; - if (hwif->dma_host_set == NULL) + if (hwif->dma_ops == NULL) goto out; err = -EBUSY; @@ -818,11 +499,14 @@ out: int set_pio_mode(ide_drive_t *drive, int arg) { struct request rq; + ide_hwif_t *hwif = drive->hwif; + const struct ide_port_ops *port_ops = hwif->port_ops; if (arg < 0 || arg > 255) return -EINVAL; - if (drive->hwif->set_pio_mode == NULL) + if (port_ops == NULL || port_ops->set_pio_mode == NULL || + (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) return -ENOSYS; if (drive->special.b.set_tune) @@ -997,27 +681,6 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device if (!capable(CAP_SYS_RAWIO)) return -EACCES; return ide_task_ioctl(drive, cmd, arg); - - case HDIO_SCAN_HWIF: - { - hw_regs_t hw; - int args[3]; - if (!capable(CAP_SYS_RAWIO)) return -EACCES; - if (copy_from_user(args, p, 3 * sizeof(int))) - return -EFAULT; - memset(&hw, 0, sizeof(hw)); - ide_init_hwif_ports(&hw, (unsigned long) args[0], - (unsigned long) args[1], NULL); - hw.irq = args[2]; - if (ide_register_hw(&hw, NULL, NULL) == -1) - return -EIO; - return 0; - } - case HDIO_UNREGISTER_HWIF: - if (!capable(CAP_SYS_RAWIO)) return -EACCES; - /* (arg > MAX_HWIFS) checked in function */ - ide_unregister(arg, 1, 1); - return 0; case HDIO_SET_NICE: if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1)))) @@ -1071,8 +734,6 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device case HDIO_SET_BUSSTATE: if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (HWIF(drive)->busproc) - return HWIF(drive)->busproc(drive, (int)arg); return -EOPNOTSUPP; default: return -EINVAL; @@ -1167,15 +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; - -static int __initdata is_chipset_set[MAX_HWIFS]; - /* * ide_setup() gets called VERY EARLY during initialization, * to handle kernel "command line" strings beginning with "hdx=" or "ide". @@ -1184,14 +836,12 @@ static int __initdata is_chipset_set[MAX_HWIFS]; */ 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 */ @@ -1207,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 */ @@ -1217,29 +867,21 @@ static int __init ide_setup(char *s) goto obsolete_option; } -#ifdef CONFIG_IDEPCI_PCIBUS_ORDER - if (!strcmp(s, "ide=reverse")) { - ide_scan_direction = 1; - printk(" : Enabled support for IDE inverse scan order.\n"); - goto obsolete_option; - } -#endif - #ifdef CONFIG_BLK_DEV_IDEACPI 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 */ @@ -1249,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; @@ -1264,30 +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; - hwif->noprobe = 0; - goto done; + goto obsolete_option; case -4: /* "cdrom" */ drive->present = 1; drive->media = ide_cdrom; /* an ATAPI device ignores DRDY */ drive->ready_stat = 0; - hwif->noprobe = 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; @@ -1305,8 +939,7 @@ static int __init ide_setup(char *s) drive->sect = drive->bios_sect = vals[2]; drive->present = 1; drive->forced_geom = 1; - hwif->noprobe = 0; - goto done; + goto obsolete_option; default: goto bad_option; } @@ -1324,155 +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[] = { - "noprobe", "serialize", "minus3", "minus4", - "reset", "minus6", "ata66", "minus8", "minus9", - "minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb", - "dtc2278", "umc8672", "ali14xx", NULL }; - - hw_regs_t hwregs; - - 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) || (i > 0 && i <= 3)) { - /* chipset already specified */ - if (is_chipset_set[hw]) - goto bad_option; - if (i > -18 && i <= -11) { - /* these drivers are for "ide0=" only */ - if (hw != 0) - goto bad_hwif; - /* chipset already specified for 2nd port */ - if (is_chipset_set[hw+1]) - goto bad_option; - } - is_chipset_set[hw] = 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 */ - { - ide_hwif_t *mate = &ide_hwifs[hw^1]; - mate->drives[0].select.all ^= 0x20; - mate->drives[1].select.all ^= 0x20; - hwif->chipset = mate->chipset = ide_4drives; - mate->irq = hwif->irq; - memcpy(mate->io_ports, hwif->io_ports, sizeof(hwif->io_ports)); - hwif->mate = mate; - mate->mate = hwif; - hwif->serialized = mate->serialized = 1; - goto obsolete_option; - } -#endif /* CONFIG_BLK_DEV_4DRIVES */ - 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: /* "noprobe" */ - hwif->noprobe = 1; - goto obsolete_option; - - case 1: /* base */ - vals[1] = vals[0] + 0x206; /* default ctl */ - case 2: /* base,ctl */ - vals[2] = 0; /* default irq = probe for it */ - case 3: /* base,ctl,irq */ - memset(&hwregs, 0, sizeof(hwregs)); - ide_init_hwif_ports(&hwregs, vals[0], vals[1], &hwif->irq); - memcpy(hwif->io_ports, hwregs.io_ports, sizeof(hwif->io_ports)); - hwif->irq = vals[2]; - hwif->noprobe = 0; - hwif->chipset = ide_forced; - goto obsolete_option; - case 0: 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); @@ -1601,6 +1094,192 @@ struct bus_type ide_bus_type = { EXPORT_SYMBOL_GPL(ide_bus_type); +static void ide_port_class_release(struct device *portdev) +{ + ide_hwif_t *hwif = dev_get_drvdata(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 */ @@ -1621,11 +1300,23 @@ static int __init ide_init(void) return ret; } + ide_port_class = class_create(THIS_MODULE, "ide_port"); + if (IS_ERR(ide_port_class)) { + ret = PTR_ERR(ide_port_class); + goto out_port_class; + } + ide_port_class->dev_release = ide_port_class_release; + init_ide_data(); proc_ide_create(); return 0; + +out_port_class: + bus_unregister(&ide_bus_type); + + return ret; } #ifdef MODULE @@ -1655,13 +1346,10 @@ int __init init_module (void) void __exit cleanup_module (void) { - int index; - - for (index = 0; index < MAX_HWIFS; ++index) - ide_unregister(index, 0, 0); - proc_ide_destroy(); + class_destroy(ide_port_class); + bus_unregister(&ide_bus_type); } diff --git a/drivers/ide/legacy/Makefile b/drivers/ide/legacy/Makefile index 7043ec7d1e05..6939329f89e8 100644 --- a/drivers/ide/legacy/Makefile +++ b/drivers/ide/legacy/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o obj-$(CONFIG_BLK_DEV_DTC2278) += dtc2278.o obj-$(CONFIG_BLK_DEV_HT6560B) += ht6560b.o obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o +obj-$(CONFIG_BLK_DEV_4DRIVES) += ide-4drives.o obj-$(CONFIG_BLK_DEV_GAYLE) += gayle.o obj-$(CONFIG_BLK_DEV_FALCON_IDE) += falconide.o diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c index d4d1a6bea599..90c65cf97448 100644 --- a/drivers/ide/legacy/ali14xx.c +++ b/drivers/ide/legacy/ali14xx.c @@ -49,6 +49,8 @@ #include <asm/io.h> +#define DRV_NAME "ali14xx" + /* port addresses for auto-detection */ #define ALI_NUM_PORTS 4 static const int ports[ALI_NUM_PORTS] __initdata = @@ -86,7 +88,7 @@ static u8 regOff; /* output to base port to close registers */ /* * Read a controller register. */ -static inline u8 inReg (u8 reg) +static inline u8 inReg(u8 reg) { outb_p(reg, regPort); return inb(dataPort); @@ -95,7 +97,7 @@ static inline u8 inReg (u8 reg) /* * Write a controller register. */ -static void outReg (u8 data, u8 reg) +static void outReg(u8 data, u8 reg) { outb_p(reg, regPort); outb_p(data, dataPort); @@ -114,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); @@ -143,7 +145,7 @@ static void ali14xx_set_pio_mode(ide_drive_t *drive, const u8 pio) /* * Auto-detect the IDE controller port. */ -static int __init findPort (void) +static int __init findPort(void) { int i; u8 t; @@ -175,7 +177,8 @@ static int __init findPort (void) /* * Initialize controller registers with default values. */ -static int __init initRegisters (void) { +static int __init initRegisters(void) +{ const RegInitializer *p; u8 t; unsigned long flags; @@ -191,16 +194,20 @@ static int __init initRegisters (void) { return t; } +static const struct ide_port_ops ali14xx_port_ops = { + .set_pio_mode = ali14xx_set_pio_mode, +}; + static const struct ide_port_info ali14xx_port_info = { + .name = DRV_NAME, .chipset = ide_ali14xx, - .host_flags = IDE_HFLAG_NO_DMA | IDE_HFLAG_NO_AUTOTUNE, + .port_ops = &ali14xx_port_ops, + .host_flags = IDE_HFLAG_NO_DMA, .pio_mask = ATA_PIO4, }; static int __init ali14xx_probe(void) { - static u8 idx[4] = { 0, 1, 0xff, 0xff }; - printk(KERN_DEBUG "ali14xx: base=0x%03x, regOn=0x%02x.\n", basePort, regOn); @@ -210,15 +217,10 @@ static int __init ali14xx_probe(void) return 1; } - ide_hwifs[0].set_pio_mode = &ali14xx_set_pio_mode; - ide_hwifs[1].set_pio_mode = &ali14xx_set_pio_mode; - - ide_device_add(idx, &ali14xx_port_info); - - return 0; + return ide_legacy_device_add(&ali14xx_port_info, 0); } -int probe_ali14xx = 0; +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 fdd3791e465f..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; @@ -221,15 +221,13 @@ fail_base2: buddha_setup_ports(&hw, base, ctl, irq_port, ack_intr); - hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]); + hwif = ide_find_port(); if (hwif) { u8 index = hwif->index; ide_init_port_data(hwif, index); ide_init_port_hw(hwif, &hw); - hwif->mmio = 1; - idx[i] = index; } } diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c index 73396f70f2b7..af791a02a120 100644 --- a/drivers/ide/legacy/dtc2278.c +++ b/drivers/ide/legacy/dtc2278.c @@ -16,6 +16,8 @@ #include <asm/io.h> +#define DRV_NAME "dtc2278" + /* * Changing this #undef to #define may solve start up problems in some systems. */ @@ -86,29 +88,26 @@ static void dtc2278_set_pio_mode(ide_drive_t *drive, const u8 pio) } } +static const struct ide_port_ops dtc2278_port_ops = { + .set_pio_mode = dtc2278_set_pio_mode, +}; + static const struct ide_port_info dtc2278_port_info __initdata = { + .name = DRV_NAME, .chipset = ide_dtc2278, + .port_ops = &dtc2278_port_ops, .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_UNMASK_IRQS | 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, }; static int __init dtc2278_probe(void) { unsigned long flags; - ide_hwif_t *hwif, *mate; - static u8 idx[4] = { 0, 1, 0xff, 0xff }; - - hwif = &ide_hwifs[0]; - mate = &ide_hwifs[1]; - - if (hwif->chipset != ide_unknown || mate->chipset != ide_unknown) - return 1; local_irq_save(flags); /* @@ -128,14 +127,10 @@ static int __init dtc2278_probe(void) #endif local_irq_restore(flags); - hwif->set_pio_mode = &dtc2278_set_pio_mode; - - ide_device_add(idx, &dtc2278_port_info); - - return 0; + 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 e950afa5939c..83555ca513b5 100644 --- a/drivers/ide/legacy/falconide.c +++ b/drivers/ide/legacy/falconide.c @@ -22,6 +22,7 @@ #include <asm/atariints.h> #include <asm/atari_stdma.h> +#define DRV_NAME "falconide" /* * Base of the IDE interface @@ -43,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; @@ -74,9 +97,14 @@ static int __init falconide_init(void) printk(KERN_INFO "ide: Falcon IDE controller\n"); + if (!request_mem_region(ATA_HD_BASE, 0x40, DRV_NAME)) { + printk(KERN_ERR "%s: resources busy\n", DRV_NAME); + return -EBUSY; + } + falconide_setup_ports(&hw); - hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]); + hwif = ide_find_port(); if (hwif) { u8 index = hwif->index; u8 idx[4] = { index, 0xff, 0xff, 0xff }; @@ -84,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 e3b4638cc883..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; @@ -175,15 +177,13 @@ found: gayle_setup_ports(&hw, base, ctrlport, irqport, ack_intr); - hwif = ide_find_port(base); + hwif = ide_find_port(); if (hwif) { u8 index = hwif->index; ide_init_port_data(hwif, index); ide_init_port_hw(hwif, &hw); - hwif->mmio = 1; - idx[i] = index; } else release_mem_region(res_start, res_n); diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c index 0b0d86731927..abdedf56643e 100644 --- a/drivers/ide/legacy/hd.c +++ b/drivers/ide/legacy/hd.c @@ -122,12 +122,12 @@ static int hd_error; * This struct defines the HD's and their types. */ struct hd_i_struct { - unsigned int head,sect,cyl,wpcom,lzone,ctl; + unsigned int head, sect, cyl, wpcom, lzone, ctl; int unit; int recalibrate; int special_op; }; - + #ifdef HD_TYPE static struct hd_i_struct hd_info[] = { HD_TYPE }; static int NR_HD = ARRAY_SIZE(hd_info); @@ -168,7 +168,7 @@ unsigned long read_timer(void) spin_lock_irqsave(&i8253_lock, flags); t = jiffies * 11932; - outb_p(0, 0x43); + outb_p(0, 0x43); i = inb_p(0x40); i |= inb(0x40) << 8; spin_unlock_irqrestore(&i8253_lock, flags); @@ -183,7 +183,7 @@ static void __init hd_setup(char *str, int *ints) if (ints[0] != 3) return; if (hd_info[0].head != 0) - hdind=1; + hdind = 1; hd_info[hdind].head = ints[2]; hd_info[hdind].sect = ints[3]; hd_info[hdind].cyl = ints[1]; @@ -193,7 +193,7 @@ static void __init hd_setup(char *str, int *ints) NR_HD = hdind+1; } -static void dump_status (const char *msg, unsigned int stat) +static void dump_status(const char *msg, unsigned int stat) { char *name = "hd?"; if (CURRENT) @@ -291,7 +291,6 @@ static int controller_ready(unsigned int drive, unsigned int head) return 0; } - static void hd_out(struct hd_i_struct *disk, unsigned int nsect, unsigned int sect, @@ -313,15 +312,15 @@ static void hd_out(struct hd_i_struct *disk, return; } SET_HANDLER(intr_addr); - outb_p(disk->ctl,HD_CMD); - port=HD_DATA; - outb_p(disk->wpcom>>2,++port); - outb_p(nsect,++port); - outb_p(sect,++port); - outb_p(cyl,++port); - outb_p(cyl>>8,++port); - outb_p(0xA0|(disk->unit<<4)|head,++port); - outb_p(cmd,++port); + outb_p(disk->ctl, HD_CMD); + port = HD_DATA; + outb_p(disk->wpcom >> 2, ++port); + outb_p(nsect, ++port); + outb_p(sect, ++port); + outb_p(cyl, ++port); + outb_p(cyl >> 8, ++port); + outb_p(0xA0 | (disk->unit << 4) | head, ++port); + outb_p(cmd, ++port); } static void hd_request (void); @@ -344,14 +343,14 @@ static void reset_controller(void) { int i; - outb_p(4,HD_CMD); - for(i = 0; i < 1000; i++) barrier(); - outb_p(hd_info[0].ctl & 0x0f,HD_CMD); - for(i = 0; i < 1000; i++) barrier(); + outb_p(4, HD_CMD); + for (i = 0; i < 1000; i++) barrier(); + outb_p(hd_info[0].ctl & 0x0f, HD_CMD); + for (i = 0; i < 1000; i++) barrier(); if (drive_busy()) printk("hd: controller still busy\n"); else if ((hd_error = inb(HD_ERROR)) != 1) - printk("hd: controller reset failed: %02x\n",hd_error); + printk("hd: controller reset failed: %02x\n", hd_error); } static void reset_hd(void) @@ -371,8 +370,8 @@ repeat: if (++i < NR_HD) { struct hd_i_struct *disk = &hd_info[i]; disk->special_op = disk->recalibrate = 1; - hd_out(disk,disk->sect,disk->sect,disk->head-1, - disk->cyl,WIN_SPECIFY,&reset_hd); + hd_out(disk, disk->sect, disk->sect, disk->head-1, + disk->cyl, WIN_SPECIFY, &reset_hd); if (reset) goto repeat; } else @@ -393,7 +392,7 @@ static void unexpected_hd_interrupt(void) unsigned int stat = inb_p(HD_STATUS); if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) { - dump_status ("unexpected interrupt", stat); + dump_status("unexpected interrupt", stat); SET_TIMER; } } @@ -453,7 +452,7 @@ static void read_intr(void) return; ok_to_read: req = CURRENT; - insw(HD_DATA,req->buffer,256); + insw(HD_DATA, req->buffer, 256); req->sector++; req->buffer += 512; req->errors = 0; @@ -507,7 +506,7 @@ ok_to_write: end_request(req, 1); if (i > 0) { SET_HANDLER(&write_intr); - outsw(HD_DATA,req->buffer,256); + outsw(HD_DATA, req->buffer, 256); local_irq_enable(); } else { #if (HD_DELAY > 0) @@ -560,11 +559,11 @@ static int do_special_op(struct hd_i_struct *disk, struct request *req) { if (disk->recalibrate) { disk->recalibrate = 0; - hd_out(disk,disk->sect,0,0,0,WIN_RESTORE,&recal_intr); + hd_out(disk, disk->sect, 0, 0, 0, WIN_RESTORE, &recal_intr); return reset; } if (disk->head > 16) { - printk ("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name); + printk("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name); end_request(req, 0); } disk->special_op = 0; @@ -633,19 +632,21 @@ repeat: if (blk_fs_request(req)) { switch (rq_data_dir(req)) { case READ: - hd_out(disk,nsect,sec,head,cyl,WIN_READ,&read_intr); + hd_out(disk, nsect, sec, head, cyl, WIN_READ, + &read_intr); if (reset) goto repeat; break; case WRITE: - hd_out(disk,nsect,sec,head,cyl,WIN_WRITE,&write_intr); + hd_out(disk, nsect, sec, head, cyl, WIN_WRITE, + &write_intr); if (reset) goto repeat; if (wait_DRQ()) { bad_rw_intr(); goto repeat; } - outsw(HD_DATA,req->buffer,256); + outsw(HD_DATA, req->buffer, 256); break; default: printk("unknown hd-command\n"); @@ -655,7 +656,7 @@ repeat: } } -static void do_hd_request (struct request_queue * q) +static void do_hd_request(struct request_queue *q) { disable_irq(HD_IRQ); hd_request(); @@ -708,12 +709,12 @@ static int __init hd_init(void) { int drive; - if (register_blkdev(MAJOR_NR,"hd")) + if (register_blkdev(MAJOR_NR, "hd")) return -1; hd_queue = blk_init_queue(do_hd_request, &hd_lock); if (!hd_queue) { - unregister_blkdev(MAJOR_NR,"hd"); + unregister_blkdev(MAJOR_NR, "hd"); return -ENOMEM; } @@ -742,7 +743,7 @@ static int __init hd_init(void) goto out; } - for (drive=0 ; drive < NR_HD ; drive++) { + for (drive = 0 ; drive < NR_HD ; drive++) { struct gendisk *disk = alloc_disk(64); struct hd_i_struct *p = &hd_info[drive]; if (!disk) @@ -756,7 +757,7 @@ static int __init hd_init(void) disk->queue = hd_queue; p->unit = drive; hd_gendisk[drive] = disk; - printk ("%s: %luMB, CHS=%d/%d/%d\n", + printk("%s: %luMB, CHS=%d/%d/%d\n", disk->disk_name, (unsigned long)get_capacity(disk)/2048, p->cyl, p->head, p->sect); } @@ -776,7 +777,7 @@ static int __init hd_init(void) } /* Let them fly */ - for(drive=0; drive < NR_HD; drive++) + for (drive = 0; drive < NR_HD; drive++) add_disk(hd_gendisk[drive]); return 0; @@ -791,7 +792,7 @@ out1: NR_HD = 0; out: del_timer(&device_timer); - unregister_blkdev(MAJOR_NR,"hd"); + unregister_blkdev(MAJOR_NR, "hd"); blk_cleanup_queue(hd_queue); return -1; Enomem: @@ -800,7 +801,8 @@ Enomem: goto out; } -static int __init parse_hd_setup (char *line) { +static int __init parse_hd_setup(char *line) +{ int ints[6]; (void) get_options(line, ARRAY_SIZE(ints), ints); diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c index 78ca68e60f97..4fe516df9f74 100644 --- a/drivers/ide/legacy/ht6560b.c +++ b/drivers/ide/legacy/ht6560b.c @@ -35,6 +35,7 @@ * Try: http://www.maf.iki.fi/~maf/ht6560b/ */ +#define DRV_NAME "ht6560b" #define HT6560B_VERSION "v0.08" #include <linux/module.h> @@ -82,7 +83,7 @@ * out how they setup those cycle time interfacing values, as they at Holtek * call them. IDESETUP.COM that is supplied with the drivers figures out * optimal values and fetches those values to drivers. I found out that - * they use IDE_SELECT_REG to fetch timings to the ide board right after + * they use Select register to fetch timings to the ide board right after * interface switching. After that it was quite easy to add code to * ht6560b.c. * @@ -127,6 +128,7 @@ */ static void ht6560b_selectproc (ide_drive_t *drive) { + ide_hwif_t *hwif = drive->hwif; unsigned long flags; static u8 current_select = 0; static u8 current_timing = 0; @@ -155,8 +157,8 @@ static void ht6560b_selectproc (ide_drive_t *drive) /* * Set timing for this drive: */ - outb(timing, IDE_SELECT_REG); - (void)inb(IDE_STATUS_REG); + 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); @@ -193,9 +195,9 @@ static int __init try_to_init_ht6560b(void) * Ht6560b autodetected */ outb(HT_CONFIG_DEFAULT, HT_CONFIG_PORT); - outb(HT_TIMING_DEFAULT, 0x1f6); /* IDE_SELECT_REG */ - (void) inb(0x1f7); /* IDE_STATUS_REG */ - + outb(HT_TIMING_DEFAULT, 0x1f6); /* Select register */ + (void)inb(0x1f7); /* Status register */ + printk("ht6560b " HT6560B_VERSION ": chipset detected and initialized" #ifdef DEBUG @@ -210,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; @@ -321,54 +323,44 @@ 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"); +static const struct ide_port_ops ht6560b_port_ops = { + .port_init_devs = ht6560b_port_init_devs, + .set_pio_mode = ht6560b_set_pio_mode, + .selectproc = ht6560b_selectproc, +}; + static const struct ide_port_info ht6560b_port_info __initdata = { + .name = DRV_NAME, .chipset = ide_ht6560b, + .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, }; static int __init ht6560b_init(void) { - ide_hwif_t *hwif, *mate; - static u8 idx[4] = { 0, 1, 0xff, 0xff }; - if (probe_ht6560b == 0) return -ENODEV; - hwif = &ide_hwifs[0]; - mate = &ide_hwifs[1]; - - if (!request_region(HT_CONFIG_PORT, 1, hwif->name)) { + if (!request_region(HT_CONFIG_PORT, 1, DRV_NAME)) { printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n", - __FUNCTION__); + __func__); return -ENODEV; } if (!try_to_init_ht6560b()) { - printk(KERN_NOTICE "%s: HBA not found\n", __FUNCTION__); + printk(KERN_NOTICE "%s: HBA not found\n", __func__); goto release_region; } - hwif->selectproc = &ht6560b_selectproc; - hwif->set_pio_mode = &ht6560b_set_pio_mode; - - mate->selectproc = &ht6560b_selectproc; - mate->set_pio_mode = &ht6560b_set_pio_mode; - - hwif->port_init_devs = ht6560b_port_init_devs; - mate->port_init_devs = ht6560b_port_init_devs; - - ide_device_add(idx, &ht6560b_port_info); - - return 0; + return ide_legacy_device_add(&ht6560b_port_info, 0); release_region: release_region(HT_CONFIG_PORT, 1); diff --git a/drivers/ide/legacy/ide-4drives.c b/drivers/ide/legacy/ide-4drives.c new file mode 100644 index 000000000000..ecae916a3385 --- /dev/null +++ b/drivers/ide/legacy/ide-4drives.c @@ -0,0 +1,72 @@ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/ide.h> + +#define DRV_NAME "ide-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"); + +static int __init ide_4drives_init(void) +{ + ide_hwif_t *hwif, *mate; + unsigned long base = 0x1f0, ctl = 0x3f6; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; + hw_regs_t hw; + + if (probe_4drives == 0) + return -ENODEV; + + if (!request_region(base, 8, DRV_NAME)) { + printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", + DRV_NAME, base, base + 7); + return -EBUSY; + } + + if (!request_region(ctl, 1, DRV_NAME)) { + printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n", + DRV_NAME, ctl); + release_region(base, 8); + return -EBUSY; + } + + memset(&hw, 0, sizeof(hw)); + + ide_std_init_ports(&hw, base, ctl); + hw.irq = 14; + hw.chipset = ide_4drives; + + hwif = ide_find_port(); + if (hwif) { + ide_init_port_hw(hwif, &hw); + idx[0] = hwif->index; + } + + mate = ide_find_port(); + if (mate) { + ide_init_port_hw(mate, &hw); + mate->drives[0].select.all ^= 0x20; + mate->drives[1].select.all ^= 0x20; + idx[1] = mate->index; + + if (hwif) { + hwif->mate = mate; + mate->mate = hwif; + hwif->serialized = mate->serialized = 1; + } + } + + ide_device_add(idx, NULL); + + return 0; +} + +module_init(ide_4drives_init); + +MODULE_AUTHOR("Bartlomiej Zolnierkiewicz"); +MODULE_DESCRIPTION("generic IDE chipset with 4 drives/port support"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 15ccf6944ae2..aa2ea3deac85 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -51,6 +51,8 @@ #include <pcmcia/cisreg.h> #include <pcmcia/ciscode.h> +#define DRV_NAME "ide-cs" + /*====================================================================*/ /* Module parameters */ @@ -72,16 +74,11 @@ static char *version = /*====================================================================*/ -static const char ide_major[] = { - IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, - IDE4_MAJOR, IDE5_MAJOR -}; - typedef struct ide_info_t { struct pcmcia_device *p_dev; + ide_hwif_t *hwif; int ndev; dev_node_t node; - int hd; } ide_info_t; static void ide_release(struct pcmcia_device *); @@ -136,45 +133,71 @@ static int ide_probe(struct pcmcia_device *link) static void ide_detach(struct pcmcia_device *link) { + ide_info_t *info = link->priv; + ide_hwif_t *hwif = info->hwif; + DEBUG(0, "ide_detach(0x%p)\n", link); ide_release(link); - kfree(link->priv); + release_region(hwif->io_ports.ctl_addr, 1); + release_region(hwif->io_ports.data_addr, 8); + + kfree(info); } /* ide_detach */ -static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq, struct pcmcia_device *handle) +static const struct ide_port_ops idecs_port_ops = { + .quirkproc = ide_undecoded_slave, +}; + +static ide_hwif_t *idecs_register(unsigned long io, unsigned long ctl, + unsigned long irq, struct pcmcia_device *handle) { ide_hwif_t *hwif; hw_regs_t hw; int i; u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; + if (!request_region(io, 8, DRV_NAME)) { + printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", + DRV_NAME, io, io + 7); + return NULL; + } + + if (!request_region(ctl, 1, DRV_NAME)) { + printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n", + DRV_NAME, ctl); + release_region(io, 8); + return NULL; + } + memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw, io, ctl); hw.irq = irq; hw.chipset = ide_pci; hw.dev = &handle->dev; - hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]); + hwif = ide_find_port(); if (hwif == NULL) - return -1; + goto out_release; i = hwif->index; - if (hwif->present) - ide_unregister(i, 0, 0); - else if (!hwif->hold) - ide_init_port_data(hwif, i); - + ide_init_port_data(hwif, i); ide_init_port_hw(hwif, &hw); - hwif->quirkproc = &ide_undecoded_slave; + hwif->port_ops = &idecs_port_ops; idx[0] = i; ide_device_add(idx, NULL); - return hwif->present ? i : -1; + if (hwif->present) + return hwif; + +out_release: + release_region(ctl, 1); + release_region(io, 8); + return NULL; } /*====================================================================== @@ -199,8 +222,9 @@ static int ide_config(struct pcmcia_device *link) cistpl_cftable_entry_t dflt; } *stk = NULL; cistpl_cftable_entry_t *cfg; - int i, pass, last_ret = 0, last_fn = 0, hd, is_kme = 0; + int i, pass, last_ret = 0, last_fn = 0, is_kme = 0; unsigned long io_base, ctl_base; + ide_hwif_t *hwif; DEBUG(0, "ide_config(0x%p)\n", link); @@ -296,14 +320,15 @@ static int ide_config(struct pcmcia_device *link) outb(0x81, ctl_base+1); /* retry registration in case device is still spinning up */ - for (hd = -1, i = 0; i < 10; i++) { - hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link); - if (hd >= 0) break; + for (i = 0; i < 10; i++) { + hwif = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link); + if (hwif) + break; if (link->io.NumPorts1 == 0x20) { outb(0x02, ctl_base + 0x10); - hd = idecs_register(io_base + 0x10, ctl_base + 0x10, - link->irq.AssignedIRQ, link); - if (hd >= 0) { + hwif = idecs_register(io_base + 0x10, ctl_base + 0x10, + link->irq.AssignedIRQ, link); + if (hwif) { io_base += 0x10; ctl_base += 0x10; break; @@ -312,7 +337,7 @@ static int ide_config(struct pcmcia_device *link) msleep(100); } - if (hd < 0) { + if (hwif == NULL) { printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3lx & 0x%3lx" ", irq %u failed\n", io_base, ctl_base, link->irq.AssignedIRQ); @@ -320,10 +345,10 @@ static int ide_config(struct pcmcia_device *link) } info->ndev = 1; - sprintf(info->node.dev_name, "hd%c", 'a' + (hd * 2)); - info->node.major = ide_major[hd]; + sprintf(info->node.dev_name, "hd%c", 'a' + hwif->index * 2); + info->node.major = hwif->major; info->node.minor = 0; - info->hd = hd; + info->hwif = hwif; link->dev_node = &info->node; printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n", info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10); @@ -354,13 +379,14 @@ failed: void ide_release(struct pcmcia_device *link) { ide_info_t *info = link->priv; + ide_hwif_t *hwif = info->hwif; DEBUG(0, "ide_release(0x%p)\n", link); if (info->ndev) { /* FIXME: if this fails we need to queue the cleanup somehow -- need to investigate the required PCMCIA magic */ - ide_unregister(info->hd, 0, 0); + ide_unregister(hwif); } info->ndev = 0; diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/legacy/ide_platform.c index 688fcae17488..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; @@ -89,7 +89,7 @@ static int __devinit plat_ide_probe(struct platform_device *pdev) res_alt->start, res_alt->end - res_alt->start + 1); } - hwif = ide_find_port((unsigned long)base); + hwif = ide_find_port(); if (!hwif) { ret = -ENODEV; goto out; @@ -102,7 +102,7 @@ static int __devinit plat_ide_probe(struct platform_device *pdev) ide_init_port_hw(hwif, &hw); if (mmio) { - hwif->mmio = 1; + hwif->host_flags = IDE_HFLAG_MMIO; default_hwif_mmiops(hwif); } @@ -122,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, 0, 0); + ide_unregister(hwif); return 0; } @@ -130,6 +130,7 @@ static int __devexit plat_ide_remove(struct platform_device *pdev) static struct platform_driver platform_ide_driver = { .driver = { .name = "pata_platform", + .owner = THIS_MODULE, }, .probe = plat_ide_probe, .remove = __devexit_p(plat_ide_remove), @@ -147,6 +148,7 @@ static void __exit platform_ide_exit(void) MODULE_DESCRIPTION("Platform IDE driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:pata_platform"); module_init(platform_ide_init); module_exit(platform_ide_exit); diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c index eaf5dbe58bc2..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; @@ -120,7 +120,7 @@ static int __init macide_init(void) macide_setup_ports(&hw, base, irq, ack_intr); - hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]); + hwif = ide_find_port(); if (hwif) { u8 index = hwif->index; u8 idx[4] = { index, 0xff, 0xff, 0xff }; @@ -128,8 +128,6 @@ static int __init macide_init(void) ide_init_port_data(hwif, index); ide_init_port_hw(hwif, &hw); - hwif->mmio = 1; - ide_device_add(idx, NULL); } diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c index 2da28759686e..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,17 +133,19 @@ 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])); - hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]); + hwif = ide_find_port(); if (hwif) { ide_init_port_data(hwif, hwif->index); ide_init_port_hw(hwif, &hw); - hwif->mmio = 1; + + /* 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 2f4f47ad602f..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" */ /* @@ -37,6 +33,8 @@ #include <asm/system.h> #include <asm/io.h> +#define DRV_NAME "qd65xx" + #include "qd65xx.h" /* @@ -88,12 +86,12 @@ static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */ /* - * qd_select: + * qd65xx_select: * - * This routine is invoked from ide.c to prepare for access to a given drive. + * This routine is invoked to prepare for access to a given drive. */ -static void qd_select (ide_drive_t *drive) +static void qd65xx_select(ide_drive_t *drive) { u8 index = (( (QD_TIMREG(drive)) & 0x80 ) >> 7) | (QD_TIMREG(drive) & 0x02); @@ -112,17 +110,18 @@ static void qd_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; } /* @@ -133,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; + + 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((recovery_cycle<<4) | active_cycle); + return (rec_cyc << 4) | act_cyc; } /* @@ -168,36 +170,15 @@ static int qd_find_disk_type (ide_drive_t *drive, } /* - * qd_timing_ok: - * - * check whether timings don't conflict - */ - -static int qd_timing_ok (ide_drive_t drives[]) -{ - return (IDE_IMPLY(drives[0].present && drives[1].present, - IDE_IMPLY(QD_TIMREG(drives) == QD_TIMREG(drives+1), - QD_TIMING(drives) == QD_TIMING(drives+1)))); - /* if same timing register, must be same timing */ -} - -/* * qd_set_timing: * - * records the timing, and enables selectproc as needed + * records the timing */ static void qd_set_timing (ide_drive_t *drive, u8 timing) { - ide_hwif_t *hwif = HWIF(drive); - drive->drive_data &= 0xff00; drive->drive_data |= timing; - if (qd_timing_ok(hwif->drives)) { - qd_select(drive); /* selects once */ - hwif->selectproc = NULL; - } else - hwif->selectproc = &qd_select; printk(KERN_DEBUG "%s: %#x\n", drive->name, timing); } @@ -225,10 +206,11 @@ static void qd6500_set_pio_mode(ide_drive_t *drive, const u8 pio) static void qd6580_set_pio_mode(ide_drive_t *drive, const u8 pio) { - int base = HWIF(drive)->select_data; + ide_hwif_t *hwif = drive->hwif; unsigned int cycle_time; int active_time = 175; int recovery_time = 415; /* worst case values from the dos driver */ + u8 base = (hwif->config_data & 0xff00) >> 8; if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)) { cycle_time = ide_pio_cycle_time(drive, pio); @@ -299,21 +281,10 @@ static int __init qd_testreg(int port) return (readreg != QD_TESTVAL); } -/* - * qd_setup: - * - * called to setup an ata channel : adjusts attributes & links for tuning - */ - -static void __init qd_setup(ide_hwif_t *hwif, int base, int config) -{ - hwif->select_data = base; - hwif->config_data = config; -} - static void __init qd6500_port_init_devs(ide_hwif_t *hwif) { - u8 base = hwif->select_data, config = QD_CONFIG(hwif); + u8 base = (hwif->config_data & 0xff00) >> 8; + u8 config = QD_CONFIG(hwif); hwif->drives[0].drive_data = QD6500_DEF_DATA; hwif->drives[1].drive_data = QD6500_DEF_DATA; @@ -322,9 +293,10 @@ static void __init qd6500_port_init_devs(ide_hwif_t *hwif) static void __init qd6580_port_init_devs(ide_hwif_t *hwif) { u16 t1, t2; - u8 base = hwif->select_data, config = QD_CONFIG(hwif); + u8 base = (hwif->config_data & 0xff00) >> 8; + u8 config = QD_CONFIG(hwif); - if (QD_CONTROL(hwif) & QD_CONTR_SEC_DISABLED) { + if (hwif->host_flags & IDE_HFLAG_SINGLE) { t1 = QD6580_DEF_DATA; t2 = QD6580_DEF_DATA2; } else @@ -334,11 +306,23 @@ static void __init qd6580_port_init_devs(ide_hwif_t *hwif) hwif->drives[1].drive_data = t2; } +static const struct ide_port_ops qd6500_port_ops = { + .port_init_devs = qd6500_port_init_devs, + .set_pio_mode = qd6500_set_pio_mode, + .selectproc = qd65xx_select, +}; + +static const struct ide_port_ops qd6580_port_ops = { + .port_init_devs = qd6580_port_init_devs, + .set_pio_mode = qd6580_set_pio_mode, + .selectproc = qd65xx_select, +}; + 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, }; @@ -351,55 +335,41 @@ static const struct ide_port_info qd65xx_port_info __initdata = { static int __init qd_probe(int base) { - ide_hwif_t *hwif; - u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; - u8 config; - u8 unit; + int rc; + u8 config, unit, control; + struct ide_port_info d = qd65xx_port_info; config = inb(QD_CONFIG_PORT); if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) ) - return 1; + return -ENODEV; unit = ! (config & QD_CONFIG_IDE_BASEPORT); - if ((config & 0xf0) == QD_CONFIG_QD6500) { + if (unit) + d.host_flags |= IDE_HFLAG_QD_2ND_PORT; - if (qd_testreg(base)) return 1; /* bad register */ + switch (config & 0xf0) { + case QD_CONFIG_QD6500: + if (qd_testreg(base)) + return -ENODEV; /* bad register */ - /* qd6500 found */ - - hwif = &ide_hwifs[unit]; - printk(KERN_NOTICE "%s: qd6500 at %#x\n", hwif->name, base); - printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n", - config, QD_ID3); - if (config & QD_CONFIG_DISABLED) { printk(KERN_WARNING "qd6500 is disabled !\n"); - return 1; + return -ENODEV; } - qd_setup(hwif, base, config); - - hwif->port_init_devs = qd6500_port_init_devs; - hwif->set_pio_mode = &qd6500_set_pio_mode; - - idx[unit] = unit; - - ide_device_add(idx, &qd65xx_port_info); - - return 1; - } - - if (((config & 0xf0) == QD_CONFIG_QD6580_A) || - ((config & 0xf0) == QD_CONFIG_QD6580_B)) { - - u8 control; - - if (qd_testreg(base) || qd_testreg(base+0x02)) return 1; - /* bad registers */ + printk(KERN_NOTICE "qd6500 at %#x\n", base); + printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n", + config, QD_ID3); - /* qd6580 found */ + d.port_ops = &qd6500_port_ops; + d.host_flags |= IDE_HFLAG_SINGLE; + break; + case QD_CONFIG_QD6580_A: + case QD_CONFIG_QD6580_B: + if (qd_testreg(base) || qd_testreg(base + 0x02)) + return -ENODEV; /* bad registers */ control = inb(QD_CONTROL_PORT); @@ -409,69 +379,44 @@ static int __init qd_probe(int base) outb(QD_DEF_CONTR, QD_CONTROL_PORT); - if (control & QD_CONTR_SEC_DISABLED) { - /* secondary disabled */ - - hwif = &ide_hwifs[unit]; - printk(KERN_INFO "%s: qd6580: single IDE board\n", - hwif->name); - - qd_setup(hwif, base, config | (control << 8)); - - hwif->port_init_devs = qd6580_port_init_devs; - hwif->set_pio_mode = &qd6580_set_pio_mode; - - idx[unit] = unit; + d.port_ops = &qd6580_port_ops; + if (control & QD_CONTR_SEC_DISABLED) + d.host_flags |= IDE_HFLAG_SINGLE; - ide_device_add(idx, &qd65xx_port_info); - - return 1; - } else { - ide_hwif_t *mate; - - hwif = &ide_hwifs[0]; - mate = &ide_hwifs[1]; - /* secondary enabled */ - printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n", - hwif->name, mate->name); - - qd_setup(hwif, base, config | (control << 8)); - - hwif->port_init_devs = qd6580_port_init_devs; - hwif->set_pio_mode = &qd6580_set_pio_mode; - - qd_setup(mate, base, config | (control << 8)); - - mate->port_init_devs = qd6580_port_init_devs; - mate->set_pio_mode = &qd6580_set_pio_mode; + printk(KERN_INFO "qd6580: %s IDE board\n", + (control & QD_CONTR_SEC_DISABLED) ? "single" : "dual"); + break; + default: + return -ENODEV; + } - idx[0] = 0; - idx[1] = 1; + rc = ide_legacy_device_add(&d, (base << 8) | config); - ide_device_add(idx, &qd65xx_port_info); + if (d.host_flags & IDE_HFLAG_SINGLE) + return (rc == 0) ? 1 : rc; - return 0; /* no other qd65xx possible */ - } - } - /* no qd65xx found */ - return 1; + 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"); static int __init qd65xx_init(void) { + int rc1, rc2 = -ENODEV; + if (probe_qd65xx == 0) return -ENODEV; - if (qd_probe(0x30)) - qd_probe(0xb0); - if (ide_hwifs[0].chipset != ide_qd65xx && - ide_hwifs[1].chipset != ide_qd65xx) + rc1 = qd_probe(0x30); + if (rc1) + rc2 = qd_probe(0xb0); + + if (rc1 < 0 && rc2 < 0) return -ENODEV; + return 0; } diff --git a/drivers/ide/legacy/qd65xx.h b/drivers/ide/legacy/qd65xx.h index 28dd50a15d55..c83dea85e621 100644 --- a/drivers/ide/legacy/qd65xx.h +++ b/drivers/ide/legacy/qd65xx.h @@ -30,7 +30,6 @@ #define QD_ID3 ((config & QD_CONFIG_ID3)!=0) #define QD_CONFIG(hwif) ((hwif)->config_data & 0x00ff) -#define QD_CONTROL(hwif) (((hwif)->config_data & 0xff00) >> 8) #define QD_TIMING(drive) (byte)(((drive)->drive_data) & 0x00ff) #define QD_TIMREG(drive) (byte)((((drive)->drive_data) & 0xff00) >> 8) diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c index 5696ba026005..b54a14a57755 100644 --- a/drivers/ide/legacy/umc8672.c +++ b/drivers/ide/legacy/umc8672.c @@ -19,7 +19,7 @@ */ /* - * VLB Controller Support from + * VLB Controller Support from * Wolfram Podien * Rohoefe 3 * D28832 Achim @@ -32,7 +32,7 @@ * #define UMC_DRIVE0 11 * in the beginning of the driver, which sets the speed of drive 0 to 11 (there * are some lines present). 0 - 11 are allowed speed values. These values are - * the results from the DOS speed test program supplied from UMC. 11 is the + * the results from the DOS speed test program supplied from UMC. 11 is the * highest speed (about PIO mode 3) */ #define REALLY_SLOW_IO /* some systems can safely undef this */ @@ -51,6 +51,8 @@ #include <asm/io.h> +#define DRV_NAME "umc8672" + /* * Default speeds. These can be changed with "auto-tune" and/or hdparm. */ @@ -60,103 +62,103 @@ #define UMC_DRIVE3 1 /* In case of crash reduce speed */ static u8 current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3}; -static const u8 pio_to_umc [5] = {0,3,7,10,11}; /* rough guesses */ +static const u8 pio_to_umc [5] = {0, 3, 7, 10, 11}; /* rough guesses */ /* 0 1 2 3 4 5 6 7 8 9 10 11 */ static const u8 speedtab [3][12] = { - {0xf, 0xb, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }, - {0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }, - {0xff,0xcb,0xc0,0x58,0x36,0x33,0x23,0x22,0x21,0x11,0x10,0x0}}; + {0x0f, 0x0b, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1}, + {0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1}, + {0xff, 0xcb, 0xc0, 0x58, 0x36, 0x33, 0x23, 0x22, 0x21, 0x11, 0x10, 0x0} +}; -static void out_umc (char port,char wert) +static void out_umc(char port, char wert) { - outb_p(port,0x108); - outb_p(wert,0x109); + outb_p(port, 0x108); + outb_p(wert, 0x109); } -static inline u8 in_umc (char port) +static inline u8 in_umc(char port) { - outb_p(port,0x108); + outb_p(port, 0x108); return inb_p(0x109); } -static void umc_set_speeds (u8 speeds[]) +static void umc_set_speeds(u8 speeds[]) { int i, tmp; - outb_p(0x5A,0x108); /* enable umc */ + outb_p(0x5A, 0x108); /* enable umc */ - out_umc (0xd7,(speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4))); - out_umc (0xd6,(speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4))); + out_umc(0xd7, (speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4))); + out_umc(0xd6, (speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4))); tmp = 0; - for (i = 3; i >= 0; i--) { + for (i = 3; i >= 0; i--) tmp = (tmp << 2) | speedtab[1][speeds[i]]; + out_umc(0xdc, tmp); + for (i = 0; i < 4; i++) { + out_umc(0xd0 + i, speedtab[2][speeds[i]]); + out_umc(0xd8 + i, speedtab[2][speeds[i]]); } - out_umc (0xdc,tmp); - for (i = 0;i < 4; i++) { - out_umc (0xd0+i,speedtab[2][speeds[i]]); - out_umc (0xd8+i,speedtab[2][speeds[i]]); - } - outb_p(0xa5,0x108); /* disable umc */ + outb_p(0xa5, 0x108); /* disable umc */ - printk ("umc8672: drive speeds [0 to 11]: %d %d %d %d\n", + printk("umc8672: drive speeds [0 to 11]: %d %d %d %d\n", speeds[0], speeds[1], speeds[2], speeds[3]); } static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio) { + ide_hwif_t *hwif = drive->hwif; unsigned long flags; - ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup; printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", drive->name, pio, pio_to_umc[pio]); spin_lock_irqsave(&ide_lock, flags); - if (hwgroup && hwgroup->handler != NULL) { + if (hwif->mate && hwif->mate->hwgroup->handler) { printk(KERN_ERR "umc8672: other interface is busy: exiting tune_umc()\n"); } else { current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio]; - umc_set_speeds (current_speeds); + umc_set_speeds(current_speeds); } spin_unlock_irqrestore(&ide_lock, flags); } +static const struct ide_port_ops umc8672_port_ops = { + .set_pio_mode = umc_set_pio_mode, +}; + static const struct ide_port_info umc8672_port_info __initdata = { + .name = DRV_NAME, .chipset = ide_umc8672, - .host_flags = IDE_HFLAG_NO_DMA | IDE_HFLAG_NO_AUTOTUNE, + .port_ops = &umc8672_port_ops, + .host_flags = IDE_HFLAG_NO_DMA, .pio_mask = ATA_PIO4, }; static int __init umc8672_probe(void) { unsigned long flags; - static u8 idx[4] = { 0, 1, 0xff, 0xff }; if (!request_region(0x108, 2, "umc8672")) { printk(KERN_ERR "umc8672: ports 0x108-0x109 already in use.\n"); return 1; } local_irq_save(flags); - outb_p(0x5A,0x108); /* enable umc */ + outb_p(0x5A, 0x108); /* enable umc */ if (in_umc (0xd5) != 0xa0) { local_irq_restore(flags); printk(KERN_ERR "umc8672: not found\n"); release_region(0x108, 2); - return 1; + return 1; } - outb_p(0xa5,0x108); /* disable umc */ + outb_p(0xa5, 0x108); /* disable umc */ - umc_set_speeds (current_speeds); + umc_set_speeds(current_speeds); local_irq_restore(flags); - ide_hwifs[0].set_pio_mode = &umc_set_pio_mode; - ide_hwifs[1].set_pio_mode = &umc_set_pio_mode; - - ide_device_add(idx, &umc8672_port_info); - - return 0; + return ide_legacy_device_add(&umc8672_port_info, 0); } -int probe_umc8672 = 0; +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 0f4bf5d72835..1a6c27b32498 100644 --- a/drivers/ide/mips/au1xxx-ide.c +++ b/drivers/ide/mips/au1xxx-ide.c @@ -32,19 +32,12 @@ #include <linux/kernel.h> #include <linux/delay.h> #include <linux/platform_device.h> - #include <linux/init.h> #include <linux/ide.h> -#include <linux/sysdev.h> - -#include <linux/dma-mapping.h> - -#include "ide-timing.h" +#include <linux/scatterlist.h> -#include <asm/io.h> #include <asm/mach-au1x00/au1xxx.h> #include <asm/mach-au1x00/au1xxx_dbdma.h> - #include <asm/mach-au1x00/au1xxx_ide.h> #define DRV_NAME "au1200-ide" @@ -54,7 +47,6 @@ #define IDE_AU1XXX_BURSTMODE 1 static _auide_hwif auide_hwif; -static int dbdma_init_done; #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA) @@ -66,7 +58,7 @@ void auide_insw(unsigned long port, void *addr, u32 count) if(!put_dest_flags(ahwif->rx_chan, (void*)addr, count << 1, DDMA_FLAGS_NOIE)) { - printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__); + printk(KERN_ERR "%s failed %d\n", __func__, __LINE__); return; } ctp = *((chan_tab_t **)ahwif->rx_chan); @@ -84,7 +76,7 @@ void auide_outsw(unsigned long port, void *addr, u32 count) if(!put_source_flags(ahwif->tx_chan, (void*)addr, count << 1, DDMA_FLAGS_NOIE)) { - printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__); + printk(KERN_ERR "%s failed %d\n", __func__, __LINE__); return; } ctp = *((chan_tab_t **)ahwif->tx_chan); @@ -94,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) @@ -255,7 +258,7 @@ static int auide_build_dmatable(ide_drive_t *drive) (void*) sg_virt(sg), tc, flags)) { printk(KERN_ERR "%s failed %d\n", - __FUNCTION__, __LINE__); + __func__, __LINE__); } } else { @@ -263,7 +266,7 @@ static int auide_build_dmatable(ide_drive_t *drive) (void*) sg_virt(sg), tc, flags)) { printk(KERN_ERR "%s failed %d\n", - __FUNCTION__, __LINE__); + __func__, __LINE__); } } @@ -320,35 +323,6 @@ static int auide_dma_setup(ide_drive_t *drive) return 0; } -static u8 auide_mdma_filter(ide_drive_t *drive) -{ - /* - * FIXME: ->white_list and ->black_list are based on completely bogus - * ->ide_dma_check implementation which didn't set neither the host - * controller timings nor the device for the desired transfer mode. - * - * They should be either removed or 0x00 MWDMA mask should be - * returned for devices on the ->black_list. - */ - - if (dbdma_init_done == 0) { - auide_hwif.white_list = ide_in_drive_list(drive->id, - dma_white_list); - auide_hwif.black_list = ide_in_drive_list(drive->id, - dma_black_list); - auide_hwif.drive = drive; - auide_ddma_init(&auide_hwif); - dbdma_init_done = 1; - } - - /* Is the drive in our DMA black list? */ - if (auide_hwif.black_list) - printk(KERN_WARNING "%s: Disabling DMA for %s (blacklisted)\n", - drive->name, drive->id->model); - - return drive->hwif->mwdma_mask; -} - static int auide_dma_test_irq(ide_drive_t *drive) { if (drive->waiting_for_dma == 0) @@ -394,48 +368,48 @@ 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; dev->dev_devwidth = devwidth; dev->dev_flags = flags; } - -#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) +#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA static void auide_dma_timeout(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name); - if (hwif->ide_dma_test_irq(drive)) + if (auide_dma_test_irq(drive)) return; - hwif->ide_dma_end(drive); + auide_dma_end(drive); } - -static int auide_ddma_init(_auide_hwif *auide) { - +static const struct ide_dma_ops au1xxx_dma_ops = { + .dma_host_set = auide_dma_host_set, + .dma_setup = auide_dma_setup, + .dma_exec_cmd = auide_dma_exec_cmd, + .dma_start = auide_dma_start, + .dma_end = auide_dma_end, + .dma_test_irq = auide_dma_test_irq, + .dma_lost_irq = auide_dma_lost_irq, + .dma_timeout = auide_dma_timeout, +}; + +static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d) +{ + _auide_hwif *auide = (_auide_hwif *)hwif->hwif_data; dbdev_tab_t source_dev_tab, target_dev_tab; u32 dev_id, tsize, devwidth, flags; - ide_hwif_t *hwif = auide->hwif; - dev_id = AU1XXX_ATA_DDMA_REQ; + dev_id = IDE_DDMA_REQ; - if (auide->white_list || auide->black_list) { - tsize = 8; - devwidth = 32; - } - else { - tsize = 1; - devwidth = 16; - - printk(KERN_ERR "au1xxx-ide: %s is not on ide driver whitelist.\n",auide_hwif.drive->id->model); - printk(KERN_ERR " please read 'Documentation/mips/AU1xxx_IDE.README'"); - } + tsize = 8; /* 1 */ + devwidth = 32; /* 16 */ #ifdef IDE_AU1XXX_BURSTMODE flags = DEV_FLAGS_SYNC | DEV_FLAGS_BURSTABLE; @@ -487,9 +461,9 @@ static int auide_ddma_init(_auide_hwif *auide) { return 0; } #else - -static int auide_ddma_init( _auide_hwif *auide ) +static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d) { + _auide_hwif *auide = (_auide_hwif *)hwif->hwif_data; dbdev_tab_t source_dev_tab; int flags; @@ -537,20 +511,28 @@ static int auide_ddma_init( _auide_hwif *auide ) 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 = { + .set_pio_mode = au1xxx_set_pio_mode, + .set_dma_mode = auide_set_dma_mode, +}; + static const struct ide_port_info au1xxx_port_info = { + .init_dma = auide_ddma_init, + .port_ops = &au1xxx_port_ops, +#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA + .dma_ops = &au1xxx_dma_ops, +#endif .host_flags = IDE_HFLAG_POST_SET_MODE | - IDE_HFLAG_NO_DMA | /* no SFF-style DMA */ IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_UNMASK_IRQS, .pio_mask = ATA_PIO4, @@ -591,21 +573,24 @@ static int au_ide_probe(struct device *dev) goto out; } - if (!request_mem_region (res->start, res->end-res->start, pdev->name)) { + if (!request_mem_region(res->start, res->end - res->start + 1, + pdev->name)) { pr_debug("%s: request_mem_region failed\n", DRV_NAME); ret = -EBUSY; goto out; } - ahwif->regbase = (u32)ioremap(res->start, res->end-res->start); + ahwif->regbase = (u32)ioremap(res->start, res->end - res->start + 1); if (ahwif->regbase == 0) { ret = -ENOMEM; goto out; } - /* FIXME: This might possibly break PCMCIA IDE devices */ - - hwif = &ide_hwifs[pdev->id]; + hwif = ide_find_port(); + if (hwif == NULL) { + ret = -ENOENT; + goto out; + } memset(&hw, 0, sizeof(hw)); auide_setup_ports(&hw, ahwif); @@ -617,35 +602,13 @@ static int au_ide_probe(struct device *dev) hwif->dev = dev; - /* hold should be on in all cases */ - hwif->hold = 1; - - hwif->mmio = 1; - /* If the user has selected DDMA assisted copies, then set up a few local I/O function entry points */ #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA - hwif->INSW = auide_insw; - hwif->OUTSW = auide_outsw; -#endif - - hwif->set_pio_mode = &au1xxx_set_pio_mode; - hwif->set_dma_mode = &auide_set_dma_mode; - -#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA - hwif->dma_timeout = &auide_dma_timeout; - - hwif->mdma_filter = &auide_mdma_filter; - - hwif->dma_host_set = &auide_dma_host_set; - hwif->dma_exec_cmd = &auide_dma_exec_cmd; - hwif->dma_start = &auide_dma_start; - hwif->ide_dma_end = &auide_dma_end; - hwif->dma_setup = &auide_dma_setup; - hwif->ide_dma_test_irq = &auide_dma_test_irq; - hwif->dma_lost_irq = &auide_dma_lost_irq; + 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 */ @@ -653,11 +616,6 @@ static int au_ide_probe(struct device *dev) auide_hwif.hwif = hwif; hwif->hwif_data = &auide_hwif; -#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA - auide_ddma_init(&auide_hwif); - dbdma_init_done = 1; -#endif - idx[0] = hwif->index; ide_device_add(idx, &au1xxx_port_info); @@ -677,12 +635,12 @@ 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, 0, 0); + ide_unregister(hwif); iounmap((void *)ahwif->regbase); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, res->end - res->start); + release_mem_region(res->start, res->end - res->start + 1); return 0; } diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c index 956259fc09ba..712d17bdd470 100644 --- a/drivers/ide/mips/swarm.c +++ b/drivers/ide/mips/swarm.c @@ -76,17 +76,12 @@ static int __devinit swarm_ide_probe(struct device *dev) if (!SIBYTE_HAVE_IDE) return -ENODEV; - /* Find an empty slot. */ - for (i = 0; i < MAX_HWIFS; i++) - if (!ide_hwifs[i].io_ports[IDE_DATA_OFFSET]) - break; - if (i >= MAX_HWIFS) { + hwif = ide_find_port(); + if (hwif == NULL) { printk(KERN_ERR DRV_NAME ": no free slot for interface\n"); return -ENOMEM; } - hwif = ide_hwifs + i; - base = ioremap(A_IO_EXT_BASE, 0x800); offset = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS)); size = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_MULT_SIZE, IDE_CS)); @@ -114,16 +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); - /* Prevent resource map manipulation. */ - hwif->mmio = 1; + hwif->chipset = ide_generic; - hwif->noprobe = 0; - 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 cfb3265bc1a8..7f46c224b7c4 100644 --- a/drivers/ide/pci/aec62xx.c +++ b/drivers/ide/pci/aec62xx.c @@ -135,12 +135,12 @@ static void aec6260_set_mode(ide_drive_t *drive, const u8 speed) static void aec_set_pio_mode(ide_drive_t *drive, const u8 pio) { - drive->hwif->set_dma_mode(drive, pio + XFER_PIO_0); + drive->hwif->port_ops->set_dma_mode(drive, pio + XFER_PIO_0); } 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); @@ -175,27 +175,23 @@ static u8 __devinit atp86x_cable_detect(ide_hwif_t *hwif) return (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; } -static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - - hwif->set_pio_mode = &aec_set_pio_mode; - - if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) - hwif->set_dma_mode = &aec6210_set_mode; - else { - hwif->set_dma_mode = &aec6260_set_mode; +static const struct ide_port_ops atp850_port_ops = { + .set_pio_mode = aec_set_pio_mode, + .set_dma_mode = aec6210_set_mode, +}; - hwif->cable_detect = atp86x_cable_detect; - } -} +static const struct ide_port_ops atp86x_port_ops = { + .set_pio_mode = aec_set_pio_mode, + .set_dma_mode = aec6260_set_mode, + .cable_detect = atp86x_cable_detect, +}; static const struct ide_port_info aec62xx_chipsets[] __devinitdata = { { /* 0 */ .name = "AEC6210", .init_chipset = init_chipset_aec62xx, - .init_hwif = init_hwif_aec62xx, .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, + .port_ops = &atp850_port_ops, .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_NO_DSC | @@ -207,7 +203,7 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = { },{ /* 1 */ .name = "AEC6260", .init_chipset = init_chipset_aec62xx, - .init_hwif = init_hwif_aec62xx, + .port_ops = &atp86x_port_ops, .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_NO_AUTODMA | IDE_HFLAG_ABUSE_SET_DMA_MODE | IDE_HFLAG_OFF_BOARD, @@ -217,17 +213,18 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = { },{ /* 2 */ .name = "AEC6260R", .init_chipset = init_chipset_aec62xx, - .init_hwif = init_hwif_aec62xx, .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, + .port_ops = &atp86x_port_ops, .host_flags = IDE_HFLAG_NO_ATAPI_DMA | - IDE_HFLAG_ABUSE_SET_DMA_MODE, + IDE_HFLAG_ABUSE_SET_DMA_MODE | + IDE_HFLAG_NON_BOOTABLE, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, },{ /* 3 */ .name = "AEC6280", .init_chipset = init_chipset_aec62xx, - .init_hwif = init_hwif_aec62xx, + .port_ops = &atp86x_port_ops, .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_ABUSE_SET_DMA_MODE | IDE_HFLAG_OFF_BOARD, @@ -237,8 +234,8 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = { },{ /* 4 */ .name = "AEC6280R", .init_chipset = init_chipset_aec62xx, - .init_hwif = init_hwif_aec62xx, .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, + .port_ops = &atp86x_port_ops, .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_ABUSE_SET_DMA_MODE | IDE_HFLAG_OFF_BOARD, diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index b3b6f514ce2d..b36a22b8c213 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) { @@ -610,7 +370,7 @@ static int ali_cable_override(struct pci_dev *pdev) } /** - * ata66_ali15x3 - check for UDMA 66 support + * ali_cable_detect - cable detection * @hwif: IDE interface * * This checks if the controller and the cable are capable @@ -620,7 +380,7 @@ static int ali_cable_override(struct pci_dev *pdev) * FIXME: frobs bits that are not defined on newer ALi devicea */ -static u8 __devinit ata66_ali15x3(ide_hwif_t *hwif) +static u8 __devinit ali_cable_detect(ide_hwif_t *hwif) { struct pci_dev *dev = to_pci_dev(hwif->dev); unsigned long flags; @@ -652,27 +412,7 @@ static u8 __devinit ata66_ali15x3(ide_hwif_t *hwif) return cbl; } -/** - * init_hwif_common_ali15x3 - Set up ALI IDE hardware - * @hwif: IDE interface - * - * Initialize the IDE structure side of the ALi 15x3 driver. - */ - -static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif) -{ - hwif->set_pio_mode = &ali_set_pio_mode; - hwif->set_dma_mode = &ali_set_dma_mode; - hwif->udma_filter = &ali_udma_filter; - - hwif->cable_detect = ata66_ali15x3; - - if (hwif->dma_base == 0) - return; - - hwif->dma_setup = &ali15x3_dma_setup; -} - +#ifndef CONFIG_SPARC64 /** * init_hwif_ali15x3 - Initialize the ALI IDE x86 stuff * @hwif: interface to configure @@ -722,35 +462,66 @@ static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif) if(irq >= 0) hwif->irq = irq; } - - init_hwif_common_ali15x3(hwif); } +#endif /** * init_dma_ali15x3 - set up DMA on ALi15x3 * @hwif: IDE interface - * @dmabase: DMA interface base PCI address + * @d: IDE port info * - * Set up the DMA functionality on the ALi 15x3. For the ALi - * controllers this is generic so we can let the generic code do - * the actual work. + * Set up the DMA functionality on the ALi 15x3. */ -static void __devinit init_dma_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase) +static int __devinit init_dma_ali15x3(ide_hwif_t *hwif, + const struct ide_port_info *d) { - if (m5229_revision < 0x20) - return; + struct pci_dev *dev = to_pci_dev(hwif->dev); + unsigned long base = ide_pci_dma_base(hwif, d); + + if (base == 0 || ide_pci_set_master(dev, d->name) < 0) + return -1; + if (!hwif->channel) - outb(inb(dmabase + 2) & 0x60, dmabase + 2); - ide_setup_dma(hwif, dmabase); + outb(inb(base + 2) & 0x60, base + 2); + + printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx\n", + hwif->name, base, base + 7); + + if (ide_allocate_dma_engine(hwif)) + return -1; + + ide_setup_dma(hwif, base); + + return 0; } +static const struct ide_port_ops ali_port_ops = { + .set_pio_mode = ali_set_pio_mode, + .set_dma_mode = ali_set_dma_mode, + .udma_filter = ali_udma_filter, + .cable_detect = ali_cable_detect, +}; + +static const struct ide_dma_ops ali_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ali15x3_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = ide_dma_start, + .dma_end = __ide_dma_end, + .dma_test_irq = ide_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; + 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, - .host_flags = IDE_HFLAG_BOOTABLE, + .port_ops = &ali_port_ops, .pio_mask = ATA_PIO5, .swdma_mask = ATA_SWDMA2, .mwdma_mask = ATA_MWDMA2, @@ -793,14 +564,17 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev d.udma_mask = ATA_UDMA5; else d.udma_mask = ATA_UDMA6; + + d.dma_ops = &ali_dma_ops; + } else { + d.host_flags |= IDE_HFLAG_NO_DMA; + + d.mwdma_mask = d.swdma_mask = 0; } if (idx == 0) d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX; -#if defined(CONFIG_SPARC64) - d.init_hwif = init_hwif_common_ali15x3; -#endif /* CONFIG_SPARC64 */ return ide_setup_pci_device(dev, &d); } diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c index 2ef890ce8097..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; @@ -210,21 +210,20 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif) if (hwif->irq == 0) /* 0 is bogus but will do for now */ hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel); - - hwif->set_pio_mode = &amd_set_pio_mode; - hwif->set_dma_mode = &amd_set_drive; - - hwif->cable_detect = amd_cable_detect; } +static const struct ide_port_ops amd_port_ops = { + .set_pio_mode = amd_set_pio_mode, + .set_dma_mode = amd_set_drive, + .cable_detect = amd_cable_detect, +}; + #define IDE_HFLAGS_AMD \ (IDE_HFLAG_PIO_NO_BLACKLIST | \ - IDE_HFLAG_PIO_NO_DOWNGRADE | \ IDE_HFLAG_ABUSE_SET_DMA_MODE | \ IDE_HFLAG_POST_SET_MODE | \ IDE_HFLAG_IO_32BIT | \ - IDE_HFLAG_UNMASK_IRQS | \ - IDE_HFLAG_BOOTABLE) + IDE_HFLAG_UNMASK_IRQS) #define DECLARE_AMD_DEV(name_str, swdma, udma) \ { \ @@ -232,6 +231,7 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif) .init_chipset = init_chipset_amd74xx, \ .init_hwif = init_hwif_amd74xx, \ .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, \ + .port_ops = &amd_port_ops, \ .host_flags = IDE_HFLAGS_AMD, \ .pio_mask = ATA_PIO5, \ .swdma_mask = swdma, \ @@ -245,6 +245,7 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif) .init_chipset = init_chipset_amd74xx, \ .init_hwif = init_hwif_amd74xx, \ .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, \ + .port_ops = &amd_port_ops, \ .host_flags = IDE_HFLAGS_AMD, \ .pio_mask = ATA_PIO5, \ .swdma_mask = ATA_SWDMA2, \ diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c index 7e037c880cb0..8b637181681a 100644 --- a/drivers/ide/pci/atiixp.c +++ b/drivers/ide/pci/atiixp.c @@ -130,37 +130,26 @@ static u8 __devinit atiixp_cable_detect(ide_hwif_t *hwif) return ATA_CBL_PATA40; } -/** - * init_hwif_atiixp - fill in the hwif for the ATIIXP - * @hwif: IDE interface - * - * Set up the ide_hwif_t for the ATIIXP interface according to the - * capabilities of the hardware. - */ - -static void __devinit init_hwif_atiixp(ide_hwif_t *hwif) -{ - hwif->set_pio_mode = &atiixp_set_pio_mode; - hwif->set_dma_mode = &atiixp_set_dma_mode; - - hwif->cable_detect = atiixp_cable_detect; -} +static const struct ide_port_ops atiixp_port_ops = { + .set_pio_mode = atiixp_set_pio_mode, + .set_dma_mode = atiixp_set_dma_mode, + .cable_detect = atiixp_cable_detect, +}; static const struct ide_port_info atiixp_pci_info[] __devinitdata = { { /* 0 */ .name = "ATIIXP", - .init_hwif = init_hwif_atiixp, .enablebits = {{0x48,0x01,0x00}, {0x48,0x08,0x00}}, - .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE, + .port_ops = &atiixp_port_ops, + .host_flags = IDE_HFLAG_LEGACY_IRQS, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, },{ /* 1 */ .name = "SB600_PATA", - .init_hwif = init_hwif_atiixp, .enablebits = {{0x48,0x01,0x00}, {0x00,0x00,0x00}}, - .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS | - IDE_HFLAG_BOOTABLE, + .port_ops = &atiixp_port_ops, + .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c index 29fbc5ead03b..aaf38109eaec 100644 --- a/drivers/ide/pci/cmd640.c +++ b/drivers/ide/pci/cmd640.c @@ -4,7 +4,7 @@ /* * Original authors: abramov@cecmow.enet.dec.com (Igor Abramov) - * mlord@pobox.com (Mark Lord) + * mlord@pobox.com (Mark Lord) * * See linux/MAINTAINERS for address of current maintainer. * @@ -98,7 +98,7 @@ #define CMD640_PREFETCH_MASKS 1 -//#define CMD640_DUMP_REGS +/*#define CMD640_DUMP_REGS */ #include <linux/types.h> #include <linux/kernel.h> @@ -109,10 +109,9 @@ #include <asm/io.h> -/* - * This flag is set in ide.c by the parameter: ide0=cmd640_vlb - */ -int cmd640_vlb = 0; +#define DRV_NAME "cmd640" + +static int cmd640_vlb; /* * CMD640 specific registers definition. @@ -185,7 +184,6 @@ static DEFINE_SPINLOCK(cmd640_lock); * These are initialized to point at the devices we control */ static ide_hwif_t *cmd_hwif0, *cmd_hwif1; -static ide_drive_t *cmd_drives[4]; /* * Interface to access cmd640x registers @@ -207,13 +205,13 @@ static unsigned int cmd640_chip_version; /* PCI method 1 access */ -static void put_cmd640_reg_pci1 (u16 reg, u8 val) +static void put_cmd640_reg_pci1(u16 reg, u8 val) { outl_p((reg & 0xfc) | cmd640_key, 0xcf8); outb_p(val, (reg & 3) | 0xcfc); } -static u8 get_cmd640_reg_pci1 (u16 reg) +static u8 get_cmd640_reg_pci1(u16 reg) { outl_p((reg & 0xfc) | cmd640_key, 0xcf8); return inb_p((reg & 3) | 0xcfc); @@ -221,14 +219,14 @@ static u8 get_cmd640_reg_pci1 (u16 reg) /* PCI method 2 access (from CMD datasheet) */ -static void put_cmd640_reg_pci2 (u16 reg, u8 val) +static void put_cmd640_reg_pci2(u16 reg, u8 val) { outb_p(0x10, 0xcf8); outb_p(val, cmd640_key + reg); outb_p(0, 0xcf8); } -static u8 get_cmd640_reg_pci2 (u16 reg) +static u8 get_cmd640_reg_pci2(u16 reg) { u8 b; @@ -240,13 +238,13 @@ static u8 get_cmd640_reg_pci2 (u16 reg) /* VLB access */ -static void put_cmd640_reg_vlb (u16 reg, u8 val) +static void put_cmd640_reg_vlb(u16 reg, u8 val) { outb_p(reg, cmd640_key); outb_p(val, cmd640_key + 4); } -static u8 get_cmd640_reg_vlb (u16 reg) +static u8 get_cmd640_reg_vlb(u16 reg) { outb_p(reg, cmd640_key); return inb_p(cmd640_key + 4); @@ -268,11 +266,11 @@ static void put_cmd640_reg(u16 reg, u8 val) unsigned long flags; spin_lock_irqsave(&cmd640_lock, flags); - __put_cmd640_reg(reg,val); + __put_cmd640_reg(reg, val); spin_unlock_irqrestore(&cmd640_lock, flags); } -static int __init match_pci_cmd640_device (void) +static int __init match_pci_cmd640_device(void) { const u8 ven_dev[4] = {0x95, 0x10, 0x40, 0x06}; unsigned int i; @@ -292,7 +290,7 @@ static int __init match_pci_cmd640_device (void) /* * Probe for CMD640x -- pci method 1 */ -static int __init probe_for_cmd640_pci1 (void) +static int __init probe_for_cmd640_pci1(void) { __get_cmd640_reg = get_cmd640_reg_pci1; __put_cmd640_reg = put_cmd640_reg_pci1; @@ -308,7 +306,7 @@ static int __init probe_for_cmd640_pci1 (void) /* * Probe for CMD640x -- pci method 2 */ -static int __init probe_for_cmd640_pci2 (void) +static int __init probe_for_cmd640_pci2(void) { __get_cmd640_reg = get_cmd640_reg_pci2; __put_cmd640_reg = put_cmd640_reg_pci2; @@ -322,7 +320,7 @@ static int __init probe_for_cmd640_pci2 (void) /* * Probe for CMD640x -- vlb */ -static int __init probe_for_cmd640_vlb (void) +static int __init probe_for_cmd640_vlb(void) { u8 b; @@ -343,18 +341,18 @@ static int __init probe_for_cmd640_vlb (void) * Returns 1 if an IDE interface/drive exists at 0x170, * Returns 0 otherwise. */ -static int __init secondary_port_responding (void) +static int __init secondary_port_responding(void) { unsigned long flags; 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 */ } @@ -367,7 +365,7 @@ static int __init secondary_port_responding (void) /* * Dump out all cmd640 registers. May be called from ide.c */ -static void cmd640_dump_regs (void) +static void cmd640_dump_regs(void) { unsigned int reg = cmd640_vlb ? 0x50 : 0x00; @@ -382,13 +380,13 @@ 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. */ -static void __init check_prefetch (unsigned int index) +static void __init check_prefetch(ide_drive_t *drive, unsigned int index) { - ide_drive_t *drive = cmd_drives[index]; u8 b = get_cmd640_reg(prefetch_regs[index]); if (b & prefetch_masks[index]) { /* is prefetch off? */ @@ -403,39 +401,12 @@ static void __init check_prefetch (unsigned int index) drive->no_io_32bit = 0; } } - -/* - * Figure out which devices we control - */ -static void __init setup_device_ptrs (void) -{ - unsigned int i; - - cmd_hwif0 = &ide_hwifs[0]; /* default, if not found below */ - cmd_hwif1 = &ide_hwifs[1]; /* default, if not found below */ - for (i = 0; i < MAX_HWIFS; i++) { - ide_hwif_t *hwif = &ide_hwifs[i]; - if (hwif->chipset == ide_unknown || hwif->chipset == ide_forced) { - if (hwif->io_ports[IDE_DATA_OFFSET] == 0x1f0) - cmd_hwif0 = hwif; - else if (hwif->io_ports[IDE_DATA_OFFSET] == 0x170) - cmd_hwif1 = hwif; - } - } - cmd_drives[0] = &cmd_hwif0->drives[0]; - cmd_drives[1] = &cmd_hwif0->drives[1]; - cmd_drives[2] = &cmd_hwif1->drives[0]; - cmd_drives[3] = &cmd_hwif1->drives[1]; -} - -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - +#else /* * Sets prefetch mode for a drive. */ -static void set_prefetch_mode (unsigned int index, int mode) +static void set_prefetch_mode(ide_drive_t *drive, unsigned int index, int mode) { - ide_drive_t *drive = cmd_drives[index]; unsigned long flags; int reg = prefetch_regs[index]; u8 b; @@ -462,7 +433,7 @@ static void set_prefetch_mode (unsigned int index, int mode) /* * Dump out current drive clocks settings */ -static void display_clocks (unsigned int index) +static void display_clocks(unsigned int index) { u8 active_count, recovery_count; @@ -481,44 +452,16 @@ static void display_clocks (unsigned int index) * Pack active and recovery counts into single byte representation * used by controller */ -static inline u8 pack_nibbles (u8 upper, u8 lower) +static inline u8 pack_nibbles(u8 upper, u8 lower) { return ((upper & 0x0f) << 4) | (lower & 0x0f); } /* - * 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. */ -static void program_drive_counts (unsigned int index) +static void program_drive_counts(ide_drive_t *drive, unsigned int index) { unsigned long flags; u8 setup_count = setup_counts[index]; @@ -532,8 +475,11 @@ static void program_drive_counts (unsigned int index) * so we merge the timings, using the slowest value for each timing. */ if (index > 1) { - unsigned int mate; - if (cmd_drives[mate = index ^ 1]->present) { + ide_hwif_t *hwif = drive->hwif; + ide_drive_t *peer = &hwif->drives[!drive->select.b.unit]; + unsigned int mate = index ^ 1; + + if (peer->present) { if (setup_count < setup_counts[mate]) setup_count = setup_counts[mate]; if (active_count < active_counts[mate]) @@ -547,11 +493,11 @@ static void program_drive_counts (unsigned int index) * Convert setup_count to internal chipset representation */ switch (setup_count) { - case 4: setup_count = 0x00; break; - case 3: setup_count = 0x80; break; - case 1: - case 2: setup_count = 0x40; break; - default: setup_count = 0xc0; /* case 5 */ + case 4: setup_count = 0x00; break; + case 3: setup_count = 0x80; break; + case 1: + case 2: setup_count = 0x40; break; + default: setup_count = 0xc0; /* case 5 */ } /* @@ -572,11 +518,19 @@ static void program_drive_counts (unsigned int index) /* * Set a specific pio_mode for a drive */ -static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle_time) +static void cmd640_set_mode(ide_drive_t *drive, unsigned int index, + u8 pio_mode, unsigned int cycle_time) { 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; @@ -584,15 +538,15 @@ static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle active_time = ide_pio_timings[pio_mode].active_time; recovery_time = cycle_time - (setup_time + active_time); clock_time = 1000 / bus_speed; - cycle_count = (cycle_time + clock_time - 1) / clock_time; + cycle_count = DIV_ROUND_UP(cycle_time, clock_time); - setup_count = (setup_time + clock_time - 1) / clock_time; + setup_count = DIV_ROUND_UP(setup_time, clock_time); - active_count = (active_time + clock_time - 1) / clock_time; + active_count = DIV_ROUND_UP(active_time, clock_time); if (active_count < 2) active_count = 2; /* minimum allowed by cmd640 */ - recovery_count = (recovery_time + clock_time - 1) / clock_time; + recovery_count = DIV_ROUND_UP(recovery_time, clock_time); recovery_count2 = cycle_count - (setup_count + active_count); if (recovery_count2 > recovery_count) recovery_count = recovery_count2; @@ -621,7 +575,7 @@ static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle * 1) this is the wrong place to do it (proper is do_special() in ide.c) * 2) in practice this is rarely, if ever, necessary */ - program_drive_counts (index); + program_drive_counts(drive, index); } static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio) @@ -629,32 +583,26 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio) unsigned int index = 0, cycle_time; u8 b; - while (drive != cmd_drives[index]) { - if (++index > 3) { - printk(KERN_ERR "%s: bad news in %s\n", - drive->name, __FUNCTION__); - return; - } - } switch (pio) { - case 6: /* set fast-devsel off */ - case 7: /* set fast-devsel on */ - b = get_cmd640_reg(CNTRL) & ~0x27; - if (pio & 1) - b |= 0x27; - put_cmd640_reg(CNTRL, b); - printk("%s: %sabled cmd640 fast host timing (devsel)\n", drive->name, (pio & 1) ? "en" : "dis"); - return; - - case 8: /* set prefetch off */ - case 9: /* set prefetch on */ - set_prefetch_mode(index, pio & 1); - printk("%s: %sabled cmd640 prefetch\n", drive->name, (pio & 1) ? "en" : "dis"); - return; + case 6: /* set fast-devsel off */ + case 7: /* set fast-devsel on */ + b = get_cmd640_reg(CNTRL) & ~0x27; + if (pio & 1) + b |= 0x27; + put_cmd640_reg(CNTRL, b); + printk("%s: %sabled cmd640 fast host timing (devsel)\n", + drive->name, (pio & 1) ? "en" : "dis"); + return; + case 8: /* set prefetch off */ + case 9: /* set prefetch on */ + set_prefetch_mode(drive, index, pio & 1); + printk("%s: %sabled cmd640 prefetch\n", + drive->name, (pio & 1) ? "en" : "dis"); + return; } cycle_time = ide_pio_cycle_time(drive, pio); - cmd640_set_mode(index, pio, cycle_time); + cmd640_set_mode(drive, index, pio, cycle_time); printk("%s: selected cmd640 PIO mode%d (%dns)", drive->name, pio, cycle_time); @@ -662,6 +610,9 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio) display_clocks(index); } +static const struct ide_port_ops cmd640_port_ops = { + .set_pio_mode = cmd640_set_pio_mode, +}; #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ static int pci_conf1(void) @@ -703,14 +654,32 @@ 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 + .port_ops = &cmd640_port_ops, .pio_mask = ATA_PIO5, #endif }; +static int cmd640x_init_one(unsigned long base, unsigned long ctl) +{ + if (!request_region(base, 8, DRV_NAME)) { + printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", + DRV_NAME, base, base + 7); + return -EBUSY; + } + + if (!request_region(ctl, 1, DRV_NAME)) { + printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n", + DRV_NAME, ctl); + release_region(base, 8); + return -EBUSY; + } + + return 0; +} + /* * Probe for a cmd640 chipset, and initialize it if found. */ @@ -719,11 +688,12 @@ static int __init cmd640x_init(void) #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED int second_port_toggled = 0; #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ - int second_port_cmd640 = 0; + int second_port_cmd640 = 0, rc; const char *bus_type, *port2; unsigned int index; u8 b, cfr; u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; + hw_regs_t hw[2]; if (cmd640_vlb && probe_for_cmd640_vlb()) { bus_type = "VLB"; @@ -758,21 +728,41 @@ static int __init cmd640x_init(void) cfr = get_cmd640_reg(CFR); cmd640_chip_version = cfr & CFR_DEVREV; if (cmd640_chip_version == 0) { - printk ("ide: bad cmd640 revision: %d\n", cmd640_chip_version); + printk("ide: bad cmd640 revision: %d\n", cmd640_chip_version); return 0; } + rc = cmd640x_init_one(0x1f0, 0x3f6); + if (rc) + return rc; + + rc = cmd640x_init_one(0x170, 0x376); + if (rc) { + release_region(0x3f6, 1); + release_region(0x1f0, 8); + return rc; + } + + memset(&hw, 0, sizeof(hw)); + + ide_std_init_ports(&hw[0], 0x1f0, 0x3f6); + hw[0].irq = 14; + + ide_std_init_ports(&hw[1], 0x170, 0x376); + hw[1].irq = 15; + + printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x" + "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr); + + cmd_hwif0 = ide_find_port(); + /* * Initialize data for primary port */ - setup_device_ptrs (); - printk("%s: buggy cmd640%c interface on %s, config=0x%02x\n", - cmd_hwif0->name, 'a' + cmd640_chip_version - 1, bus_type, cfr); -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - cmd_hwif0->set_pio_mode = &cmd640_set_pio_mode; -#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ - - idx[0] = cmd_hwif0->index; + if (cmd_hwif0) { + ide_init_port_hw(cmd_hwif0, &hw[0]); + idx[0] = cmd_hwif0->index; + } /* * Ensure compatibility by always using the slowest timings @@ -784,11 +774,13 @@ static int __init cmd640x_init(void) put_cmd640_reg(CMDTIM, 0); put_cmd640_reg(BRST, 0x40); + cmd_hwif1 = ide_find_port(); + /* * Try to enable the secondary interface, if not already enabled */ - if (cmd_hwif1->noprobe || - (cmd_hwif1->drives[0].noprobe && cmd_hwif1->drives[1].noprobe)) { + if (cmd_hwif1 && + cmd_hwif1->drives[0].noprobe && cmd_hwif1->drives[1].noprobe) { port2 = "not probed"; } else { b = get_cmd640_reg(CNTRL); @@ -819,14 +811,11 @@ static int __init cmd640x_init(void) /* * Initialize data for secondary cmd640 port, if enabled */ - if (second_port_cmd640) { -#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED - cmd_hwif1->set_pio_mode = &cmd640_set_pio_mode; -#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ - + if (second_port_cmd640 && cmd_hwif1) { + ide_init_port_hw(cmd_hwif1, &hw[1]); idx[1] = cmd_hwif1->index; } - printk(KERN_INFO "%s: %sserialized, secondary interface %s\n", cmd_hwif1->name, + printk(KERN_INFO "cmd640: %sserialized, secondary interface %s\n", second_port_cmd640 ? "" : "not ", port2); /* @@ -834,35 +823,34 @@ static int __init cmd640x_init(void) * Do not unnecessarily disturb any prior BIOS setup of these. */ for (index = 0; index < (2 + (second_port_cmd640 << 1)); index++) { - ide_drive_t *drive = cmd_drives[index]; -#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 (index); - set_prefetch_mode (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 (index); - printk("cmd640: drive%d timings/prefetch(%s) preserved", - index, drive->no_io_32bit ? "off" : "on"); - display_clocks(index); + ide_drive_t *drive; + + if (index > 1) { + if (cmd_hwif1 == NULL) + continue; + drive = &cmd_hwif1->drives[index & 1]; + } else { + if (cmd_hwif0 == NULL) + continue; + drive = &cmd_hwif0->drives[index & 1]; } + +#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED + /* + * 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 */ - check_prefetch (index); + check_prefetch(drive, index); printk("cmd640: drive%d timings/prefetch(%s) preserved\n", index, drive->no_io_32bit ? "off" : "on"); #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c index edabe6299efd..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 @@ -223,7 +223,7 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed) (void) pci_write_config_byte(dev, pciU, regU); } -static int cmd648_ide_dma_end (ide_drive_t *drive) +static int cmd648_dma_end(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); unsigned long base = hwif->dma_base - (hwif->channel * 8); @@ -239,7 +239,7 @@ static int cmd648_ide_dma_end (ide_drive_t *drive) return err; } -static int cmd64x_ide_dma_end (ide_drive_t *drive) +static int cmd64x_dma_end(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = to_pci_dev(hwif->dev); @@ -256,7 +256,7 @@ static int cmd64x_ide_dma_end (ide_drive_t *drive) return err; } -static int cmd648_ide_dma_test_irq (ide_drive_t *drive) +static int cmd648_dma_test_irq(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); unsigned long base = hwif->dma_base - (hwif->channel * 8); @@ -279,7 +279,7 @@ static int cmd648_ide_dma_test_irq (ide_drive_t *drive) return 0; } -static int cmd64x_ide_dma_test_irq (ide_drive_t *drive) +static int cmd64x_dma_test_irq(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = to_pci_dev(hwif->dev); @@ -310,7 +310,7 @@ static int cmd64x_ide_dma_test_irq (ide_drive_t *drive) * event order for DMA transfers. */ -static int cmd646_1_ide_dma_end (ide_drive_t *drive) +static int cmd646_1_dma_end(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); u8 dma_stat = 0, dma_cmd = 0; @@ -370,7 +370,7 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha return 0; } -static u8 __devinit ata66_cmd64x(ide_hwif_t *hwif) +static u8 __devinit cmd64x_cable_detect(ide_hwif_t *hwif) { struct pci_dev *dev = to_pci_dev(hwif->dev); u8 bmidecsr = 0, mask = hwif->channel ? 0x02 : 0x01; @@ -385,91 +385,85 @@ static u8 __devinit ata66_cmd64x(ide_hwif_t *hwif) } } -static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - - hwif->set_pio_mode = &cmd64x_set_pio_mode; - hwif->set_dma_mode = &cmd64x_set_dma_mode; - - hwif->cable_detect = ata66_cmd64x; +static const struct ide_port_ops cmd64x_port_ops = { + .set_pio_mode = cmd64x_set_pio_mode, + .set_dma_mode = cmd64x_set_dma_mode, + .cable_detect = cmd64x_cable_detect, +}; - if (!hwif->dma_base) - return; +static const struct ide_dma_ops cmd64x_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 = cmd64x_dma_end, + .dma_test_irq = cmd64x_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; - /* - * UltraDMA only supported on PCI646U and PCI646U2, which - * correspond to revisions 0x03, 0x05 and 0x07 respectively. - * Actually, although the CMD tech support people won't - * tell me the details, the 0x03 revision cannot support - * UDMA correctly without hardware modifications, and even - * then it only works with Quantum disks due to some - * hold time assumptions in the 646U part which are fixed - * in the 646U2. - * - * So we only do UltraDMA on revision 0x05 and 0x07 chipsets. - */ - if (dev->device == PCI_DEVICE_ID_CMD_646 && dev->revision < 5) - hwif->ultra_mask = 0x00; +static const struct ide_dma_ops cmd646_rev1_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 = cmd646_1_dma_end, + .dma_test_irq = ide_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; - switch (dev->device) { - case PCI_DEVICE_ID_CMD_648: - case PCI_DEVICE_ID_CMD_649: - alt_irq_bits: - hwif->ide_dma_end = &cmd648_ide_dma_end; - hwif->ide_dma_test_irq = &cmd648_ide_dma_test_irq; - break; - case PCI_DEVICE_ID_CMD_646: - if (dev->revision == 0x01) { - hwif->ide_dma_end = &cmd646_1_ide_dma_end; - break; - } else if (dev->revision >= 0x03) - goto alt_irq_bits; - /* fall thru */ - default: - hwif->ide_dma_end = &cmd64x_ide_dma_end; - hwif->ide_dma_test_irq = &cmd64x_ide_dma_test_irq; - break; - } -} +static const struct ide_dma_ops cmd648_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 = cmd648_dma_end, + .dma_test_irq = cmd648_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; static const struct ide_port_info cmd64x_chipsets[] __devinitdata = { { /* 0 */ .name = "CMD643", .init_chipset = init_chipset_cmd64x, - .init_hwif = init_hwif_cmd64x, .enablebits = {{0x00,0x00,0x00}, {0x51,0x08,0x08}}, + .port_ops = &cmd64x_port_ops, + .dma_ops = &cmd64x_dma_ops, .host_flags = IDE_HFLAG_CLEAR_SIMPLEX | - IDE_HFLAG_ABUSE_PREFETCH | - IDE_HFLAG_BOOTABLE, + IDE_HFLAG_ABUSE_PREFETCH, .pio_mask = ATA_PIO5, .mwdma_mask = ATA_MWDMA2, .udma_mask = 0x00, /* no udma */ },{ /* 1 */ .name = "CMD646", .init_chipset = init_chipset_cmd64x, - .init_hwif = init_hwif_cmd64x, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, .chipset = ide_cmd646, - .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE, + .port_ops = &cmd64x_port_ops, + .dma_ops = &cmd648_dma_ops, + .host_flags = IDE_HFLAG_ABUSE_PREFETCH, .pio_mask = ATA_PIO5, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA2, },{ /* 2 */ .name = "CMD648", .init_chipset = init_chipset_cmd64x, - .init_hwif = init_hwif_cmd64x, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, - .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE, + .port_ops = &cmd64x_port_ops, + .dma_ops = &cmd648_dma_ops, + .host_flags = IDE_HFLAG_ABUSE_PREFETCH, .pio_mask = ATA_PIO5, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, },{ /* 3 */ .name = "CMD649", .init_chipset = init_chipset_cmd64x, - .init_hwif = init_hwif_cmd64x, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, - .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE, + .port_ops = &cmd64x_port_ops, + .dma_ops = &cmd648_dma_ops, + .host_flags = IDE_HFLAG_ABUSE_PREFETCH, .pio_mask = ATA_PIO5, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, @@ -483,12 +477,35 @@ static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_devic d = cmd64x_chipsets[idx]; - /* - * The original PCI0646 didn't have the primary channel enable bit, - * it appeared starting with PCI0646U (i.e. revision ID 3). - */ - if (idx == 1 && dev->revision < 3) - d.enablebits[0].reg = 0; + if (idx == 1) { + /* + * UltraDMA only supported on PCI646U and PCI646U2, which + * correspond to revisions 0x03, 0x05 and 0x07 respectively. + * Actually, although the CMD tech support people won't + * tell me the details, the 0x03 revision cannot support + * UDMA correctly without hardware modifications, and even + * then it only works with Quantum disks due to some + * hold time assumptions in the 646U part which are fixed + * in the 646U2. + * + * So we only do UltraDMA on revision 0x05 and 0x07 chipsets. + */ + if (dev->revision < 5) { + d.udma_mask = 0x00; + /* + * The original PCI0646 didn't have the primary + * channel enable bit, it appeared starting with + * PCI0646U (i.e. revision ID 3). + */ + if (dev->revision < 3) { + d.enablebits[0].reg = 0; + if (dev->revision == 1) + d.dma_ops = &cmd646_rev1_dma_ops; + else + d.dma_ops = &cmd64x_dma_ops; + } + } + } return ide_setup_pci_device(dev, &d); } diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c index 1c163e4ef03f..17669a434438 100644 --- a/drivers/ide/pci/cs5520.c +++ b/drivers/ide/pci/cs5520.c @@ -103,27 +103,32 @@ static void cs5520_dma_host_set(ide_drive_t *drive, int on) ide_dma_host_set(drive, on); } -static void __devinit init_hwif_cs5520(ide_hwif_t *hwif) -{ - hwif->set_pio_mode = &cs5520_set_pio_mode; - hwif->set_dma_mode = &cs5520_set_dma_mode; - - if (hwif->dma_base == 0) - return; +static const struct ide_port_ops cs5520_port_ops = { + .set_pio_mode = cs5520_set_pio_mode, + .set_dma_mode = cs5520_set_dma_mode, +}; - hwif->dma_host_set = &cs5520_dma_host_set; -} +static const struct ide_dma_ops cs5520_dma_ops = { + .dma_host_set = cs5520_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 = ide_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; #define DECLARE_CS_DEV(name_str) \ { \ .name = name_str, \ - .init_hwif = init_hwif_cs5520, \ + .port_ops = &cs5520_port_ops, \ + .dma_ops = &cs5520_dma_ops, \ .host_flags = IDE_HFLAG_ISA_PORTS | \ IDE_HFLAG_CS5520 | \ IDE_HFLAG_VDMA | \ IDE_HFLAG_NO_ATAPI_DMA | \ - IDE_HFLAG_ABUSE_SET_DMA_MODE |\ - IDE_HFLAG_BOOTABLE, \ + IDE_HFLAG_ABUSE_SET_DMA_MODE, \ .pio_mask = ATA_PIO4, \ } diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c index 941a1344820b..f5534c1ff349 100644 --- a/drivers/ide/pci/cs5530.c +++ b/drivers/ide/pci/cs5530.c @@ -228,29 +228,27 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif) unsigned long basereg; u32 d0_timings; - hwif->set_pio_mode = &cs5530_set_pio_mode; - hwif->set_dma_mode = &cs5530_set_dma_mode; - basereg = CS5530_BASEREG(hwif); d0_timings = inl(basereg + 0); if (CS5530_BAD_PIO(d0_timings)) outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 0); if (CS5530_BAD_PIO(inl(basereg + 8))) outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 8); - - if (hwif->dma_base == 0) - return; - - hwif->udma_filter = cs5530_udma_filter; } +static const struct ide_port_ops cs5530_port_ops = { + .set_pio_mode = cs5530_set_pio_mode, + .set_dma_mode = cs5530_set_dma_mode, + .udma_filter = cs5530_udma_filter, +}; + static const struct ide_port_info cs5530_chipset __devinitdata = { .name = "CS5530", .init_chipset = init_chipset_cs5530, .init_hwif = init_hwif_cs5530, + .port_ops = &cs5530_port_ops, .host_flags = IDE_HFLAG_SERIALIZE | - IDE_HFLAG_POST_SET_MODE | - IDE_HFLAG_BOOTABLE, + IDE_HFLAG_POST_SET_MODE, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA2, diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c index d7b5ea992e94..99fe91a191b8 100644 --- a/drivers/ide/pci/cs5535.c +++ b/drivers/ide/pci/cs5535.c @@ -166,27 +166,17 @@ static u8 __devinit cs5535_cable_detect(ide_hwif_t *hwif) return (bit & 1) ? ATA_CBL_PATA80 : ATA_CBL_PATA40; } -/**** - * init_hwif_cs5535 - Initialize one ide cannel - * @hwif: Channel descriptor - * - * This gets invoked by the IDE driver once for each channel. It - * performs channel-specific pre-initialization before drive probing. - * - */ -static void __devinit init_hwif_cs5535(ide_hwif_t *hwif) -{ - hwif->set_pio_mode = &cs5535_set_pio_mode; - hwif->set_dma_mode = &cs5535_set_dma_mode; - - hwif->cable_detect = cs5535_cable_detect; -} +static const struct ide_port_ops cs5535_port_ops = { + .set_pio_mode = cs5535_set_pio_mode, + .set_dma_mode = cs5535_set_dma_mode, + .cable_detect = cs5535_cable_detect, +}; static const struct ide_port_info cs5535_chipset __devinitdata = { .name = "CS5535", - .init_hwif = init_hwif_cs5535, + .port_ops = &cs5535_port_ops, .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE | - IDE_HFLAG_ABUSE_SET_DMA_MODE | IDE_HFLAG_BOOTABLE, + IDE_HFLAG_ABUSE_SET_DMA_MODE, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c index 724cbacf4e5b..77cc22c2ad45 100644 --- a/drivers/ide/pci/cy82c693.c +++ b/drivers/ide/pci/cy82c693.c @@ -6,7 +6,7 @@ * * The CY82C693 chipset is used on Digital's PC-Alpha 164SX boards. * Writing the driver was quite simple, since most of the job is - * done by the generic pci-ide support. + * done by the generic pci-ide support. * The hard part was finding the CY82C693's datasheet on Cypress's * web page :-(. But Altavista solved this problem :-). * @@ -15,12 +15,10 @@ * - I recently got a 16.8G IBM DTTA, so I was able to test it with * a large and fast disk - the results look great, so I'd say the * driver is working fine :-) - * 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 + * 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 + * - 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 * (lost interrupts) ????? @@ -110,11 +108,11 @@ typedef struct pio_clocks_s { * calc clocks using bus_speed * returns (rounded up) time in bus clocks for time in ns */ -static int calc_clk (int time, int bus_speed) +static int calc_clk(int time, int bus_speed) { int clocks; - clocks = (time*bus_speed+999)/1000 -1; + clocks = (time*bus_speed+999)/1000 - 1; if (clocks < 0) clocks = 0; @@ -132,11 +130,11 @@ static int calc_clk (int time, int bus_speed) * NOTE: for mode 0,1 and 2 drives 8-bit IDE command control registers are used * for mode 3 and 4 drives 8 and 16-bit timings are the same * - */ -static void compute_clocks (u8 pio, pio_clocks_t *p_pclk) + */ +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 @@ -158,7 +156,7 @@ static void compute_clocks (u8 pio, pio_clocks_t *p_pclk) clk1 = (clk1<<4)|clk2; /* combine active and recovery clocks */ /* note: we use the same values for 16bit IOR and IOW - * those are all the same, since I don't have other + * those are all the same, since I don't have other * timings than those from ide-lib.c */ @@ -186,7 +184,7 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode) outb(index, CY82_INDEX_PORT); data = inb(CY82_DATA_PORT); - printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n", + printk(KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n", drive->name, HWIF(drive)->channel, drive->select.b.unit, (data&0x3), ((data>>2)&1)); #endif /* CY82C693_DEBUG_LOGS */ @@ -202,7 +200,7 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode) mode & 3, single); #endif /* CY82C693_DEBUG_INFO */ - /* + /* * note: below we set the value for Bus Master IDE TimeOut Register * I'm not absolutly sure what this does, but it solved my problem * with IDE DMA and sound, so I now can play sound and work with @@ -216,8 +214,8 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode) outb(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT); outb(data, CY82_DATA_PORT); -#if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n", +#if CY82C693_DEBUG_INFO + printk(KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n", drive->name, data); #endif /* CY82C693_DEBUG_INFO */ } @@ -242,14 +240,14 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio) #if CY82C693_DEBUG_LOGS /* for debug let's show the register values */ - - if (drive->select.b.unit == 0) { + + if (drive->select.b.unit == 0) { /* - * get master drive registers + * get master drive registers * address setup control register * is 32 bit !!! - */ - pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); + */ + pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); addrCtrl &= 0x0F; /* now let's get the remaining registers */ @@ -261,7 +259,7 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio) * set slave drive registers * address setup control register * is 32 bit !!! - */ + */ pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); addrCtrl &= 0xF0; @@ -288,9 +286,9 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio) * set master drive * address setup control register * is 32 bit !!! - */ + */ pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); - + addrCtrl &= (~0xF); addrCtrl |= (unsigned int)pclk.address_time; pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl); @@ -299,14 +297,14 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio) pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, pclk.time_16r); pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, pclk.time_16w); pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, pclk.time_8); - + addrCtrl &= 0xF; } else { /* * set slave drive * address setup control register * is 32 bit !!! - */ + */ pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl); addrCtrl &= (~0xF0); @@ -320,7 +318,7 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio) addrCtrl >>= 4; addrCtrl &= 0xF; - } + } #if CY82C693_DEBUG_INFO printk(KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to " @@ -340,41 +338,41 @@ static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const c #ifdef CY82C693_SETDMA_CLOCK u8 data = 0; -#endif /* CY82C693_SETDMA_CLOCK */ +#endif /* CY82C693_SETDMA_CLOCK */ /* write info about this verion of the driver */ printk(KERN_INFO CY82_VERSION "\n"); #ifdef CY82C693_SETDMA_CLOCK /* okay let's set the DMA clock speed */ - - outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT); - data = inb(CY82_DATA_PORT); + + outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT); + data = inb(CY82_DATA_PORT); #if CY82C693_DEBUG_INFO printk(KERN_INFO "%s: Peripheral Configuration Register: 0x%X\n", name, data); #endif /* CY82C693_DEBUG_INFO */ - /* + /* * for some reason sometimes the DMA controller * speed is set to ATCLK/2 ???? - we fix this here - * + * * note: i don't know what causes this strange behaviour, * but even changing the dma speed doesn't solve it :-( - * the ide performance is still only half the normal speed - * + * the ide performance is still only half the normal speed + * * if anybody knows what goes wrong with my machine, please * let me know - ASK - */ + */ data |= 0x03; - outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT); - outb(data, CY82_DATA_PORT); + outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT); + outb(data, CY82_DATA_PORT); #if CY82C693_DEBUG_INFO - printk (KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n", + printk(KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n", name, data); #endif /* CY82C693_DEBUG_INFO */ @@ -382,15 +380,6 @@ static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const c return 0; } -/* - * the init function - called for each ide channel once - */ -static void __devinit init_hwif_cy82c693(ide_hwif_t *hwif) -{ - hwif->set_pio_mode = &cy82c693_set_pio_mode; - hwif->set_dma_mode = &cy82c693_set_dma_mode; -} - static void __devinit init_iops_cy82c693(ide_hwif_t *hwif) { static ide_hwif_t *primary; @@ -404,14 +393,18 @@ static void __devinit init_iops_cy82c693(ide_hwif_t *hwif) } } +static const struct ide_port_ops cy82c693_port_ops = { + .set_pio_mode = cy82c693_set_pio_mode, + .set_dma_mode = cy82c693_set_dma_mode, +}; + static const struct ide_port_info cy82c693_chipset __devinitdata = { .name = "CY82C693", .init_chipset = init_chipset_cy82c693, .init_iops = init_iops_cy82c693, - .init_hwif = init_hwif_cy82c693, + .port_ops = &cy82c693_port_ops, .chipset = ide_cy82c693, - .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_CY82C693 | - IDE_HFLAG_BOOTABLE, + .host_flags = IDE_HFLAG_SINGLE, .pio_mask = ATA_PIO4, .swdma_mask = ATA_SWDMA2, .mwdma_mask = ATA_MWDMA2, @@ -424,7 +417,7 @@ static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_dev /* CY82C693 is more than only a IDE controller. Function 1 is primary IDE channel, function 2 - secondary. */ - if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && + if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && PCI_FUNC(dev->devfn) == 1) { dev2 = pci_get_slot(dev->bus, dev->devfn + 1); ret = ide_setup_pci_devices(dev, dev2, &cy82c693_chipset); diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c index 3f9cd64c26a6..b9e457996d0e 100644 --- a/drivers/ide/pci/delkin_cb.c +++ b/drivers/ide/pci/delkin_cb.c @@ -43,6 +43,10 @@ static const u8 setup[] = { 0x00, 0x00, 0x00, 0x00, 0xa4, 0x83, 0x02, 0x13, }; +static const struct ide_port_ops delkin_cb_port_ops = { + .quirkproc = ide_undecoded_slave, +}; + static int __devinit delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) { @@ -71,26 +75,21 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) if (setup[i]) outb(setup[i], base + i); } - pci_release_regions(dev); /* IDE layer handles regions itself */ memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw, base + 0x10, base + 0x1e); hw.irq = dev->irq; hw.chipset = ide_pci; /* this enables IRQ sharing */ - hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]); + hwif = ide_find_port(); if (hwif == NULL) goto out_disable; i = hwif->index; - if (hwif->present) - ide_unregister(i, 0, 0); - else if (!hwif->hold) - ide_init_port_data(hwif, i); - + ide_init_port_data(hwif, i); ide_init_port_hw(hwif, &hw); - hwif->quirkproc = &ide_undecoded_slave; + hwif->port_ops = &delkin_cb_port_ops; idx[0] = i; @@ -110,6 +109,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) out_disable: printk(KERN_ERR "delkin_cb: no IDE devices found\n"); + pci_release_regions(dev); pci_disable_device(dev); return -ENODEV; } @@ -119,9 +119,9 @@ delkin_cb_remove (struct pci_dev *dev) { ide_hwif_t *hwif = pci_get_drvdata(dev); - if (hwif) - ide_unregister(hwif->index, 0, 0); + ide_unregister(hwif); + pci_release_regions(dev); pci_disable_device(dev); } diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index 7fd83a9d4dee..041720e22762 100644 --- a/drivers/ide/pci/generic.c +++ b/drivers/ide/pci/generic.c @@ -38,8 +38,7 @@ MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE st { \ .name = name_str, \ .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | \ - extra_flags | \ - IDE_HFLAG_BOOTABLE, \ + extra_flags, \ .swdma_mask = ATA_SWDMA2, \ .mwdma_mask = ATA_MWDMA2, \ .udma_mask = ATA_UDMA6, \ @@ -50,9 +49,8 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = { { /* 1 */ .name = "NS87410", - .enablebits = {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | - IDE_HFLAG_BOOTABLE, + .enablebits = { {0x43, 0x08, 0x08}, {0x47, 0x08, 0x08} }, + .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, .swdma_mask = ATA_SWDMA2, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, @@ -99,7 +97,7 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = { * Called when the PCI registration layer (or the IDE initialization) * finds a device matching our IDE device tables. */ - + static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_device_id *id) { const struct ide_port_info *d = &generic_chipsets[id->driver_data]; diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c index 9f01da46b016..84c36c117194 100644 --- a/drivers/ide/pci/hpt34x.c +++ b/drivers/ide/pci/hpt34x.c @@ -115,11 +115,10 @@ static unsigned int __devinit init_chipset_hpt34x(struct pci_dev *dev, const cha return dev->irq; } -static void __devinit init_hwif_hpt34x(ide_hwif_t *hwif) -{ - hwif->set_pio_mode = &hpt34x_set_pio_mode; - hwif->set_dma_mode = &hpt34x_set_mode; -} +static const struct ide_port_ops hpt34x_port_ops = { + .set_pio_mode = hpt34x_set_pio_mode, + .set_dma_mode = hpt34x_set_mode, +}; #define IDE_HFLAGS_HPT34X \ (IDE_HFLAG_NO_ATAPI_DMA | \ @@ -131,16 +130,14 @@ static const struct ide_port_info hpt34x_chipsets[] __devinitdata = { { /* 0 */ .name = "HPT343", .init_chipset = init_chipset_hpt34x, - .init_hwif = init_hwif_hpt34x, - .extra = 16, - .host_flags = IDE_HFLAGS_HPT34X, + .port_ops = &hpt34x_port_ops, + .host_flags = IDE_HFLAGS_HPT34X | IDE_HFLAG_NON_BOOTABLE, .pio_mask = ATA_PIO5, }, { /* 1 */ .name = "HPT345", .init_chipset = init_chipset_hpt34x, - .init_hwif = init_hwif_hpt34x, - .extra = 16, + .port_ops = &hpt34x_port_ops, .host_flags = IDE_HFLAGS_HPT34X | IDE_HFLAG_OFF_BOARD, .pio_mask = ATA_PIO5, #ifdef CONFIG_HPT34X_AUTODMA diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 6357bb6269ab..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), - IDE_CONTROL_REG); + hwif->io_ports.ctl_addr); } /* @@ -776,7 +776,7 @@ static void hpt366_dma_lost_irq(ide_drive_t *drive) pci_read_config_byte(dev, 0x52, &mcr3); pci_read_config_byte(dev, 0x5a, &scr1); printk("%s: (%s) mcr1=0x%02x, mcr3=0x%02x, scr1=0x%02x\n", - drive->name, __FUNCTION__, mcr1, mcr3, scr1); + drive->name, __func__, mcr1, mcr3, scr1); if (scr1 & 0x10) pci_write_config_byte(dev, 0x5a, scr1 & ~0x10); ide_dma_lost_irq(drive); @@ -808,7 +808,7 @@ static void hpt370_irq_timeout(ide_drive_t *drive) hpt370_clear_engine(drive); } -static void hpt370_ide_dma_start(ide_drive_t *drive) +static void hpt370_dma_start(ide_drive_t *drive) { #ifdef HPT_RESET_STATE_ENGINE hpt370_clear_engine(drive); @@ -816,7 +816,7 @@ static void hpt370_ide_dma_start(ide_drive_t *drive) ide_dma_start(drive); } -static int hpt370_ide_dma_end(ide_drive_t *drive) +static int hpt370_dma_end(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); u8 dma_stat = inb(hwif->dma_status); @@ -838,7 +838,7 @@ static void hpt370_dma_timeout(ide_drive_t *drive) } /* returns 1 if DMA IRQ issued, 0 otherwise */ -static int hpt374_ide_dma_test_irq(ide_drive_t *drive) +static int hpt374_dma_test_irq(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = to_pci_dev(hwif->dev); @@ -858,11 +858,11 @@ static int hpt374_ide_dma_test_irq(ide_drive_t *drive) if (!drive->waiting_for_dma) printk(KERN_WARNING "%s: (%s) called while not waiting\n", - drive->name, __FUNCTION__); + drive->name, __func__); return 0; } -static int hpt374_ide_dma_end(ide_drive_t *drive) +static int hpt374_dma_end(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = to_pci_dev(hwif->dev); @@ -929,64 +929,6 @@ static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq) hpt3xxn_set_clock(HWIF(drive), rq_data_dir(rq) ? 0x23 : 0x21); } -/* - * Set/get power state for a drive. - * NOTE: affects both drives on each channel. - * - * When we turn the power back on, we need to re-initialize things. - */ -#define TRISTATE_BIT 0x8000 - -static int hpt3xx_busproc(ide_drive_t *drive, int state) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - u8 mcr_addr = hwif->select_data + 2; - u8 resetmask = hwif->channel ? 0x80 : 0x40; - u8 bsr2 = 0; - u16 mcr = 0; - - hwif->bus_state = state; - - /* Grab the status. */ - pci_read_config_word(dev, mcr_addr, &mcr); - pci_read_config_byte(dev, 0x59, &bsr2); - - /* - * Set the state. We don't set it if we don't need to do so. - * Make sure that the drive knows that it has failed if it's off. - */ - switch (state) { - case BUSSTATE_ON: - if (!(bsr2 & resetmask)) - return 0; - hwif->drives[0].failures = hwif->drives[1].failures = 0; - - pci_write_config_byte(dev, 0x59, bsr2 & ~resetmask); - pci_write_config_word(dev, mcr_addr, mcr & ~TRISTATE_BIT); - return 0; - case BUSSTATE_OFF: - if ((bsr2 & resetmask) && !(mcr & TRISTATE_BIT)) - return 0; - mcr &= ~TRISTATE_BIT; - break; - case BUSSTATE_TRISTATE: - if ((bsr2 & resetmask) && (mcr & TRISTATE_BIT)) - return 0; - mcr |= TRISTATE_BIT; - break; - default: - return -EINVAL; - } - - hwif->drives[0].failures = hwif->drives[0].max_failures + 1; - hwif->drives[1].failures = hwif->drives[1].max_failures + 1; - - pci_write_config_word(dev, mcr_addr, mcr); - pci_write_config_byte(dev, 0x59, bsr2 | resetmask); - return 0; -} - /** * hpt37x_calibrate_dpll - calibrate the DPLL * @dev: PCI device @@ -1329,18 +1271,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) /* Cache the channel's MISC. control registers' offset */ hwif->select_data = hwif->channel ? 0x54 : 0x50; - hwif->set_pio_mode = &hpt3xx_set_pio_mode; - hwif->set_dma_mode = &hpt3xx_set_mode; - - hwif->quirkproc = &hpt3xx_quirkproc; - hwif->maskproc = &hpt3xx_maskproc; - hwif->busproc = &hpt3xx_busproc; - - hwif->udma_filter = &hpt3xx_udma_filter; - hwif->mdma_filter = &hpt3xx_mdma_filter; - - hwif->cable_detect = hpt3xx_cable_detect; - /* * HPT3xxN chips have some complications: * @@ -1382,29 +1312,19 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) if (new_mcr != old_mcr) pci_write_config_byte(dev, hwif->select_data + 1, new_mcr); - - if (hwif->dma_base == 0) - return; - - if (chip_type >= HPT374) { - hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; - hwif->ide_dma_end = &hpt374_ide_dma_end; - } else if (chip_type >= HPT370) { - hwif->dma_start = &hpt370_ide_dma_start; - hwif->ide_dma_end = &hpt370_ide_dma_end; - hwif->dma_timeout = &hpt370_dma_timeout; - } else - hwif->dma_lost_irq = &hpt366_dma_lost_irq; } -static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) +static int __devinit init_dma_hpt366(ide_hwif_t *hwif, + const struct ide_port_info *d) { struct pci_dev *dev = to_pci_dev(hwif->dev); - u8 masterdma = 0, slavedma = 0; - u8 dma_new = 0, dma_old = 0; - unsigned long flags; + unsigned long flags, base = ide_pci_dma_base(hwif, d); + u8 dma_old, dma_new, masterdma = 0, slavedma = 0; - dma_old = inb(dmabase + 2); + if (base == 0 || ide_pci_set_master(dev, d->name) < 0) + return -1; + + dma_old = inb(base + 2); local_irq_save(flags); @@ -1415,11 +1335,21 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) if (masterdma & 0x30) dma_new |= 0x20; if ( slavedma & 0x30) dma_new |= 0x40; if (dma_new != dma_old) - outb(dma_new, dmabase + 2); + outb(dma_new, base + 2); local_irq_restore(flags); - ide_setup_dma(hwif, dmabase); + printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx\n", + hwif->name, base, base + 7); + + hwif->extra_base = base + (hwif->channel ? 8 : 16); + + if (ide_allocate_dma_engine(hwif)) + return -1; + + ide_setup_dma(hwif, base); + + return 0; } static void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2) @@ -1475,6 +1405,49 @@ static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2) IDE_HFLAG_ABUSE_SET_DMA_MODE | \ IDE_HFLAG_OFF_BOARD) +static const struct ide_port_ops hpt3xx_port_ops = { + .set_pio_mode = hpt3xx_set_pio_mode, + .set_dma_mode = hpt3xx_set_mode, + .quirkproc = hpt3xx_quirkproc, + .maskproc = hpt3xx_maskproc, + .mdma_filter = hpt3xx_mdma_filter, + .udma_filter = hpt3xx_udma_filter, + .cable_detect = hpt3xx_cable_detect, +}; + +static const struct ide_dma_ops hpt37x_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 = hpt374_dma_end, + .dma_test_irq = hpt374_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; + +static const struct ide_dma_ops hpt370_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ide_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = hpt370_dma_start, + .dma_end = hpt370_dma_end, + .dma_test_irq = ide_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = hpt370_dma_timeout, +}; + +static const struct ide_dma_ops hpt36x_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 = ide_dma_test_irq, + .dma_lost_irq = hpt366_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; + static const struct ide_port_info hpt366_chipsets[] __devinitdata = { { /* 0 */ .name = "HPT36x", @@ -1488,7 +1461,8 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = { * Bit 4 is for the primary channel, bit 5 for the secondary. */ .enablebits = {{0x50,0x10,0x10}, {0x54,0x04,0x04}}, - .extra = 240, + .port_ops = &hpt3xx_port_ops, + .dma_ops = &hpt36x_dma_ops, .host_flags = IDE_HFLAGS_HPT3XX | IDE_HFLAG_SINGLE, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, @@ -1498,7 +1472,8 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = { .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, - .extra = 240, + .port_ops = &hpt3xx_port_ops, + .dma_ops = &hpt37x_dma_ops, .host_flags = IDE_HFLAGS_HPT3XX, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, @@ -1508,7 +1483,8 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = { .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, - .extra = 240, + .port_ops = &hpt3xx_port_ops, + .dma_ops = &hpt37x_dma_ops, .host_flags = IDE_HFLAGS_HPT3XX, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, @@ -1518,7 +1494,8 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = { .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, - .extra = 240, + .port_ops = &hpt3xx_port_ops, + .dma_ops = &hpt37x_dma_ops, .host_flags = IDE_HFLAGS_HPT3XX, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, @@ -1529,7 +1506,8 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = { .init_dma = init_dma_hpt366, .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .udma_mask = ATA_UDMA5, - .extra = 240, + .port_ops = &hpt3xx_port_ops, + .dma_ops = &hpt37x_dma_ops, .host_flags = IDE_HFLAGS_HPT3XX, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, @@ -1539,7 +1517,8 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = { .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, - .extra = 240, + .port_ops = &hpt3xx_port_ops, + .dma_ops = &hpt37x_dma_ops, .host_flags = IDE_HFLAGS_HPT3XX, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, @@ -1602,6 +1581,10 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic d.name = info->chip_name; d.udma_mask = info->udma_mask; + /* fixup ->dma_ops for HPT370/HPT370A */ + if (info == &hpt370 || info == &hpt370a) + d.dma_ops = &hpt370_dma_ops; + pci_set_drvdata(dev, (void *)info); if (info == &hpt36x || info == &hpt374) @@ -1616,7 +1599,7 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic hpt374_init(dev, dev2); else { if (hpt36x_init(dev, dev2)) - d.host_flags |= IDE_HFLAG_BOOTABLE; + d.host_flags &= ~IDE_HFLAG_NON_BOOTABLE; } ret = ide_setup_pci_devices(dev, dev2, &d); diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c index e3427eaab430..9053c8771e6e 100644 --- a/drivers/ide/pci/it8213.c +++ b/drivers/ide/pci/it8213.c @@ -35,7 +35,7 @@ static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio) static DEFINE_SPINLOCK(tune_lock); int control = 0; - static const u8 timings[][2]= { + static const u8 timings[][2] = { { 0, 0 }, { 0, 0 }, { 1, 0 }, @@ -105,11 +105,10 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed) if (!(reg48 & u_flag)) pci_write_config_byte(dev, 0x48, reg48 | u_flag); - if (speed >= XFER_UDMA_5) { + if (speed >= XFER_UDMA_5) pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag); - } else { + else pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); - } if ((reg4a & a_speed) != u_speed) pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed); @@ -150,29 +149,18 @@ static u8 __devinit it8213_cable_detect(ide_hwif_t *hwif) return (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; } -/** - * init_hwif_it8213 - set up hwif structs - * @hwif: interface to set up - * - * We do the basic set up of the interface structure. - */ - -static void __devinit init_hwif_it8213(ide_hwif_t *hwif) -{ - hwif->set_dma_mode = &it8213_set_dma_mode; - hwif->set_pio_mode = &it8213_set_pio_mode; - - hwif->cable_detect = it8213_cable_detect; -} - +static const struct ide_port_ops it8213_port_ops = { + .set_pio_mode = it8213_set_pio_mode, + .set_dma_mode = it8213_set_dma_mode, + .cable_detect = it8213_cable_detect, +}; #define DECLARE_ITE_DEV(name_str) \ { \ .name = name_str, \ - .init_hwif = init_hwif_it8213, \ - .enablebits = {{0x41,0x80,0x80}}, \ - .host_flags = IDE_HFLAG_SINGLE | \ - IDE_HFLAG_BOOTABLE, \ + .enablebits = { {0x41, 0x80, 0x80} }, \ + .port_ops = &it8213_port_ops, \ + .host_flags = IDE_HFLAG_SINGLE, \ .pio_mask = ATA_PIO4, \ .swdma_mask = ATA_SWDMA2_ONLY, \ .mwdma_mask = ATA_MWDMA12_ONLY, \ diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c index 1597f0cc1bf1..6ab04115286b 100644 --- a/drivers/ide/pci/it821x.c +++ b/drivers/ide/pci/it821x.c @@ -418,7 +418,7 @@ static void it821x_set_dma_mode(ide_drive_t *drive, const u8 speed) } /** - * ata66_it821x - check for 80 pin cable + * it821x_cable_detect - cable detection * @hwif: interface to check * * Check for the presence of an ATA66 capable cable on the @@ -426,7 +426,7 @@ static void it821x_set_dma_mode(ide_drive_t *drive, const u8 speed) * the needed logic onboard. */ -static u8 __devinit ata66_it821x(ide_hwif_t *hwif) +static u8 __devinit it821x_cable_detect(ide_hwif_t *hwif) { /* The reference driver also only does disk side */ return ATA_CBL_PATA80; @@ -511,6 +511,11 @@ static void __devinit it821x_quirkproc(ide_drive_t *drive) } +static struct ide_dma_ops it821x_pass_through_dma_ops = { + .dma_start = it821x_dma_start, + .dma_end = it821x_dma_end, +}; + /** * init_hwif_it821x - set up hwif structs * @hwif: interface to set up @@ -523,16 +528,10 @@ static void __devinit it821x_quirkproc(ide_drive_t *drive) static void __devinit init_hwif_it821x(ide_hwif_t *hwif) { struct pci_dev *dev = to_pci_dev(hwif->dev); - struct it821x_dev *idev = kzalloc(sizeof(struct it821x_dev), GFP_KERNEL); + struct it821x_dev **itdevs = (struct it821x_dev **)pci_get_drvdata(dev); + struct it821x_dev *idev = itdevs[hwif->channel]; u8 conf; - hwif->quirkproc = &it821x_quirkproc; - - if (idev == NULL) { - printk(KERN_ERR "it821x: out of memory, falling back to legacy behaviour.\n"); - return; - } - ide_set_hwifdata(hwif, idev); pci_read_config_byte(dev, 0x50, &conf); @@ -567,17 +566,11 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif) } if (idev->smart == 0) { - hwif->set_pio_mode = &it821x_set_pio_mode; - hwif->set_dma_mode = &it821x_set_dma_mode; - /* MWDMA/PIO clock switching for pass through mode */ - hwif->dma_start = &it821x_dma_start; - hwif->ide_dma_end = &it821x_dma_end; + hwif->dma_ops = &it821x_pass_through_dma_ops; } else hwif->host_flags |= IDE_HFLAG_NO_SET_MODE; - hwif->cable_detect = ata66_it821x; - if (hwif->dma_base == 0) return; @@ -617,13 +610,20 @@ static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const cha return 0; } +static const struct ide_port_ops it821x_port_ops = { + /* it821x_set_{pio,dma}_mode() are only used in pass-through mode */ + .set_pio_mode = it821x_set_pio_mode, + .set_dma_mode = it821x_set_dma_mode, + .quirkproc = it821x_quirkproc, + .cable_detect = it821x_cable_detect, +}; #define DECLARE_ITE_DEV(name_str) \ { \ .name = name_str, \ .init_chipset = init_chipset_it821x, \ .init_hwif = init_hwif_it821x, \ - .host_flags = IDE_HFLAG_BOOTABLE, \ + .port_ops = &it821x_port_ops, \ .pio_mask = ATA_PIO4, \ } @@ -642,6 +642,22 @@ static const struct ide_port_info it821x_chipsets[] __devinitdata = { static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id) { + struct it821x_dev *itdevs[2] = { NULL, NULL} , *itdev; + unsigned int i; + + for (i = 0; i < 2; i++) { + itdev = kzalloc(sizeof(*itdev), GFP_KERNEL); + if (itdev == NULL) { + kfree(itdevs[0]); + printk(KERN_ERR "it821x: out of memory\n"); + return -ENOMEM; + } + + itdevs[i] = itdev; + } + + pci_set_drvdata(dev, itdevs); + return ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]); } @@ -667,7 +683,7 @@ static int __init it821x_ide_init(void) module_init(it821x_ide_init); module_param_named(noraid, it8212_noraid, int, S_IRUGO); -MODULE_PARM_DESC(it8212_noraid, "Force card into bypass mode"); +MODULE_PARM_DESC(noraid, "Force card into bypass mode"); MODULE_AUTHOR("Alan Cox"); MODULE_DESCRIPTION("PCI driver module for the ITE 821x"); diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c index a56bcb4f22f4..96ef7394f283 100644 --- a/drivers/ide/pci/jmicron.c +++ b/drivers/ide/pci/jmicron.c @@ -19,13 +19,13 @@ typedef enum { } port_type; /** - * ata66_jmicron - Cable check + * jmicron_cable_detect - cable detection * @hwif: IDE port * * Returns the cable type. */ -static u8 __devinit ata66_jmicron(ide_hwif_t *hwif) +static u8 __devinit jmicron_cable_detect(ide_hwif_t *hwif) { struct pci_dev *pdev = to_pci_dev(hwif->dev); @@ -63,8 +63,7 @@ static u8 __devinit ata66_jmicron(ide_hwif_t *hwif) * actually do our cable checking etc. Thankfully we don't need * to do the plumbing for other cases. */ - switch (port_map[port]) - { + switch (port_map[port]) { case PORT_PATA0: if (control & (1 << 3)) /* 40/80 pin primary */ return ATA_CBL_PATA40; @@ -96,26 +95,16 @@ static void jmicron_set_dma_mode(ide_drive_t *drive, const u8 mode) { } -/** - * init_hwif_jmicron - set up hwif structs - * @hwif: interface to set up - * - * Minimal set up is required for the Jmicron hardware. - */ - -static void __devinit init_hwif_jmicron(ide_hwif_t *hwif) -{ - hwif->set_pio_mode = &jmicron_set_pio_mode; - hwif->set_dma_mode = &jmicron_set_dma_mode; - - hwif->cable_detect = ata66_jmicron; -} +static const struct ide_port_ops jmicron_port_ops = { + .set_pio_mode = jmicron_set_pio_mode, + .set_dma_mode = jmicron_set_dma_mode, + .cable_detect = jmicron_cable_detect, +}; static const struct ide_port_info jmicron_chipset __devinitdata = { .name = "JMB", - .init_hwif = init_hwif_jmicron, - .host_flags = IDE_HFLAG_BOOTABLE, .enablebits = { { 0x40, 0x01, 0x01 }, { 0x40, 0x10, 0x10 } }, + .port_ops = &jmicron_port_ops, .pio_mask = ATA_PIO5, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c index bf0d3b2931f1..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; } @@ -150,7 +194,7 @@ static void ns87415_selectproc (ide_drive_t *drive) ns87415_prepare_drive (drive, drive->using_dma); } -static int ns87415_ide_dma_end (ide_drive_t *drive) +static int ns87415_dma_end(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); u8 dma_stat = 0, dma_cmd = 0; @@ -170,7 +214,7 @@ static int ns87415_ide_dma_end (ide_drive_t *drive) return (dma_stat & 7) != 4; } -static int ns87415_ide_dma_setup(ide_drive_t *drive) +static int ns87415_dma_setup(ide_drive_t *drive) { /* select DMA xfer */ ns87415_prepare_drive(drive, 1); @@ -181,6 +225,10 @@ static int ns87415_ide_dma_setup(ide_drive_t *drive) return 1; } +#ifndef ide_default_irq +#define ide_default_irq(irq) 0 +#endif + static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) { struct pci_dev *dev = to_pci_dev(hwif->dev); @@ -191,8 +239,6 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) u8 stat; #endif - hwif->selectproc = &ns87415_selectproc; - /* * We cannot probe for IRQ: both ports share common IRQ on INTA. * Also, leave IRQ masked during drive probing, to prevent infinite @@ -229,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); @@ -242,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 */ @@ -250,19 +296,33 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) return; outb(0x60, hwif->dma_status); - hwif->dma_setup = &ns87415_ide_dma_setup; - hwif->ide_dma_end = &ns87415_ide_dma_end; } +static const struct ide_port_ops ns87415_port_ops = { + .selectproc = ns87415_selectproc, +}; + +static const struct ide_dma_ops ns87415_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ns87415_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = ide_dma_start, + .dma_end = ns87415_dma_end, + .dma_test_irq = ide_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; + static const struct ide_port_info ns87415_chipset __devinitdata = { .name = "NS87415", #ifdef CONFIG_SUPERIO .init_iops = init_iops_ns87415, #endif .init_hwif = init_hwif_ns87415, + .port_ops = &ns87415_port_ops, + .dma_ops = &ns87415_dma_ops, .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | - IDE_HFLAG_NO_ATAPI_DMA | - IDE_HFLAG_BOOTABLE, + IDE_HFLAG_NO_ATAPI_DMA, }; static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id) diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c index 46e8748f507e..6e99080497bf 100644 --- a/drivers/ide/pci/opti621.c +++ b/drivers/ide/pci/opti621.c @@ -53,13 +53,12 @@ * 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. + * by Jaromir Koutek, for 2.1.8. * Initial version of driver. - * + * * Version 0.2 * Number 0.2 skipped. * @@ -75,7 +74,7 @@ * by Jaromir Koutek * Updates for use with (again) new IDE block driver. * Update of documentation. - * + * * Version 0.6, Jan 2, 1999 * by Jaromir Koutek * Reversed to version 0.3 of the driver, because @@ -208,29 +207,34 @@ typedef struct pio_clocks_s { 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(); - - adr_setup = ide_pio_timings[pio].setup_time; - data_pls = ide_pio_timings[pio].active_time; - clks->address_time = cmpt_clk(adr_setup, bus_speed); - clks->data_time = cmpt_clk(data_pls, bus_speed); - clks->recovery_time = cmpt_clk(ide_pio_timings[pio].cycle_time - - adr_setup-data_pls, bus_speed); - if (clks->address_time<1) clks->address_time = 1; - if (clks->address_time>4) clks->address_time = 4; - if (clks->data_time<1) clks->data_time = 1; - if (clks->data_time>16) clks->data_time = 16; - if (clks->recovery_time<2) clks->recovery_time = 2; - if (clks->recovery_time>17) clks->recovery_time = 17; + if (pio != PIO_NOT_EXIST) { + int adr_setup, data_pls; + 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; + clks->address_time = cmpt_clk(adr_setup, bus_speed); + clks->data_time = cmpt_clk(data_pls, bus_speed); + clks->recovery_time = cmpt_clk(ide_pio_timings[pio].cycle_time + - adr_setup-data_pls, bus_speed); + if (clks->address_time < 1) + clks->address_time = 1; + if (clks->address_time > 4) + clks->address_time = 4; + if (clks->data_time < 1) + clks->data_time = 1; + if (clks->data_time > 16) + clks->data_time = 16; + if (clks->recovery_time < 2) + clks->recovery_time = 2; + if (clks->recovery_time > 17) + clks->recovery_time = 17; } else { clks->address_time = 1; clks->data_time = 1; clks->recovery_time = 2; /* minimal values */ } - } static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) @@ -247,8 +251,8 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) /* sets drive->drive_data for both drives */ compute_pios(drive, pio); - pio1 = hwif->drives[0].drive_data; - pio2 = hwif->drives[1].drive_data; + pio1 = hwif->drives[0].drive_data; + pio2 = hwif->drives[1].drive_data; compute_clocks(pio1, &first); compute_clocks(pio2, &second); @@ -275,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); @@ -321,31 +325,25 @@ static void __devinit opti621_port_init_devs(ide_hwif_t *hwif) hwif->drives[1].drive_data = PIO_DONT_KNOW; } -/* - * init_hwif_opti621() is called once for each hwif found at boot. - */ -static void __devinit init_hwif_opti621 (ide_hwif_t *hwif) -{ - hwif->port_init_devs = opti621_port_init_devs; - hwif->set_pio_mode = &opti621_set_pio_mode; -} +static const struct ide_port_ops opti621_port_ops = { + .port_init_devs = opti621_port_init_devs, + .set_pio_mode = opti621_set_pio_mode, +}; static const struct ide_port_info opti621_chipsets[] __devinitdata = { { /* 0 */ .name = "OPTI621", - .init_hwif = init_hwif_opti621, - .enablebits = {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | - IDE_HFLAG_BOOTABLE, + .enablebits = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} }, + .port_ops = &opti621_port_ops, + .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, .pio_mask = ATA_PIO3, .swdma_mask = ATA_SWDMA2, .mwdma_mask = ATA_MWDMA2, - },{ /* 1 */ + }, { /* 1 */ .name = "OPTI621X", - .init_hwif = init_hwif_opti621, - .enablebits = {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, - .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | - IDE_HFLAG_BOOTABLE, + .enablebits = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} }, + .port_ops = &opti621_port_ops, + .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA, .pio_mask = ATA_PIO3, .swdma_mask = ATA_SWDMA2, .mwdma_mask = ATA_MWDMA2, diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index 1c8cb7797a4a..070df8ab3b21 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -34,7 +34,7 @@ #undef DEBUG #ifdef DEBUG -#define DBG(fmt, args...) printk("%s: " fmt, __FUNCTION__, ## args) +#define DBG(fmt, args...) printk("%s: " fmt, __func__, ## args) #else #define DBG(fmt, args...) #endif @@ -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); } @@ -442,17 +442,6 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha return dev->irq; } -static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif) -{ - hwif->set_pio_mode = &pdcnew_set_pio_mode; - hwif->set_dma_mode = &pdcnew_set_dma_mode; - - hwif->quirkproc = &pdcnew_quirkproc; - hwif->resetproc = &pdcnew_reset; - - hwif->cable_detect = pdcnew_cable_detect; -} - static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev) { struct pci_dev *dev2; @@ -476,11 +465,19 @@ static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev) return NULL; } +static const struct ide_port_ops pdcnew_port_ops = { + .set_pio_mode = pdcnew_set_pio_mode, + .set_dma_mode = pdcnew_set_dma_mode, + .quirkproc = pdcnew_quirkproc, + .resetproc = pdcnew_reset, + .cable_detect = pdcnew_cable_detect, +}; + #define DECLARE_PDCNEW_DEV(name_str, udma) \ { \ .name = name_str, \ .init_chipset = init_chipset_pdcnew, \ - .init_hwif = init_hwif_pdc202new, \ + .port_ops = &pdcnew_port_ops, \ .host_flags = IDE_HFLAG_POST_SET_MODE | \ IDE_HFLAG_ERROR_STOPS_FIFO | \ IDE_HFLAG_OFF_BOARD, \ diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c index 150422ec3cfa..fca89eda5c02 100644 --- a/drivers/ide/pci/pdc202xx_old.c +++ b/drivers/ide/pci/pdc202xx_old.c @@ -115,7 +115,7 @@ static void pdc202xx_set_pio_mode(ide_drive_t *drive, const u8 pio) pdc202xx_set_mode(drive, XFER_PIO_0 + pio); } -static u8 __devinit pdc2026x_old_cable_detect(ide_hwif_t *hwif) +static u8 __devinit pdc2026x_cable_detect(ide_hwif_t *hwif) { struct pci_dev *dev = to_pci_dev(hwif->dev); u16 CIS, mask = hwif->channel ? (1 << 11) : (1 << 10); @@ -163,7 +163,7 @@ static void pdc202xx_quirkproc(ide_drive_t *drive) drive->quirk_list = 0; } -static void pdc202xx_old_ide_dma_start(ide_drive_t *drive) +static void pdc202xx_dma_start(ide_drive_t *drive) { if (drive->current_speed > XFER_UDMA_2) pdc_old_enable_66MHz_clock(drive->hwif); @@ -185,7 +185,7 @@ static void pdc202xx_old_ide_dma_start(ide_drive_t *drive) ide_dma_start(drive); } -static int pdc202xx_old_ide_dma_end(ide_drive_t *drive) +static int pdc202xx_dma_end(ide_drive_t *drive) { if (drive->media != ide_disk || drive->addressing == 1) { ide_hwif_t *hwif = HWIF(drive); @@ -202,7 +202,7 @@ static int pdc202xx_old_ide_dma_end(ide_drive_t *drive) return __ide_dma_end(drive); } -static int pdc202xx_old_ide_dma_test_irq(ide_drive_t *drive) +static int pdc202xx_dma_test_irq(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); unsigned long high_16 = hwif->extra_base - 16; @@ -226,26 +226,6 @@ somebody_else: return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ } -static void pdc202xx_dma_lost_irq(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - - if (hwif->resetproc != NULL) - hwif->resetproc(drive); - - ide_dma_lost_irq(drive); -} - -static void pdc202xx_dma_timeout(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - - if (hwif->resetproc != NULL) - hwif->resetproc(drive); - - ide_dma_timeout(drive); -} - static void pdc202xx_reset_host (ide_hwif_t *hwif) { unsigned long high_16 = hwif->extra_base - 16; @@ -271,68 +251,46 @@ static void pdc202xx_reset (ide_drive_t *drive) ide_set_max_pio(drive); } -static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev, - const char *name) +static void pdc202xx_dma_lost_irq(ide_drive_t *drive) { - return dev->irq; + pdc202xx_reset(drive); + ide_dma_lost_irq(drive); } -static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif) +static void pdc202xx_dma_timeout(ide_drive_t *drive) { - struct pci_dev *dev = to_pci_dev(hwif->dev); - - hwif->set_pio_mode = &pdc202xx_set_pio_mode; - hwif->set_dma_mode = &pdc202xx_set_mode; - - hwif->quirkproc = &pdc202xx_quirkproc; - - if (dev->device != PCI_DEVICE_ID_PROMISE_20246) { - hwif->resetproc = &pdc202xx_reset; - - hwif->cable_detect = pdc2026x_old_cable_detect; - } - - if (hwif->dma_base == 0) - return; - - hwif->dma_lost_irq = &pdc202xx_dma_lost_irq; - hwif->dma_timeout = &pdc202xx_dma_timeout; - - if (dev->device != PCI_DEVICE_ID_PROMISE_20246) { - hwif->dma_start = &pdc202xx_old_ide_dma_start; - hwif->ide_dma_end = &pdc202xx_old_ide_dma_end; - } - hwif->ide_dma_test_irq = &pdc202xx_old_ide_dma_test_irq; + pdc202xx_reset(drive); + ide_dma_timeout(drive); } -static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase) +static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev, + const char *name) { + unsigned long dmabase = pci_resource_start(dev, 4); u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0; - if (hwif->channel) { - ide_setup_dma(hwif, dmabase); - return; - } + if (dmabase == 0) + goto out; udma_speed_flag = inb(dmabase | 0x1f); primary_mode = inb(dmabase | 0x1a); secondary_mode = inb(dmabase | 0x1b); printk(KERN_INFO "%s: (U)DMA Burst Bit %sABLED " \ "Primary %s Mode " \ - "Secondary %s Mode.\n", hwif->cds->name, + "Secondary %s Mode.\n", pci_name(dev), (udma_speed_flag & 1) ? "EN" : "DIS", (primary_mode & 1) ? "MASTER" : "PCI", (secondary_mode & 1) ? "MASTER" : "PCI" ); if (!(udma_speed_flag & 1)) { printk(KERN_INFO "%s: FORCING BURST BIT 0x%02x->0x%02x ", - hwif->cds->name, udma_speed_flag, + pci_name(dev), udma_speed_flag, (udma_speed_flag|1)); outb(udma_speed_flag | 1, dmabase | 0x1f); printk("%sACTIVE\n", (inb(dmabase | 0x1f) & 1) ? "" : "IN"); } - - ide_setup_dma(hwif, dmabase); +out: + return dev->irq; } static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev, @@ -357,13 +315,48 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev, IDE_HFLAG_ABUSE_SET_DMA_MODE | \ IDE_HFLAG_OFF_BOARD) +static const struct ide_port_ops pdc20246_port_ops = { + .set_pio_mode = pdc202xx_set_pio_mode, + .set_dma_mode = pdc202xx_set_mode, + .quirkproc = pdc202xx_quirkproc, +}; + +static const struct ide_port_ops pdc2026x_port_ops = { + .set_pio_mode = pdc202xx_set_pio_mode, + .set_dma_mode = pdc202xx_set_mode, + .quirkproc = pdc202xx_quirkproc, + .resetproc = pdc202xx_reset, + .cable_detect = pdc2026x_cable_detect, +}; + +static const struct ide_dma_ops pdc20246_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 = pdc202xx_dma_test_irq, + .dma_lost_irq = pdc202xx_dma_lost_irq, + .dma_timeout = pdc202xx_dma_timeout, +}; + +static const struct ide_dma_ops pdc2026x_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ide_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = pdc202xx_dma_start, + .dma_end = pdc202xx_dma_end, + .dma_test_irq = pdc202xx_dma_test_irq, + .dma_lost_irq = pdc202xx_dma_lost_irq, + .dma_timeout = pdc202xx_dma_timeout, +}; + #define DECLARE_PDC2026X_DEV(name_str, udma, extra_flags) \ { \ .name = name_str, \ .init_chipset = init_chipset_pdc202xx, \ - .init_hwif = init_hwif_pdc202xx, \ - .init_dma = init_dma_pdc202xx, \ - .extra = 48, \ + .port_ops = &pdc2026x_port_ops, \ + .dma_ops = &pdc2026x_dma_ops, \ .host_flags = IDE_HFLAGS_PDC202XX | extra_flags, \ .pio_mask = ATA_PIO4, \ .mwdma_mask = ATA_MWDMA2, \ @@ -374,9 +367,8 @@ static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = { { /* 0 */ .name = "PDC20246", .init_chipset = init_chipset_pdc202xx, - .init_hwif = init_hwif_pdc202xx, - .init_dma = init_dma_pdc202xx, - .extra = 16, + .port_ops = &pdc20246_port_ops, + .dma_ops = &pdc20246_dma_ops, .host_flags = IDE_HFLAGS_PDC202XX, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index decef0f47674..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, } }; @@ -285,11 +286,6 @@ static u8 __devinit piix_cable_detect(ide_hwif_t *hwif) static void __devinit init_hwif_piix(ide_hwif_t *hwif) { - hwif->set_pio_mode = &piix_set_pio_mode; - hwif->set_dma_mode = &piix_set_dma_mode; - - hwif->cable_detect = piix_cable_detect; - if (!hwif->dma_base) return; @@ -306,10 +302,16 @@ static void __devinit init_hwif_ich(ide_hwif_t *hwif) hwif->ide_dma_clear_irq = &piix_dma_clear_irq; } +static const struct ide_port_ops piix_port_ops = { + .set_pio_mode = piix_set_pio_mode, + .set_dma_mode = piix_set_dma_mode, + .cable_detect = piix_cable_detect, +}; + #ifndef CONFIG_IA64 - #define IDE_HFLAGS_PIIX (IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE) + #define IDE_HFLAGS_PIIX IDE_HFLAG_LEGACY_IRQS #else - #define IDE_HFLAGS_PIIX IDE_HFLAG_BOOTABLE + #define IDE_HFLAGS_PIIX 0 #endif #define DECLARE_PIIX_DEV(name_str, udma) \ @@ -317,6 +319,7 @@ static void __devinit init_hwif_ich(ide_hwif_t *hwif) .name = name_str, \ .init_hwif = init_hwif_piix, \ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \ + .port_ops = &piix_port_ops, \ .host_flags = IDE_HFLAGS_PIIX, \ .pio_mask = ATA_PIO4, \ .swdma_mask = ATA_SWDMA2_ONLY, \ @@ -330,6 +333,7 @@ static void __devinit init_hwif_ich(ide_hwif_t *hwif) .init_chipset = init_chipset_ich, \ .init_hwif = init_hwif_ich, \ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \ + .port_ops = &piix_port_ops, \ .host_flags = IDE_HFLAGS_PIIX, \ .pio_mask = ATA_PIO4, \ .swdma_mask = ATA_SWDMA2_ONLY, \ diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c index 51676612f78f..532154adba29 100644 --- a/drivers/ide/pci/rz1000.c +++ b/drivers/ide/pci/rz1000.c @@ -43,7 +43,7 @@ static const struct ide_port_info rz1000_chipset __devinitdata = { .name = "RZ100x", .init_hwif = init_hwif_rz1000, .chipset = ide_rz1000, - .host_flags = IDE_HFLAG_NO_DMA | IDE_HFLAG_BOOTABLE, + .host_flags = IDE_HFLAG_NO_DMA, }; static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id) diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c index 561aa47c7720..14c787b5d95f 100644 --- a/drivers/ide/pci/sc1200.c +++ b/drivers/ide/pci/sc1200.c @@ -165,7 +165,7 @@ static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode) * * returns 1 on error, 0 otherwise */ -static int sc1200_ide_dma_end (ide_drive_t *drive) +static int sc1200_dma_end(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); unsigned long dma_base = hwif->dma_base; @@ -214,7 +214,7 @@ static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio) printk("SC1200: %s: changing (U)DMA mode\n", drive->name); ide_dma_off_quietly(drive); if (ide_set_dma_mode(drive, mode) == 0 && drive->using_dma) - hwif->dma_host_set(drive, 1); + hwif->dma_ops->dma_host_set(drive, 1); return; } @@ -286,29 +286,30 @@ static int sc1200_resume (struct pci_dev *dev) } #endif -/* - * This gets invoked by the IDE driver once for each channel, - * and performs channel-specific pre-initialization before drive probing. - */ -static void __devinit init_hwif_sc1200 (ide_hwif_t *hwif) -{ - hwif->set_pio_mode = &sc1200_set_pio_mode; - hwif->set_dma_mode = &sc1200_set_dma_mode; - - if (hwif->dma_base == 0) - return; +static const struct ide_port_ops sc1200_port_ops = { + .set_pio_mode = sc1200_set_pio_mode, + .set_dma_mode = sc1200_set_dma_mode, + .udma_filter = sc1200_udma_filter, +}; - hwif->udma_filter = sc1200_udma_filter; - hwif->ide_dma_end = &sc1200_ide_dma_end; -} +static const struct ide_dma_ops sc1200_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 = sc1200_dma_end, + .dma_test_irq = ide_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; static const struct ide_port_info sc1200_chipset __devinitdata = { .name = "SC1200", - .init_hwif = init_hwif_sc1200, + .port_ops = &sc1200_port_ops, + .dma_ops = &sc1200_dma_ops, .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_POST_SET_MODE | - IDE_HFLAG_ABUSE_DMA_MODES | - IDE_HFLAG_BOOTABLE, + IDE_HFLAG_ABUSE_DMA_MODES, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA2, diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c index 238e3e181e87..910fb00deb71 100644 --- a/drivers/ide/pci/scc_pata.c +++ b/drivers/ide/pci/scc_pata.c @@ -65,7 +65,7 @@ static struct scc_ports { unsigned long ctl, dma; - unsigned char hwif_id; /* for removing hwif from system */ + ide_hwif_t *hwif; /* for removing port from system */ } scc_ports[MAX_HWIFS]; /* PIO transfer mode table */ @@ -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,16 +318,48 @@ 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_ide_dma_end - Stop DMA + * 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_ide_dma_end(ide_drive_t * drive) +static int scc_dma_end(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); unsigned long intsts_port = hwif->dma_base + 0x014; @@ -334,7 +369,8 @@ static int scc_ide_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 *)IDE_ALTSTATUS_REG) & ERR_STAT) && + 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); if (!(reg & INTSTS_ACTEINT)) { @@ -424,7 +460,7 @@ static int scc_ide_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; @@ -437,7 +473,8 @@ 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 *)IDE_ALTSTATUS_REG) & ERR_STAT) && + if ((in_be32((void __iomem *)hwif->io_ports.ctl_addr) + & ERR_STAT) && (int_stat & INTSTS_INTRQ)) return 1; @@ -447,7 +484,7 @@ static int scc_dma_test_irq(ide_drive_t *drive) if (!drive->waiting_for_dma) printk(KERN_WARNING "%s: (%s) called while not waiting\n", - drive->name, __FUNCTION__); + drive->name, __func__); return 0; } @@ -481,7 +518,7 @@ static int setup_mmio_scc (struct pci_dev *dev, const char *name) unsigned long dma_size = pci_resource_len(dev, 1); void __iomem *ctl_addr; void __iomem *dma_addr; - int i; + int i, ret; for (i = 0; i < MAX_HWIFS; i++) { if (scc_ports[i].ctl == 0) @@ -490,21 +527,17 @@ static int setup_mmio_scc (struct pci_dev *dev, const char *name) if (i >= MAX_HWIFS) return -ENOMEM; - if (!request_mem_region(ctl_base, ctl_size, name)) { - printk(KERN_WARNING "%s: IDE controller MMIO ports not available.\n", SCC_PATA_NAME); - goto fail_0; - } - - if (!request_mem_region(dma_base, dma_size, name)) { - printk(KERN_WARNING "%s: IDE controller MMIO ports not available.\n", SCC_PATA_NAME); - goto fail_1; + ret = pci_request_selected_regions(dev, (1 << 2) - 1, name); + if (ret < 0) { + printk(KERN_ERR "%s: can't reserve resources\n", name); + return ret; } if ((ctl_addr = ioremap(ctl_base, ctl_size)) == NULL) - goto fail_2; + goto fail_0; if ((dma_addr = ioremap(dma_base, dma_size)) == NULL) - goto fail_3; + goto fail_1; pci_set_master(dev); scc_ports[i].ctl = (unsigned long)ctl_addr; @@ -513,16 +546,44 @@ static int setup_mmio_scc (struct pci_dev *dev, const char *name) return 1; - fail_3: - iounmap(ctl_addr); - fail_2: - release_mem_region(dma_base, dma_size); fail_1: - release_mem_region(ctl_base, ctl_size); + iounmap(ctl_addr); fail_0: return -ENOMEM; } +static int scc_ide_setup_pci_device(struct pci_dev *dev, + const struct ide_port_info *d) +{ + struct scc_ports *ports = pci_get_drvdata(dev); + ide_hwif_t *hwif = NULL; + hw_regs_t hw; + u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; + int i; + + hwif = ide_find_port(); + if (hwif == NULL) { + printk(KERN_ERR "%s: too many IDE interfaces, " + "no room in table\n", SCC_PATA_NAME); + return -ENOMEM; + } + + memset(&hw, 0, sizeof(hw)); + 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; + ide_init_port_hw(hwif, &hw); + hwif->dev = &dev->dev; + + idx[0] = hwif->index; + + ide_device_add(idx, d); + + return 0; +} + /** * init_setup_scc - set up an SCC PATA Controller * @dev: PCI device @@ -545,10 +606,13 @@ static int __devinit init_setup_scc(struct pci_dev *dev, struct scc_ports *ports; int rc; + rc = pci_enable_device(dev); + if (rc) + goto end; + rc = setup_mmio_scc(dev, d->name); - if (rc < 0) { - return rc; - } + if (rc < 0) + goto end; ports = pci_get_drvdata(dev); ctl_base = ports->ctl; @@ -583,7 +647,126 @@ static int __devinit init_setup_scc(struct pci_dev *dev, out_be32((void*)mode_port, MODE_JCUSFEN); out_be32((void*)intmask_port, INTMASK_MSK); - return ide_setup_pci_device(dev, d); + rc = scc_ide_setup_pci_device(dev, d); + + end: + 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); } /** @@ -600,27 +783,16 @@ 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->io_ports[IDE_DATA_OFFSET] = dma_base + 0x20; - hwif->io_ports[IDE_ERROR_OFFSET] = dma_base + 0x24; - hwif->io_ports[IDE_NSECTOR_OFFSET] = dma_base + 0x28; - hwif->io_ports[IDE_SECTOR_OFFSET] = dma_base + 0x2c; - hwif->io_ports[IDE_LCYL_OFFSET] = dma_base + 0x30; - hwif->io_ports[IDE_HCYL_OFFSET] = dma_base + 0x34; - hwif->io_ports[IDE_SELECT_OFFSET] = dma_base + 0x38; - hwif->io_ports[IDE_STATUS_OFFSET] = dma_base + 0x3c; - hwif->io_ports[IDE_CONTROL_OFFSET] = dma_base + 0x40; - - hwif->irq = dev->irq; + hwif->dma_base = dma_base; hwif->config_data = ports->ctl; hwif->mmio = 1; @@ -662,37 +834,46 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif) { struct scc_ports *ports = ide_get_hwifdata(hwif); - ports->hwif_id = hwif->index; + ports->hwif = 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); - hwif->dma_setup = scc_dma_setup; - hwif->ide_dma_end = scc_ide_dma_end; - hwif->set_pio_mode = scc_set_pio_mode; - hwif->set_dma_mode = scc_set_dma_mode; - hwif->ide_dma_test_irq = scc_dma_test_irq; - hwif->udma_filter = scc_udma_filter; - if (in_be32((void __iomem *)(hwif->config_data + 0xff0)) & CCKCTRL_ATACLKOEN) hwif->ultra_mask = ATA_UDMA6; /* 133MHz */ else hwif->ultra_mask = ATA_UDMA5; /* 100MHz */ - - hwif->cable_detect = scc_cable_detect; } +static const struct ide_port_ops scc_port_ops = { + .set_pio_mode = scc_set_pio_mode, + .set_dma_mode = scc_set_dma_mode, + .udma_filter = scc_udma_filter, + .cable_detect = scc_cable_detect, +}; + +static const struct ide_dma_ops scc_dma_ops = { + .dma_host_set = scc_dma_host_set, + .dma_setup = scc_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = scc_dma_start, + .dma_end = scc_dma_end, + .dma_test_irq = scc_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; + #define DECLARE_SCC_DEV(name_str) \ { \ .name = name_str, \ .init_iops = init_iops_scc, \ .init_hwif = init_hwif_scc, \ - .host_flags = IDE_HFLAG_SINGLE | \ - IDE_HFLAG_BOOTABLE, \ + .port_ops = &scc_port_ops, \ + .dma_ops = &scc_dma_ops, \ + .host_flags = IDE_HFLAG_SINGLE, \ .pio_mask = ATA_PIO4, \ } @@ -724,11 +905,7 @@ static int __devinit scc_init_one(struct pci_dev *dev, const struct pci_device_i static void __devexit scc_remove(struct pci_dev *dev) { struct scc_ports *ports = pci_get_drvdata(dev); - ide_hwif_t *hwif = &ide_hwifs[ports->hwif_id]; - unsigned long ctl_base = pci_resource_start(dev, 0); - unsigned long dma_base = pci_resource_start(dev, 1); - unsigned long ctl_size = pci_resource_len(dev, 0); - unsigned long dma_size = pci_resource_len(dev, 1); + ide_hwif_t *hwif = ports->hwif; if (hwif->dmatable_cpu) { pci_free_consistent(dev, PRD_ENTRIES * PRD_BYTES, @@ -736,13 +913,11 @@ static void __devexit scc_remove(struct pci_dev *dev) hwif->dmatable_cpu = NULL; } - ide_unregister(hwif->index, 0, 0); + ide_unregister(hwif); - hwif->chipset = ide_unknown; iounmap((void*)ports->dma); iounmap((void*)ports->ctl); - release_mem_region(dma_base, dma_size); - release_mem_region(ctl_base, ctl_size); + pci_release_selected_regions(dev, (1 << 2) - 1); memset(ports, 0, sizeof(*ports)); } diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c index c11880b0709f..a1fb20826a5b 100644 --- a/drivers/ide/pci/serverworks.c +++ b/drivers/ide/pci/serverworks.c @@ -312,7 +312,7 @@ static u8 __devinit ata66_svwks_cobalt(ide_hwif_t *hwif) return ATA_CBL_PATA40; } -static u8 __devinit ata66_svwks(ide_hwif_t *hwif) +static u8 __devinit svwks_cable_detect(ide_hwif_t *hwif) { struct pci_dev *dev = to_pci_dev(hwif->dev); @@ -336,28 +336,28 @@ static u8 __devinit ata66_svwks(ide_hwif_t *hwif) return ATA_CBL_PATA40; } -static void __devinit init_hwif_svwks (ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - - hwif->set_pio_mode = &svwks_set_pio_mode; - hwif->set_dma_mode = &svwks_set_dma_mode; - hwif->udma_filter = &svwks_udma_filter; +static const struct ide_port_ops osb4_port_ops = { + .set_pio_mode = svwks_set_pio_mode, + .set_dma_mode = svwks_set_dma_mode, + .udma_filter = svwks_udma_filter, +}; - if (dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) - hwif->cable_detect = ata66_svwks; -} +static const struct ide_port_ops svwks_port_ops = { + .set_pio_mode = svwks_set_pio_mode, + .set_dma_mode = svwks_set_dma_mode, + .udma_filter = svwks_udma_filter, + .cable_detect = svwks_cable_detect, +}; #define IDE_HFLAGS_SVWKS \ (IDE_HFLAG_LEGACY_IRQS | \ - IDE_HFLAG_ABUSE_SET_DMA_MODE | \ - IDE_HFLAG_BOOTABLE) + IDE_HFLAG_ABUSE_SET_DMA_MODE) static const struct ide_port_info serverworks_chipsets[] __devinitdata = { { /* 0 */ .name = "SvrWks OSB4", .init_chipset = init_chipset_svwks, - .init_hwif = init_hwif_svwks, + .port_ops = &osb4_port_ops, .host_flags = IDE_HFLAGS_SVWKS, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, @@ -365,7 +365,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = { },{ /* 1 */ .name = "SvrWks CSB5", .init_chipset = init_chipset_svwks, - .init_hwif = init_hwif_svwks, + .port_ops = &svwks_port_ops, .host_flags = IDE_HFLAGS_SVWKS, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, @@ -373,7 +373,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = { },{ /* 2 */ .name = "SvrWks CSB6", .init_chipset = init_chipset_svwks, - .init_hwif = init_hwif_svwks, + .port_ops = &svwks_port_ops, .host_flags = IDE_HFLAGS_SVWKS, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, @@ -381,7 +381,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = { },{ /* 3 */ .name = "SvrWks CSB6", .init_chipset = init_chipset_svwks, - .init_hwif = init_hwif_svwks, + .port_ops = &svwks_port_ops, .host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, @@ -389,7 +389,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = { },{ /* 4 */ .name = "SvrWks HT1000", .init_chipset = init_chipset_svwks, - .init_hwif = init_hwif_svwks, + .port_ops = &svwks_port_ops, .host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, @@ -418,7 +418,7 @@ static int __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device else if (idx == 2 || idx == 3) { if ((PCI_FUNC(dev->devfn) & 1) == 0) { if (pci_resource_start(dev, 0) != 0x01f1) - d.host_flags &= ~IDE_HFLAG_BOOTABLE; + d.host_flags |= IDE_HFLAG_NON_BOOTABLE; d.host_flags |= IDE_HFLAG_SINGLE; } else d.host_flags &= ~IDE_HFLAG_SINGLE; diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index 054626497be4..16a0bce17d69 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -98,29 +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 *)IDE_CONTROL_REG); + (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; @@ -135,25 +134,25 @@ 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); if (intr_reg & 0x03) { /* Valid IOC4-IDE interrupt */ /* - * Using sgiioc4_INB to read the IDE_STATUS_REG has a side effect - * of clearing the interrupt. The first read should clear it - * if it is set. The second read should return a "clear" status - * if it got cleared. If not, then spin for a bit trying to - * clear it. + * Using sgiioc4_INB to read the Status register has a side + * effect of clearing the interrupt. The first read should + * clear it if it is set. The second read should return + * a "clear" status if it got cleared. If not, then spin + * for a bit trying to clear it. */ - u8 stat = sgiioc4_INB(IDE_STATUS_REG); + u8 stat = sgiioc4_INB(io_ports->status_addr); int count = 0; - stat = sgiioc4_INB(IDE_STATUS_REG); + stat = sgiioc4_INB(io_ports->status_addr); while ((stat & 0x80) && (count++ < 100)) { udelay(1); - stat = sgiioc4_INB(IDE_STATUS_REG); + stat = sgiioc4_INB(io_ports->status_addr); } if (intr_reg & 0x02) { @@ -163,18 +162,18 @@ 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 "%s(%s) : PCI Bus Error when doing DMA:" " status-cmd reg is 0x%x\n", - __FUNCTION__, drive->name, pci_stat_cmd_reg); + __func__, drive->name, pci_stat_cmd_reg); printk(KERN_ERR "%s(%s) : PCI Error Address is 0x%x%x\n", - __FUNCTION__, drive->name, + __func__, drive->name, pci_err_addr_high, pci_err_addr_low); /* Clear the PCI Error indicator */ pci_write_config_dword(dev, PCI_COMMAND, 0x00000146); @@ -189,7 +188,7 @@ sgiioc4_clearirq(ide_drive_t * drive) return intr_reg & 3; } -static void sgiioc4_ide_dma_start(ide_drive_t * drive) +static void sgiioc4_dma_start(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); unsigned long ioc4_dma_addr = hwif->dma_base + IOC4_DMA_CTRL * 4; @@ -216,8 +215,7 @@ sgiioc4_ide_dma_stop(ide_hwif_t *hwif, u64 dma_base) } /* Stops the IOC4 DMA Engine */ -static int -sgiioc4_ide_dma_end(ide_drive_t * drive) +static int sgiioc4_dma_end(ide_drive_t *drive) { u32 ioc4_dma, bc_dev, bc_mem, num, valid = 0, cnt = 0; ide_hwif_t *hwif = HWIF(drive); @@ -233,7 +231,7 @@ sgiioc4_ide_dma_end(ide_drive_t * drive) printk(KERN_ERR "%s(%s): IOC4 DMA STOP bit is still 1 :" "ioc4_dma_reg 0x%x\n", - __FUNCTION__, drive->name, ioc4_dma); + __func__, drive->name, ioc4_dma); dma_stat = 1; } @@ -252,7 +250,7 @@ sgiioc4_ide_dma_end(ide_drive_t * drive) udelay(1); } if (!valid) { - printk(KERN_ERR "%s(%s) : DMA incomplete\n", __FUNCTION__, + printk(KERN_ERR "%s(%s) : DMA incomplete\n", __func__, drive->name); dma_stat = 1; } @@ -265,7 +263,7 @@ sgiioc4_ide_dma_end(ide_drive_t * drive) printk(KERN_ERR "%s(%s): WARNING!! byte_count_dev %d " "!= byte_count_mem %d\n", - __FUNCTION__, drive->name, bc_dev, bc_mem); + __func__, drive->name, bc_dev, bc_mem); } } @@ -280,8 +278,7 @@ static void sgiioc4_set_dma_mode(ide_drive_t *drive, const u8 speed) } /* returns 1 if dma irq issued, 0 otherwise */ -static int -sgiioc4_ide_dma_test_irq(ide_drive_t * drive) +static int sgiioc4_dma_test_irq(ide_drive_t *drive) { return sgiioc4_checkirq(HWIF(drive)); } @@ -295,7 +292,7 @@ static void sgiioc4_dma_host_set(ide_drive_t *drive, int on) static void sgiioc4_resetproc(ide_drive_t * drive) { - sgiioc4_ide_dma_end(drive); + sgiioc4_dma_end(drive); sgiioc4_clearirq(drive); } @@ -330,13 +327,17 @@ sgiioc4_INB(unsigned long port) /* Creates a dma map for the scatter-gather list entries */ static int __devinit -ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base) +ide_dma_sgiioc4(ide_hwif_t *hwif, const struct ide_port_info *d) { struct pci_dev *dev = to_pci_dev(hwif->dev); + unsigned long dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET; void __iomem *virt_dma_base; int num_ports = sizeof (ioc4_dma_regs_t); void *pad; + if (dma_base == 0) + return -1; + printk(KERN_INFO "%s: BM-DMA at 0x%04lx-0x%04lx\n", hwif->name, dma_base, dma_base + num_ports - 1); @@ -344,7 +345,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base) printk(KERN_ERR "%s(%s) -- ERROR, Addresses 0x%p to 0x%p " "ALREADY in use\n", - __FUNCTION__, hwif->name, (void *) dma_base, + __func__, hwif->name, (void *) dma_base, (void *) dma_base + num_ports - 1); return -1; } @@ -353,7 +354,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base) if (virt_dma_base == NULL) { printk(KERN_ERR "%s(%s) -- ERROR, Unable to map addresses 0x%lx to 0x%lx\n", - __FUNCTION__, hwif->name, dma_base, dma_base + num_ports - 1); + __func__, hwif->name, dma_base, dma_base + num_ports - 1); goto dma_remap_failure; } hwif->dma_base = (unsigned long) virt_dma_base; @@ -379,7 +380,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base) hwif->dmatable_cpu, hwif->dmatable_dma); printk(KERN_INFO "%s() -- Error! Unable to allocate DMA Maps for drive %s\n", - __FUNCTION__, hwif->name); + __func__, hwif->name); printk(KERN_INFO "Changing from DMA to PIO mode for Drive %s\n", hwif->name); @@ -407,14 +408,14 @@ sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive) if (ioc4_dma & IOC4_S_DMA_ACTIVE) { printk(KERN_WARNING "%s(%s):Warning!! DMA from previous transfer was still active\n", - __FUNCTION__, drive->name); + __func__, drive->name); writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr); ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base); if (ioc4_dma & IOC4_S_DMA_STOP) printk(KERN_ERR "%s(%s) : IOC4 Dma STOP bit is still 1\n", - __FUNCTION__, drive->name); + __func__, drive->name); } ioc4_dma = readl((void __iomem *)ioc4_dma_addr); @@ -422,14 +423,14 @@ sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive) printk(KERN_WARNING "%s(%s) : Warning!! - DMA Error during Previous" " transfer | status 0x%x\n", - __FUNCTION__, drive->name, ioc4_dma); + __func__, drive->name, ioc4_dma); writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr); ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base); if (ioc4_dma & IOC4_S_DMA_STOP) printk(KERN_ERR "%s(%s) : IOC4 DMA STOP bit is still 1\n", - __FUNCTION__, drive->name); + __func__, drive->name); } /* Address of the Scatter Gather List */ @@ -520,7 +521,7 @@ use_pio_instead: return 0; /* revert to PIO for this request */ } -static int sgiioc4_ide_dma_setup(ide_drive_t *drive) +static int sgiioc4_dma_setup(ide_drive_t *drive) { struct request *rq = HWGROUP(drive)->rq; unsigned int count = 0; @@ -549,63 +550,46 @@ static int sgiioc4_ide_dma_setup(ide_drive_t *drive) return 0; } -static void __devinit -ide_init_sgiioc4(ide_hwif_t * hwif) -{ - hwif->mmio = 1; - hwif->set_pio_mode = NULL; /* Sets timing for PIO mode */ - hwif->set_dma_mode = &sgiioc4_set_dma_mode; - hwif->selectproc = NULL;/* Use the default routine to select drive */ - hwif->reset_poll = NULL;/* No HBA specific reset_poll needed */ - hwif->pre_reset = NULL; /* No HBA specific pre_set needed */ - hwif->resetproc = &sgiioc4_resetproc;/* Reset DMA engine, - clear interrupts */ - hwif->maskproc = &sgiioc4_maskproc; /* Mask on/off NIEN register */ - hwif->quirkproc = NULL; - hwif->busproc = NULL; - - hwif->INB = &sgiioc4_INB; - - if (hwif->dma_base == 0) - return; +static const struct ide_port_ops sgiioc4_port_ops = { + .set_dma_mode = sgiioc4_set_dma_mode, + /* reset DMA engine, clear IRQs */ + .resetproc = sgiioc4_resetproc, + /* mask on/off NIEN register */ + .maskproc = sgiioc4_maskproc, +}; - hwif->dma_host_set = &sgiioc4_dma_host_set; - hwif->dma_setup = &sgiioc4_ide_dma_setup; - hwif->dma_start = &sgiioc4_ide_dma_start; - hwif->ide_dma_end = &sgiioc4_ide_dma_end; - hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq; - hwif->dma_lost_irq = &sgiioc4_dma_lost_irq; - hwif->dma_timeout = &ide_dma_timeout; -} +static const struct ide_dma_ops sgiioc4_dma_ops = { + .dma_host_set = sgiioc4_dma_host_set, + .dma_setup = sgiioc4_dma_setup, + .dma_start = sgiioc4_dma_start, + .dma_end = sgiioc4_dma_end, + .dma_test_irq = sgiioc4_dma_test_irq, + .dma_lost_irq = sgiioc4_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; static const struct ide_port_info sgiioc4_port_info __devinitdata = { .chipset = ide_pci, - .host_flags = IDE_HFLAG_NO_DMA | /* no SFF-style DMA */ - IDE_HFLAG_NO_AUTOTUNE, + .init_dma = ide_dma_sgiioc4, + .port_ops = &sgiioc4_port_ops, + .dma_ops = &sgiioc4_dma_ops, + .host_flags = IDE_HFLAG_MMIO, .mwdma_mask = ATA_MWDMA2_ONLY, }; static int __devinit sgiioc4_ide_setup_pci_device(struct pci_dev *dev) { - unsigned long cmd_base, dma_base, irqport; + unsigned long cmd_base, irqport; unsigned long bar0, cmd_phys_base, ctl; void __iomem *virt_base; ide_hwif_t *hwif; - int h; u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; hw_regs_t hw; struct ide_port_info d = sgiioc4_port_info; - /* - * Find an empty HWIF; if none available, return -ENOMEM. - */ - for (h = 0; h < MAX_HWIFS; ++h) { - hwif = &ide_hwifs[h]; - if (hwif->chipset == ide_unknown) - break; - } - if (h == MAX_HWIFS) { + hwif = ide_find_port(); + if (hwif == NULL) { printk(KERN_ERR "%s: too many IDE interfaces, no room in table\n", DRV_NAME); return -ENOMEM; @@ -622,7 +606,6 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) cmd_base = (unsigned long) virt_base + IOC4_CMD_OFFSET; ctl = (unsigned long) virt_base + IOC4_CTRL_OFFSET; irqport = (unsigned long) virt_base + IOC4_INTR_OFFSET; - dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET; cmd_phys_base = bar0 + IOC4_CMD_OFFSET; if (!request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE, @@ -630,7 +613,7 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) printk(KERN_ERR "%s : %s -- ERROR, Addresses " "0x%p to 0x%p ALREADY in use\n", - __FUNCTION__, hwif->name, (void *) cmd_phys_base, + __func__, hwif->name, (void *) cmd_phys_base, (void *) cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE); return -ENOMEM; } @@ -651,13 +634,7 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) /* Initializing chipset IRQ Registers */ writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4)); - if (dma_base == 0 || ide_dma_sgiioc4(hwif, dma_base)) { - printk(KERN_INFO "%s: %s Bus-Master DMA disabled\n", - hwif->name, DRV_NAME); - d.mwdma_mask = 0; - } - - ide_init_sgiioc4(hwif); + hwif->INB = &sgiioc4_INB; idx[0] = hwif->index; diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index 8d624afe8529..4cf8fc54aa2a 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,63 +281,49 @@ 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 */ -static int siimage_io_ide_dma_test_irq (ide_drive_t *drive) +static int siimage_io_dma_test_irq(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = to_pci_dev(hwif->dev); @@ -309,25 +331,26 @@ static int siimage_io_ide_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; } /** - * siimage_mmio_ide_dma_test_irq - check we caused an IRQ + * siimage_mmio_dma_test_irq - check we caused an IRQ * @drive: drive we are testing * * Check if we caused an IDE DMA interrupt. We may also have caused * SATA status interrupts, if so we clean them up and continue. */ - -static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive) + +static int siimage_mmio_dma_test_irq(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); unsigned long addr = siimage_selreg(hwif, 0x1); @@ -335,9 +358,9 @@ static int siimage_mmio_ide_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,69 +369,32 @@ static int siimage_mmio_ide_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, - __FUNCTION__); - - } 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; } -/** - * sil_sata_busproc - bus isolation IOCTL - * @drive: drive to isolate/restore - * @state: bus state to set - * - * Used by the SII3112 to handle bus isolation. As this is a - * SATA controller the work required is quite limited, we - * just have to clean up the statistics - */ - -static int sil_sata_busproc(ide_drive_t * drive, int state) +static int siimage_dma_test_irq(ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - u32 stat_config = 0; - unsigned long addr = siimage_selreg(hwif, 0); - - if (hwif->mmio) - stat_config = readl((void __iomem *)addr); + if (drive->hwif->mmio) + return siimage_mmio_dma_test_irq(drive); else - pci_read_config_dword(dev, addr, &stat_config); - - switch (state) { - case BUSSTATE_ON: - hwif->drives[0].failures = 0; - hwif->drives[1].failures = 0; - break; - case BUSSTATE_OFF: - hwif->drives[0].failures = hwif->drives[0].max_failures + 1; - hwif->drives[1].failures = hwif->drives[1].max_failures + 1; - break; - case BUSSTATE_TRISTATE: - hwif->drives[0].failures = hwif->drives[0].max_failures + 1; - hwif->drives[1].failures = hwif->drives[1].max_failures + 1; - break; - default: - return -EINVAL; - } - hwif->bus_state = state; - return 0; + return siimage_io_dma_test_irq(drive); } /** @@ -457,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; } @@ -521,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; } @@ -586,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); } - 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; + 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; + } + + 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; } @@ -644,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 @@ -656,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) @@ -681,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; @@ -706,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); @@ -717,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; + const char *s = &drive->id->model[0]; + unsigned len = strnlen(s, sizeof(drive->id->model)); - 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; } @@ -746,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; } @@ -777,104 +704,91 @@ static void __devinit init_iops_siimage(ide_hwif_t *hwif) } /** - * ata66_siimage - check for 80 pin cable + * 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 ata66_siimage(ide_hwif_t *hwif) +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; } -/** - * init_hwif_siimage - set up hwif structs - * @hwif: interface to set up - * - * We do the basic set up of the interface structure. The SIIMAGE - * requires several custom handlers so we override the default - * ide DMA handlers appropriately - */ - -static void __devinit init_hwif_siimage(ide_hwif_t *hwif) -{ - u8 sata = is_sata(hwif); - - hwif->set_pio_mode = &sil_set_pio_mode; - hwif->set_dma_mode = &sil_set_dma_mode; - hwif->quirkproc = &sil_quirkproc; - - if (sata) { - static int first = 1; - - hwif->busproc = &sil_sata_busproc; - hwif->reset_poll = &sil_sata_reset_poll; - hwif->pre_reset = &sil_sata_pre_reset; - hwif->udma_filter = &sil_sata_udma_filter; - - if (first) { - printk(KERN_INFO "siimage: For full SATA support you should use the libata sata_sil module.\n"); - first = 0; - } - } else - hwif->udma_filter = &sil_pata_udma_filter; - - hwif->cable_detect = ata66_siimage; - - if (hwif->dma_base == 0) - return; +static const struct ide_port_ops sil_pata_port_ops = { + .set_pio_mode = sil_set_pio_mode, + .set_dma_mode = sil_set_dma_mode, + .quirkproc = sil_quirkproc, + .udma_filter = sil_pata_udma_filter, + .cable_detect = sil_cable_detect, +}; - if (sata) - hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA; +static const struct ide_port_ops sil_sata_port_ops = { + .set_pio_mode = sil_set_pio_mode, + .set_dma_mode = sil_set_dma_mode, + .reset_poll = sil_sata_reset_poll, + .pre_reset = sil_sata_pre_reset, + .quirkproc = sil_quirkproc, + .udma_filter = sil_sata_udma_filter, + .cable_detect = sil_cable_detect, +}; - if (hwif->mmio) { - hwif->ide_dma_test_irq = &siimage_mmio_ide_dma_test_irq; - } else { - hwif->ide_dma_test_irq = & siimage_io_ide_dma_test_irq; - } -} +static struct ide_dma_ops sil_dma_ops = { + .dma_test_irq = siimage_dma_test_irq, +}; -#define DECLARE_SII_DEV(name_str) \ +#define DECLARE_SII_DEV(name_str, p_ops) \ { \ .name = name_str, \ .init_chipset = init_chipset_siimage, \ .init_iops = init_iops_siimage, \ - .init_hwif = init_hwif_siimage, \ - .host_flags = IDE_HFLAG_BOOTABLE, \ + .port_ops = p_ops, \ + .dma_ops = &sil_dma_ops, \ .pio_mask = ATA_PIO4, \ .mwdma_mask = ATA_MWDMA2, \ .udma_mask = ATA_UDMA6, \ } static const struct ide_port_info siimage_chipsets[] __devinitdata = { - /* 0 */ DECLARE_SII_DEV("SiI680"), - /* 1 */ DECLARE_SII_DEV("SiI3112 Serial ATA"), - /* 2 */ DECLARE_SII_DEV("Adaptec AAR-1210SA") + /* 0 */ DECLARE_SII_DEV("SiI680", &sil_pata_port_ops), + /* 1 */ DECLARE_SII_DEV("SiI3112 Serial ATA", &sil_sata_port_ops), + /* 2 */ DECLARE_SII_DEV("Adaptec AAR-1210SA", &sil_sata_port_ops) }; /** - * 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) { - return ide_setup_pci_device(dev, &siimage_chipsets[id->driver_data]); + struct ide_port_info d; + u8 idx = id->driver_data; + + d = siimage_chipsets[idx]; + + if (idx) { + static int first = 1; + + if (first) { + printk(KERN_INFO "siimage: For full SATA support you " + "should use the libata sata_sil module.\n"); + first = 0; + } + + d.host_flags |= IDE_HFLAG_NO_ATAPI_DMA; + } + + return ide_setup_pci_device(dev, &d); } static const struct pci_device_id siimage_pci_tbl[] = { diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index 512bb4c1fd5c..4b0b85d8faf5 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c @@ -59,10 +59,10 @@ #define ATA_16 0x01 #define ATA_33 0x02 #define ATA_66 0x03 -#define ATA_100a 0x04 // SiS730/SiS550 is ATA100 with ATA66 layout +#define ATA_100a 0x04 /* SiS730/SiS550 is ATA100 with ATA66 layout */ #define ATA_100 0x05 -#define ATA_133a 0x06 // SiS961b with 133 support -#define ATA_133 0x07 // SiS962/963 +#define ATA_133a 0x06 /* SiS961b with 133 support */ +#define ATA_133 0x07 /* SiS962/963 */ static u8 chipset_family; @@ -111,69 +111,70 @@ static const struct { Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */ /* {0, ATA_16, ATA_33, ATA_66, ATA_100a, ATA_100, ATA_133} */ -static u8 cycle_time_offset[] = {0,0,5,4,4,0,0}; -static u8 cycle_time_range[] = {0,0,2,3,3,4,4}; +static u8 cycle_time_offset[] = { 0, 0, 5, 4, 4, 0, 0 }; +static u8 cycle_time_range[] = { 0, 0, 2, 3, 3, 4, 4 }; static u8 cycle_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = { - {0,0,0,0,0,0,0}, /* no udma */ - {0,0,0,0,0,0,0}, /* no udma */ - {3,2,1,0,0,0,0}, /* ATA_33 */ - {7,5,3,2,1,0,0}, /* ATA_66 */ - {7,5,3,2,1,0,0}, /* ATA_100a (730 specific), differences are on cycle_time range and offset */ - {11,7,5,4,2,1,0}, /* ATA_100 */ - {15,10,7,5,3,2,1}, /* ATA_133a (earliest 691 southbridges) */ - {15,10,7,5,3,2,1}, /* ATA_133 */ + { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */ + { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */ + { 3, 2, 1, 0, 0, 0, 0 }, /* ATA_33 */ + { 7, 5, 3, 2, 1, 0, 0 }, /* ATA_66 */ + { 7, 5, 3, 2, 1, 0, 0 }, /* ATA_100a (730 specific), + different cycle_time range and offset */ + { 11, 7, 5, 4, 2, 1, 0 }, /* ATA_100 */ + { 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133a (earliest 691 southbridges) */ + { 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133 */ }; /* CRC Valid Setup Time vary across IDE clock setting 33/66/100/133 See SiS962 data sheet for more detail */ static u8 cvs_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = { - {0,0,0,0,0,0,0}, /* no udma */ - {0,0,0,0,0,0,0}, /* no udma */ - {2,1,1,0,0,0,0}, - {4,3,2,1,0,0,0}, - {4,3,2,1,0,0,0}, - {6,4,3,1,1,1,0}, - {9,6,4,2,2,2,2}, - {9,6,4,2,2,2,2}, + { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */ + { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */ + { 2, 1, 1, 0, 0, 0, 0 }, + { 4, 3, 2, 1, 0, 0, 0 }, + { 4, 3, 2, 1, 0, 0, 0 }, + { 6, 4, 3, 1, 1, 1, 0 }, + { 9, 6, 4, 2, 2, 2, 2 }, + { 9, 6, 4, 2, 2, 2, 2 }, }; /* Initialize time, Active time, Recovery time vary across IDE clock settings. These 3 arrays hold the register value for PIO0/1/2/3/4 and DMA0/1/2 mode in order */ static u8 ini_time_value[][8] = { - {0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0}, - {2,1,0,0,0,1,0,0}, - {4,3,1,1,1,3,1,1}, - {4,3,1,1,1,3,1,1}, - {6,4,2,2,2,4,2,2}, - {9,6,3,3,3,6,3,3}, - {9,6,3,3,3,6,3,3}, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 2, 1, 0, 0, 0, 1, 0, 0 }, + { 4, 3, 1, 1, 1, 3, 1, 1 }, + { 4, 3, 1, 1, 1, 3, 1, 1 }, + { 6, 4, 2, 2, 2, 4, 2, 2 }, + { 9, 6, 3, 3, 3, 6, 3, 3 }, + { 9, 6, 3, 3, 3, 6, 3, 3 }, }; static u8 act_time_value[][8] = { - {0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0}, - {9,9,9,2,2,7,2,2}, - {19,19,19,5,4,14,5,4}, - {19,19,19,5,4,14,5,4}, - {28,28,28,7,6,21,7,6}, - {38,38,38,10,9,28,10,9}, - {38,38,38,10,9,28,10,9}, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 9, 9, 9, 2, 2, 7, 2, 2 }, + { 19, 19, 19, 5, 4, 14, 5, 4 }, + { 19, 19, 19, 5, 4, 14, 5, 4 }, + { 28, 28, 28, 7, 6, 21, 7, 6 }, + { 38, 38, 38, 10, 9, 28, 10, 9 }, + { 38, 38, 38, 10, 9, 28, 10, 9 }, }; static u8 rco_time_value[][8] = { - {0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0}, - {9,2,0,2,0,7,1,1}, - {19,5,1,5,2,16,3,2}, - {19,5,1,5,2,16,3,2}, - {30,9,3,9,4,25,6,4}, - {40,12,4,12,5,34,12,5}, - {40,12,4,12,5,34,12,5}, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 9, 2, 0, 2, 0, 7, 1, 1 }, + { 19, 5, 1, 5, 2, 16, 3, 2 }, + { 19, 5, 1, 5, 2, 16, 3, 2 }, + { 30, 9, 3, 9, 4, 25, 6, 4 }, + { 40, 12, 4, 12, 5, 34, 12, 5 }, + { 40, 12, 4, 12, 5, 34, 12, 5 }, }; /* * Printing configuration */ /* Used for chipset type printing at boot time */ -static char* chipset_capability[] = { +static char *chipset_capability[] = { "ATA", "ATA 16", "ATA 33", "ATA 66", "ATA 100 (1st gen)", "ATA 100 (2nd gen)", @@ -272,7 +273,7 @@ static void sis_program_timings(ide_drive_t *drive, const u8 mode) sis_ata133_program_timings(drive, mode); } -static void config_drive_art_rwp (ide_drive_t *drive) +static void config_drive_art_rwp(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = to_pci_dev(hwif->dev); @@ -346,7 +347,7 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed) sis_program_timings(drive, speed); } -static u8 sis5513_ata133_udma_filter(ide_drive_t *drive) +static u8 sis_ata133_udma_filter(ide_drive_t *drive) { struct pci_dev *dev = to_pci_dev(drive->hwif->dev); u32 regdw = 0; @@ -358,8 +359,7 @@ static u8 sis5513_ata133_udma_filter(ide_drive_t *drive) return (regdw & 0x08) ? ATA_UDMA6 : ATA_UDMA5; } -/* Chip detection and general config */ -static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const char *name) +static int __devinit sis_find_family(struct pci_dev *dev) { struct pci_dev *host; int i = 0; @@ -381,7 +381,7 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c chipset_family = ATA_100a; } pci_dev_put(host); - + printk(KERN_INFO "SIS5513: %s %s controller\n", SiSHostChipInfo[i].name, chipset_capability[chipset_family]); } @@ -440,63 +440,60 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c } } - if (!chipset_family) - return -1; + return chipset_family; +} +static unsigned int __devinit init_chipset_sis5513(struct pci_dev *dev, + const char *name) +{ /* Make general config ops here 1/ tell IDE channels to operate in Compatibility mode only 2/ tell old chips to allow per drive IDE timings */ - { - u8 reg; - u16 regw; - - switch(chipset_family) { - case ATA_133: - /* SiS962 operation mode */ - pci_read_config_word(dev, 0x50, ®w); - if (regw & 0x08) - pci_write_config_word(dev, 0x50, regw&0xfff7); - pci_read_config_word(dev, 0x52, ®w); - if (regw & 0x08) - pci_write_config_word(dev, 0x52, regw&0xfff7); - break; - case ATA_133a: - case ATA_100: - /* Fixup latency */ - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80); - /* Set compatibility bit */ - pci_read_config_byte(dev, 0x49, ®); - if (!(reg & 0x01)) { - pci_write_config_byte(dev, 0x49, reg|0x01); - } - break; - case ATA_100a: - case ATA_66: - /* Fixup latency */ - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10); - - /* On ATA_66 chips the bit was elsewhere */ - pci_read_config_byte(dev, 0x52, ®); - if (!(reg & 0x04)) { - pci_write_config_byte(dev, 0x52, reg|0x04); - } - break; - case ATA_33: - /* On ATA_33 we didn't have a single bit to set */ - pci_read_config_byte(dev, 0x09, ®); - if ((reg & 0x0f) != 0x00) { - pci_write_config_byte(dev, 0x09, reg&0xf0); - } - case ATA_16: - /* force per drive recovery and active timings - needed on ATA_33 and below chips */ - pci_read_config_byte(dev, 0x52, ®); - if (!(reg & 0x08)) { - pci_write_config_byte(dev, 0x52, reg|0x08); - } - break; - } + u8 reg; + u16 regw; + + switch (chipset_family) { + case ATA_133: + /* SiS962 operation mode */ + pci_read_config_word(dev, 0x50, ®w); + if (regw & 0x08) + pci_write_config_word(dev, 0x50, regw&0xfff7); + pci_read_config_word(dev, 0x52, ®w); + if (regw & 0x08) + pci_write_config_word(dev, 0x52, regw&0xfff7); + break; + case ATA_133a: + case ATA_100: + /* Fixup latency */ + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80); + /* Set compatibility bit */ + pci_read_config_byte(dev, 0x49, ®); + if (!(reg & 0x01)) + pci_write_config_byte(dev, 0x49, reg|0x01); + break; + case ATA_100a: + case ATA_66: + /* Fixup latency */ + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10); + + /* On ATA_66 chips the bit was elsewhere */ + pci_read_config_byte(dev, 0x52, ®); + if (!(reg & 0x04)) + pci_write_config_byte(dev, 0x52, reg|0x04); + break; + case ATA_33: + /* On ATA_33 we didn't have a single bit to set */ + pci_read_config_byte(dev, 0x09, ®); + if ((reg & 0x0f) != 0x00) + pci_write_config_byte(dev, 0x09, reg&0xf0); + case ATA_16: + /* force per drive recovery and active timings + needed on ATA_33 and below chips */ + pci_read_config_byte(dev, 0x52, ®); + if (!(reg & 0x08)) + pci_write_config_byte(dev, 0x52, reg|0x08); + break; } return 0; @@ -517,7 +514,7 @@ static const struct sis_laptop sis_laptop[] = { { 0, } }; -static u8 __devinit ata66_sis5513(ide_hwif_t *hwif) +static u8 __devinit sis_cable_detect(ide_hwif_t *hwif) { struct pci_dev *pdev = to_pci_dev(hwif->dev); const struct sis_laptop *lap = &sis_laptop[0]; @@ -546,38 +543,44 @@ static u8 __devinit ata66_sis5513(ide_hwif_t *hwif) return ata66 ? ATA_CBL_PATA80 : ATA_CBL_PATA40; } -static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif) -{ - u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f }; - - hwif->set_pio_mode = &sis_set_pio_mode; - hwif->set_dma_mode = &sis_set_dma_mode; - - if (chipset_family >= ATA_133) - hwif->udma_filter = sis5513_ata133_udma_filter; - - hwif->cable_detect = ata66_sis5513; - - if (hwif->dma_base == 0) - return; +static const struct ide_port_ops sis_port_ops = { + .set_pio_mode = sis_set_pio_mode, + .set_dma_mode = sis_set_dma_mode, + .cable_detect = sis_cable_detect, +}; - hwif->ultra_mask = udma_rates[chipset_family]; -} +static const struct ide_port_ops sis_ata133_port_ops = { + .set_pio_mode = sis_set_pio_mode, + .set_dma_mode = sis_set_dma_mode, + .udma_filter = sis_ata133_udma_filter, + .cable_detect = sis_cable_detect, +}; static const struct ide_port_info sis5513_chipset __devinitdata = { .name = "SIS5513", .init_chipset = init_chipset_sis5513, - .init_hwif = init_hwif_sis5513, - .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, - .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA | - IDE_HFLAG_BOOTABLE, + .enablebits = { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} }, + .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, }; static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - return ide_setup_pci_device(dev, &sis5513_chipset); + struct ide_port_info d = sis5513_chipset; + u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f }; + + if (sis_find_family(dev) == 0) + return -ENOTSUPP; + + if (chipset_family >= ATA_133) + d.port_ops = &sis_ata133_port_ops; + else + d.port_ops = &sis_port_ops; + + d.udma_mask = udma_rates[chipset_family]; + + return ide_setup_pci_device(dev, &d); } static const struct pci_device_id sis5513_pci_tbl[] = { diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c index ee261ae15b6f..ce84fa045d39 100644 --- a/drivers/ide/pci/sl82c105.c +++ b/drivers/ide/pci/sl82c105.c @@ -179,7 +179,7 @@ static void sl82c105_dma_start(ide_drive_t *drive) struct pci_dev *dev = to_pci_dev(hwif->dev); int reg = 0x44 + drive->dn * 4; - DBG(("%s(drive:%s)\n", __FUNCTION__, drive->name)); + DBG(("%s(drive:%s)\n", __func__, drive->name)); pci_write_config_word(dev, reg, drive->drive_data >> 16); @@ -203,7 +203,7 @@ static int sl82c105_dma_end(ide_drive_t *drive) int reg = 0x44 + drive->dn * 4; int ret; - DBG(("%s(drive:%s)\n", __FUNCTION__, drive->name)); + DBG(("%s(drive:%s)\n", __func__, drive->name)); ret = __ide_dma_end(drive); @@ -232,7 +232,7 @@ static void sl82c105_resetproc(ide_drive_t *drive) * Return the revision of the Winbond bridge * which this function is part of. */ -static unsigned int sl82c105_bridge_revision(struct pci_dev *dev) +static u8 sl82c105_bridge_revision(struct pci_dev *dev) { struct pci_dev *bridge; @@ -282,60 +282,59 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c return dev->irq; } -/* - * Initialise IDE channel - */ -static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - unsigned int rev; - - DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index)); - - hwif->set_pio_mode = &sl82c105_set_pio_mode; - hwif->set_dma_mode = &sl82c105_set_dma_mode; - hwif->resetproc = &sl82c105_resetproc; - - if (!hwif->dma_base) - return; - - rev = sl82c105_bridge_revision(dev); - if (rev <= 5) { - /* - * Never ever EVER under any circumstances enable - * DMA when the bridge is this old. - */ - printk(" %s: Winbond W83C553 bridge revision %d, " - "BM-DMA disabled\n", hwif->name, rev); - return; - } - - hwif->mwdma_mask = ATA_MWDMA2; - - hwif->dma_lost_irq = &sl82c105_dma_lost_irq; - hwif->dma_start = &sl82c105_dma_start; - hwif->ide_dma_end = &sl82c105_dma_end; - hwif->dma_timeout = &sl82c105_dma_timeout; +static const struct ide_port_ops sl82c105_port_ops = { + .set_pio_mode = sl82c105_set_pio_mode, + .set_dma_mode = sl82c105_set_dma_mode, + .resetproc = sl82c105_resetproc, +}; - if (hwif->mate) - hwif->serialized = hwif->mate->serialized = 1; -} +static const struct ide_dma_ops sl82c105_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ide_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = sl82c105_dma_start, + .dma_end = sl82c105_dma_end, + .dma_test_irq = ide_dma_test_irq, + .dma_lost_irq = sl82c105_dma_lost_irq, + .dma_timeout = sl82c105_dma_timeout, +}; static const struct ide_port_info sl82c105_chipset __devinitdata = { .name = "W82C105", .init_chipset = init_chipset_sl82c105, - .init_hwif = init_hwif_sl82c105, .enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, + .port_ops = &sl82c105_port_ops, + .dma_ops = &sl82c105_dma_ops, .host_flags = IDE_HFLAG_IO_32BIT | IDE_HFLAG_UNMASK_IRQS | - IDE_HFLAG_NO_AUTODMA | - IDE_HFLAG_BOOTABLE, +/* FIXME: check for Compatibility mode in generic IDE PCI code */ +#if defined(CONFIG_LOPEC) || defined(CONFIG_SANDPOINT) + IDE_HFLAG_FORCE_LEGACY_IRQS | +#endif + IDE_HFLAG_SERIALIZE_DMA | + IDE_HFLAG_NO_AUTODMA, .pio_mask = ATA_PIO5, + .mwdma_mask = ATA_MWDMA2, }; static int __devinit sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - return ide_setup_pci_device(dev, &sl82c105_chipset); + struct ide_port_info d = sl82c105_chipset; + u8 rev = sl82c105_bridge_revision(dev); + + if (rev <= 5) { + /* + * Never ever EVER under any circumstances enable + * DMA when the bridge is this old. + */ + printk(KERN_INFO "W82C105_IDE: Winbond W83C553 bridge " + "revision %d, BM-DMA disabled\n", rev); + d.dma_ops = NULL; + d.mwdma_mask = 0; + d.host_flags &= ~IDE_HFLAG_SERIALIZE_DMA; + } + + return ide_setup_pci_device(dev, &d); } static const struct pci_device_id sl82c105_pci_tbl[] = { diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c index 65f4c2ffaa59..dae6e2c94d86 100644 --- a/drivers/ide/pci/slc90e66.c +++ b/drivers/ide/pci/slc90e66.c @@ -27,9 +27,9 @@ static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio) unsigned long flags; u16 master_data; u8 slave_data; - int control = 0; + int control = 0; /* ISP RTC */ - static const u8 timings[][2]= { + static const u8 timings[][2] = { { 0, 0 }, { 0, 0 }, { 1, 0 }, @@ -125,19 +125,17 @@ static u8 __devinit slc90e66_cable_detect(ide_hwif_t *hwif) return (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; } -static void __devinit init_hwif_slc90e66(ide_hwif_t *hwif) -{ - hwif->set_pio_mode = &slc90e66_set_pio_mode; - hwif->set_dma_mode = &slc90e66_set_dma_mode; - - hwif->cable_detect = slc90e66_cable_detect; -} +static const struct ide_port_ops slc90e66_port_ops = { + .set_pio_mode = slc90e66_set_pio_mode, + .set_dma_mode = slc90e66_set_dma_mode, + .cable_detect = slc90e66_cable_detect, +}; static const struct ide_port_info slc90e66_chipset __devinitdata = { .name = "SLC90E66", - .init_hwif = init_hwif_slc90e66, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE, + .enablebits = { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} }, + .port_ops = &slc90e66_port_ops, + .host_flags = IDE_HFLAG_LEGACY_IRQS, .pio_mask = ATA_PIO4, .swdma_mask = ATA_SWDMA2_ONLY, .mwdma_mask = ATA_MWDMA12_ONLY, diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c index 2ef2ed2f2b32..9b4b27a4c711 100644 --- a/drivers/ide/pci/tc86c001.c +++ b/drivers/ide/pci/tc86c001.c @@ -18,20 +18,20 @@ static void tc86c001_set_mode(ide_drive_t *drive, const u8 speed) u16 mode, scr = inw(scr_port); switch (speed) { - case XFER_UDMA_4: mode = 0x00c0; break; - case XFER_UDMA_3: mode = 0x00b0; break; - case XFER_UDMA_2: mode = 0x00a0; break; - case XFER_UDMA_1: mode = 0x0090; break; - case XFER_UDMA_0: mode = 0x0080; break; - case XFER_MW_DMA_2: mode = 0x0070; break; - case XFER_MW_DMA_1: mode = 0x0060; break; - case XFER_MW_DMA_0: mode = 0x0050; break; - case XFER_PIO_4: mode = 0x0400; break; - case XFER_PIO_3: mode = 0x0300; break; - case XFER_PIO_2: mode = 0x0200; break; - case XFER_PIO_1: mode = 0x0100; break; - case XFER_PIO_0: - default: mode = 0x0000; break; + case XFER_UDMA_4: mode = 0x00c0; break; + case XFER_UDMA_3: mode = 0x00b0; break; + case XFER_UDMA_2: mode = 0x00a0; break; + case XFER_UDMA_1: mode = 0x0090; break; + case XFER_UDMA_0: mode = 0x0080; break; + case XFER_MW_DMA_2: mode = 0x0070; break; + case XFER_MW_DMA_1: mode = 0x0060; break; + case XFER_MW_DMA_0: mode = 0x0050; break; + case XFER_PIO_4: mode = 0x0400; break; + case XFER_PIO_3: mode = 0x0300; break; + case XFER_PIO_2: mode = 0x0200; break; + case XFER_PIO_1: mode = 0x0100; break; + case XFER_PIO_0: + default: mode = 0x0000; break; } scr &= (speed < XFER_MW_DMA_0) ? 0xf8ff : 0xff0f; @@ -126,40 +126,6 @@ static void tc86c001_dma_start(ide_drive_t *drive) ide_dma_start(drive); } -static int tc86c001_busproc(ide_drive_t *drive, int state) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned long sc_base = hwif->config_data; - u16 scr1; - - /* System Control 1 Register bit 11 (ATA Hard Reset) read */ - scr1 = inw(sc_base + 0x00); - - switch (state) { - case BUSSTATE_ON: - if (!(scr1 & 0x0800)) - return 0; - scr1 &= ~0x0800; - - hwif->drives[0].failures = hwif->drives[1].failures = 0; - break; - case BUSSTATE_OFF: - if (scr1 & 0x0800) - return 0; - scr1 |= 0x0800; - - hwif->drives[0].failures = hwif->drives[0].max_failures + 1; - hwif->drives[1].failures = hwif->drives[1].max_failures + 1; - break; - default: - return -EINVAL; - } - - /* System Control 1 Register bit 11 (ATA Hard Reset) write */ - outw(scr1, sc_base + 0x00); - return 0; -} - static u8 __devinit tc86c001_cable_detect(ide_hwif_t *hwif) { struct pci_dev *dev = to_pci_dev(hwif->dev); @@ -191,13 +157,6 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif) /* Store the system control register base for convenience... */ hwif->config_data = sc_base; - hwif->set_pio_mode = &tc86c001_set_pio_mode; - hwif->set_dma_mode = &tc86c001_set_mode; - - hwif->busproc = &tc86c001_busproc; - - hwif->cable_detect = tc86c001_cable_detect; - if (!hwif->dma_base) return; @@ -209,8 +168,6 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif) /* Sector Count Register limit */ hwif->rqsize = 0xffff; - - hwif->dma_start = &tc86c001_dma_start; } static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev, @@ -223,10 +180,29 @@ static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev, return err; } +static const struct ide_port_ops tc86c001_port_ops = { + .set_pio_mode = tc86c001_set_pio_mode, + .set_dma_mode = tc86c001_set_mode, + .cable_detect = tc86c001_cable_detect, +}; + +static const struct ide_dma_ops tc86c001_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ide_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = tc86c001_dma_start, + .dma_end = __ide_dma_end, + .dma_test_irq = ide_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; + static const struct ide_port_info tc86c001_chipset __devinitdata = { .name = "TC86C001", .init_chipset = init_chipset_tc86c001, .init_hwif = init_hwif_tc86c001, + .port_ops = &tc86c001_port_ops, + .dma_ops = &tc86c001_dma_ops, .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD | IDE_HFLAG_ABUSE_SET_DMA_MODE, .pio_mask = ATA_PIO4, diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c index a67d02a3f96e..db65a558d4ec 100644 --- a/drivers/ide/pci/triflex.c +++ b/drivers/ide/pci/triflex.c @@ -87,17 +87,15 @@ static void triflex_set_pio_mode(ide_drive_t *drive, const u8 pio) triflex_set_mode(drive, XFER_PIO_0 + pio); } -static void __devinit init_hwif_triflex(ide_hwif_t *hwif) -{ - hwif->set_pio_mode = &triflex_set_pio_mode; - hwif->set_dma_mode = &triflex_set_mode; -} +static const struct ide_port_ops triflex_port_ops = { + .set_pio_mode = triflex_set_pio_mode, + .set_dma_mode = triflex_set_mode, +}; static const struct ide_port_info triflex_device __devinitdata = { .name = "TRIFLEX", - .init_hwif = init_hwif_triflex, .enablebits = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}}, - .host_flags = IDE_HFLAG_BOOTABLE, + .port_ops = &triflex_port_ops, .pio_mask = ATA_PIO4, .swdma_mask = ATA_SWDMA2, .mwdma_mask = ATA_MWDMA2, diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c index de750f7a43e9..a8a3138682ef 100644 --- a/drivers/ide/pci/trm290.c +++ b/drivers/ide/pci/trm290.c @@ -214,7 +214,7 @@ static void trm290_dma_start(ide_drive_t *drive) { } -static int trm290_ide_dma_end (ide_drive_t *drive) +static int trm290_dma_end(ide_drive_t *drive) { u16 status; @@ -225,7 +225,7 @@ static int trm290_ide_dma_end (ide_drive_t *drive) return status != 0x00ff; } -static int trm290_ide_dma_test_irq (ide_drive_t *drive) +static int trm290_dma_test_irq(ide_drive_t *drive) { u16 status; @@ -254,22 +254,11 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif) hwif->config_data = cfg_base; hwif->dma_base = (cfg_base + 4) ^ (hwif->channel ? 0x80 : 0); - printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx", + printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx\n", hwif->name, hwif->dma_base, hwif->dma_base + 3); - if (!request_region(hwif->dma_base, 4, hwif->name)) { - printk(KERN_CONT " -- Error, ports in use.\n"); + if (ide_allocate_dma_engine(hwif)) return; - } - - hwif->dmatable_cpu = pci_alloc_consistent(dev, PRD_ENTRIES * PRD_BYTES, - &hwif->dmatable_dma); - if (!hwif->dmatable_cpu) { - printk(KERN_CONT " -- Error, unable to allocate DMA table.\n"); - release_region(hwif->dma_base, 4); - return; - } - printk(KERN_CONT "\n"); local_irq_save(flags); /* put config reg into first byte of hwif->select_data */ @@ -291,14 +280,6 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif) /* sharing IRQ with mate */ hwif->irq = hwif->mate->irq; - hwif->dma_host_set = &trm290_dma_host_set; - hwif->dma_setup = &trm290_dma_setup; - hwif->dma_exec_cmd = &trm290_dma_exec_cmd; - hwif->dma_start = &trm290_dma_start; - hwif->ide_dma_end = &trm290_ide_dma_end; - hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq; - - hwif->selectproc = &trm290_selectproc; #if 1 { /* @@ -317,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: " @@ -328,16 +309,32 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif) #endif } +static const struct ide_port_ops trm290_port_ops = { + .selectproc = trm290_selectproc, +}; + +static struct ide_dma_ops trm290_dma_ops = { + .dma_host_set = trm290_dma_host_set, + .dma_setup = trm290_dma_setup, + .dma_exec_cmd = trm290_dma_exec_cmd, + .dma_start = trm290_dma_start, + .dma_end = trm290_dma_end, + .dma_test_irq = trm290_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; + static const struct ide_port_info trm290_chipset __devinitdata = { .name = "TRM290", .init_hwif = init_hwif_trm290, .chipset = ide_trm290, + .port_ops = &trm290_port_ops, + .dma_ops = &trm290_dma_ops, .host_flags = IDE_HFLAG_NO_ATAPI_DMA | #if 0 /* play it safe for now */ IDE_HFLAG_TRUST_BIOS_FOR_DMA | #endif IDE_HFLAG_NO_AUTODMA | - IDE_HFLAG_BOOTABLE | IDE_HFLAG_NO_LBA48, }; diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index 9004e7521889..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; @@ -415,25 +415,21 @@ static u8 __devinit via82cxxx_cable_detect(ide_hwif_t *hwif) return ATA_CBL_PATA40; } -static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif) -{ - hwif->set_pio_mode = &via_set_pio_mode; - hwif->set_dma_mode = &via_set_drive; - - hwif->cable_detect = via82cxxx_cable_detect; -} +static const struct ide_port_ops via_port_ops = { + .set_pio_mode = via_set_pio_mode, + .set_dma_mode = via_set_drive, + .cable_detect = via82cxxx_cable_detect, +}; static const struct ide_port_info via82cxxx_chipset __devinitdata = { .name = "VP_IDE", .init_chipset = init_chipset_via82cxxx, - .init_hwif = init_hwif_via82cxxx, .enablebits = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } }, + .port_ops = &via_port_ops, .host_flags = IDE_HFLAG_PIO_NO_BLACKLIST | - IDE_HFLAG_PIO_NO_DOWNGRADE | IDE_HFLAG_ABUSE_SET_DMA_MODE | IDE_HFLAG_POST_SET_MODE | - IDE_HFLAG_IO_32BIT | - IDE_HFLAG_BOOTABLE, + IDE_HFLAG_IO_32BIT, .pio_mask = ATA_PIO5, .swdma_mask = ATA_SWDMA2, .mwdma_mask = ATA_MWDMA2, diff --git a/drivers/ide/ppc/mpc8xx.c b/drivers/ide/ppc/mpc8xx.c index ebaba01c7551..f0e638dcc3ab 100644 --- a/drivers/ide/ppc/mpc8xx.c +++ b/drivers/ide/ppc/mpc8xx.c @@ -36,6 +36,8 @@ #include <asm/machdep.h> #include <asm/irq.h> +#define DRV_NAME "ide-mpc8xx" + static int identify (volatile u8 *p); static void print_fixed (volatile u8 *p); static void print_funcid (int func); @@ -99,32 +101,6 @@ static int _slot_ = -1; /* will be read from PCMCIA registers */ /* Make clock cycles and always round up */ #define PCMCIA_MK_CLKS( t, T ) (( (t) * ((T)/1000000) + 999U ) / 1000U ) - - -/* - * IDE stuff. - */ -static int -m8xx_ide_default_irq(unsigned long base) -{ -#ifdef CONFIG_BLK_DEV_MPC8xx_IDE - if (base >= MAX_HWIFS) - return 0; - - printk("[%d] m8xx_ide_default_irq %d\n",__LINE__,ioport_dsc[base].irq); - - return (ioport_dsc[base].irq); -#else - return 9; -#endif -} - -static unsigned long -m8xx_ide_default_io_base(int index) -{ - return index; -} - #define M8XX_PCMCIA_CD2(slot) (0x10000000 >> (slot << 4)) #define M8XX_PCMCIA_CD1(slot) (0x08000000 >> (slot << 4)) @@ -149,14 +125,13 @@ static int pcmcia_schlvl = PCMCIA_SCHLVL; */ /* - * m8xx_ide_init_hwif_ports for a direct IDE interface _using_ + * m8xx_ide_init_ports() for a direct IDE interface _using_ + * MPC8xx's internal PCMCIA interface */ #if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT) -static void -m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, - unsigned long ctrl_port, int *irq) +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 { @@ -173,8 +148,6 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, unsigned long base; *p = 0; - if (irq) - *irq = 0; pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia)); @@ -211,6 +184,13 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, pcmcia_phy_base, pcmcia_phy_end, pcmcia_phy_end - pcmcia_phy_base); + if (!request_mem_region(pcmcia_phy_base, + pcmcia_phy_end - pcmcia_phy_base, + DRV_NAME)) { + printk(KERN_ERR "%s: resources busy\n", DRV_NAME); + return -EBUSY; + } + pcmcia_base=(unsigned long)ioremap(pcmcia_phy_base, pcmcia_phy_end-pcmcia_phy_base); @@ -248,9 +228,6 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, } } - if (data_port >= MAX_HWIFS) - return; - if (_slot_ == -1) { printk ("PCMCIA slot has not been defined! Using A as default\n"); _slot_ = 0; @@ -268,7 +245,7 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, if (pcmp->pcmc_pipr & (M8XX_PCMCIA_CD1(_slot_)|M8XX_PCMCIA_CD2(_slot_))) { printk ("No card in slot %c: PIPR=%08x\n", 'A' + _slot_, (u32) pcmp->pcmc_pipr); - return; /* No card in slot */ + return -ENODEV; /* No card in slot */ } check_ide_device (pcmcia_base); @@ -292,11 +269,13 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, *p++ = base + ioport_dsc[data_port].reg_off[i]; } - if (irq) { + hw->irq = ioport_dsc[data_port].irq; + hw->ack_intr = (ide_ack_intr_t *)ide_interrupt_ack; + #ifdef CONFIG_IDE_8xx_PCCARD + { unsigned int reg; - *irq = ioport_dsc[data_port].irq; if (_slot_) pgcrx = &((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pgcrb; else @@ -306,14 +285,8 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, reg |= mk_int_int_mask (pcmcia_schlvl) << 24; reg |= mk_int_int_mask (pcmcia_schlvl) << 16; *pgcrx = reg; -#else /* direct connected IDE drive, i.e. external IRQ, not the PCMCIA irq */ - *irq = ioport_dsc[data_port].irq; -#endif /* CONFIG_IDE_8xx_PCCARD */ } - - ide_hwifs[data_port].pio_mask = ATA_PIO4; - ide_hwifs[data_port].set_pio_mode = m8xx_ide_set_pio_mode; - ide_hwifs[data_port].ack_intr = (ide_ack_intr_t *)ide_interrupt_ack; +#endif /* CONFIG_IDE_8xx_PCCARD */ /* Enable Harddisk Interrupt, * and make it edge sensitive @@ -329,18 +302,19 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, /* Enable falling edge irq */ pcmp->pcmc_per = 0x100000 >> (16 * _slot_); #endif /* CONFIG_IDE_8xx_PCCARD */ -} /* m8xx_ide_init_hwif_ports() using 8xx internal PCMCIA interface */ + + return 0; +} #endif /* CONFIG_IDE_8xx_PCCARD || CONFIG_IDE_8xx_DIRECT */ /* - * m8xx_ide_init_hwif_ports for a direct IDE interface _not_ using + * m8xx_ide_init_ports() for a direct IDE interface _not_ using * MPC8xx's internal PCMCIA interface */ #if defined(CONFIG_IDE_EXT_DIRECT) -void m8xx_ide_init_hwif_ports (hw_regs_t *hw, - unsigned long data_port, unsigned long ctrl_port, int *irq) +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; @@ -349,8 +323,6 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw, unsigned long base; *p = 0; - if (irq) - *irq = 0; if (!ide_base) { @@ -363,7 +335,12 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw, printk ("IDE phys mem : %08x...%08x (size %08x)\n", ide_phy_base, ide_phy_end, ide_phy_end - ide_phy_base); - + + if (!request_mem_region(ide_phy_base, 0x200, DRV_NAME)) { + printk(KERN_ERR "%s: resources busy\n", DRV_NAME); + return -EBUSY; + } + ide_base=(unsigned long)ioremap(ide_phy_base, ide_phy_end-ide_phy_base); @@ -372,9 +349,6 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw, #endif } - if (data_port >= MAX_HWIFS) - return; - base = ide_base + ioport_dsc[data_port].base_off; #ifdef DEBUG printk ("base: %08x + %08x = %08x\n", @@ -392,14 +366,9 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw, *p++ = base + ioport_dsc[data_port].reg_off[i]; } - if (irq) { - /* direct connected IDE drive, i.e. external IRQ */ - *irq = ioport_dsc[data_port].irq; - } - - ide_hwifs[data_port].pio_mask = ATA_PIO4; - ide_hwifs[data_port].set_pio_mode = m8xx_ide_set_pio_mode; - ide_hwifs[data_port].ack_intr = (ide_ack_intr_t *)ide_interrupt_ack; + /* direct connected IDE drive, i.e. external IRQ */ + hw->irq = ioport_dsc[data_port].irq; + hw->ack_intr = (ide_ack_intr_t *)ide_interrupt_ack; /* Enable Harddisk Interrupt, * and make it edge sensitive @@ -407,8 +376,9 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw, /* (11-18) Set edge detect for irq, no wakeup from low power mode */ ((immap_t *) IMAP_ADDR)->im_siu_conf.sc_siel |= (0x80000000 >> ioport_dsc[data_port].irq); -} /* m8xx_ide_init_hwif_ports() for CONFIG_IDE_8xx_DIRECT */ + return 0; +} #endif /* CONFIG_IDE_8xx_DIRECT */ @@ -468,10 +438,14 @@ static void m8xx_ide_set_pio_mode(ide_drive_t *drive, const u8 pio) #elif defined(CONFIG_IDE_EXT_DIRECT) printk("%s[%d] %s: not implemented yet!\n", - __FILE__,__LINE__,__FUNCTION__); + __FILE__, __LINE__, __func__); #endif /* defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_PCMCIA */ } +static const struct ide_port_ops m8xx_port_ops = { + .set_pio_mode = m8xx_ide_set_pio_mode, +}; + static void ide_interrupt_ack (void *dev) { @@ -829,21 +803,37 @@ static int identify (volatile u8 *p) return (0); /* don't know */ } -void m8xx_ide_init(void) -{ - ppc_ide_md.default_irq = m8xx_ide_default_irq; - ppc_ide_md.default_io_base = m8xx_ide_default_io_base; - ppc_ide_md.ide_init_hwif = m8xx_ide_init_hwif_ports; -} - static int __init mpc8xx_ide_probe(void) { + hw_regs_t hw; u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; #ifdef IDE0_BASE_OFFSET - idx[0] = 0; + memset(&hw, 0, sizeof(hw)); + if (!m8xx_ide_init_ports(&hw, 0)) { + ide_hwif_t *hwif = ide_find_port(); + + if (hwif) { + ide_init_port_hw(hwif, &hw); + hwif->pio_mask = ATA_PIO4; + hwif->port_ops = &m8xx_port_ops; + + idx[0] = hwif->index; + } + } #ifdef IDE1_BASE_OFFSET - idx[1] = 1; + memset(&hw, 0, sizeof(hw)); + if (!m8xx_ide_init_ports(&hw, 1)) { + ide_hwif_t *mate = ide_find_port(); + + if (mate) { + ide_init_port_hw(mate, &hw); + mate->pio_mask = ATA_PIO4; + mate->port_ops = &m8xx_port_ops; + + idx[1] = mate->index; + } + } #endif #endif diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index d9ca52e6cdab..48aa019127bc 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -79,9 +79,6 @@ typedef struct pmac_ide_hwif { } pmac_ide_hwif_t; -static pmac_ide_hwif_t pmac_ide[MAX_HWIFS]; -static int pmac_ide_count; - enum { controller_ohare, /* OHare based */ controller_heathrow, /* Heathrow/Paddington */ @@ -412,45 +409,15 @@ kauai_lookup_timing(struct kauai_timing* table, int cycle_time) */ #define IDE_WAKEUP_DELAY (1*HZ) -static int pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif); +static int pmac_ide_init_dma(ide_hwif_t *, const struct ide_port_info *); static int pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq); static void pmac_ide_selectproc(ide_drive_t *drive); static void pmac_ide_kauai_selectproc(ide_drive_t *drive); #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ -/* - * N.B. this can't be an initfunc, because the media-bay task can - * call ide_[un]register at any time. - */ -void -pmac_ide_init_hwif_ports(hw_regs_t *hw, - unsigned long data_port, unsigned long ctrl_port, - int *irq) -{ - int i, ix; - - if (data_port == 0) - return; - - for (ix = 0; ix < MAX_HWIFS; ++ix) - if (data_port == pmac_ide[ix].regbase) - break; - - if (ix >= MAX_HWIFS) - return; /* not an IDE PMAC interface */ - - for (i = 0; i < 8; ++i) - hw->io_ports[i] = data_port + i * 0x10; - hw->io_ports[8] = data_port + 0x160; - - if (irq != NULL) - *irq = pmac_ide[ix].irq; - - hw->dev = &pmac_ide[ix].mdev->ofdev.dev; -} - -#define PMAC_IDE_REG(x) ((void __iomem *)(IDE_DATA_REG+(x))) +#define PMAC_IDE_REG(x) \ + ((void __iomem *)((drive)->hwif->io_ports.data_addr + (x))) /* * Apply the timings of the proper unit (master/slave) to the shared @@ -886,58 +853,6 @@ sanitize_timings(pmac_ide_hwif_t *pmif) pmif->timings[2] = pmif->timings[3] = value2; } -unsigned long -pmac_ide_get_base(int index) -{ - return pmac_ide[index].regbase; -} - -int -pmac_ide_check_base(unsigned long base) -{ - int ix; - - for (ix = 0; ix < MAX_HWIFS; ++ix) - if (base == pmac_ide[ix].regbase) - return ix; - return -1; -} - -int -pmac_ide_get_irq(unsigned long base) -{ - int ix; - - for (ix = 0; ix < MAX_HWIFS; ++ix) - if (base == pmac_ide[ix].regbase) - return pmac_ide[ix].irq; - return 0; -} - -static int ide_majors[] = { 3, 22, 33, 34, 56, 57 }; - -dev_t __init -pmac_find_ide_boot(char *bootdevice, int n) -{ - int i; - - /* - * Look through the list of IDE interfaces for this one. - */ - for (i = 0; i < pmac_ide_count; ++i) { - char *name; - if (!pmac_ide[i].node || !pmac_ide[i].node->full_name) - continue; - name = pmac_ide[i].node->full_name; - if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) { - /* XXX should cope with the 2nd drive as well... */ - return MKDEV(ide_majors[i], 0); - } - } - - return 0; -} - /* Suspend call back, should be called after the child devices * have actually been suspended */ @@ -1003,12 +918,30 @@ pmac_ide_do_resume(ide_hwif_t *hwif) return 0; } +static const struct ide_port_ops pmac_ide_ata6_port_ops = { + .set_pio_mode = pmac_ide_set_pio_mode, + .set_dma_mode = pmac_ide_set_dma_mode, + .selectproc = pmac_ide_kauai_selectproc, +}; + +static const struct ide_port_ops pmac_ide_port_ops = { + .set_pio_mode = pmac_ide_set_pio_mode, + .set_dma_mode = pmac_ide_set_dma_mode, + .selectproc = pmac_ide_selectproc, +}; + +static const struct ide_dma_ops pmac_dma_ops; + static const struct ide_port_info pmac_port_info = { + .init_dma = pmac_ide_init_dma, .chipset = ide_pmac, +#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC + .dma_ops = &pmac_dma_ops, +#endif + .port_ops = &pmac_ide_port_ops, .host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA | - IDE_HFLAG_PIO_NO_DOWNGRADE | IDE_HFLAG_POST_SET_MODE | - IDE_HFLAG_NO_DMA | /* no SFF-style DMA */ + IDE_HFLAG_MMIO | IDE_HFLAG_UNMASK_IRQS, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, @@ -1033,12 +966,15 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw) pmif->broken_dma = pmif->broken_dma_warn = 0; if (of_device_is_compatible(np, "shasta-ata")) { pmif->kind = controller_sh_ata6; + d.port_ops = &pmac_ide_ata6_port_ops; d.udma_mask = ATA_UDMA6; } else if (of_device_is_compatible(np, "kauai-ata")) { pmif->kind = controller_un_ata6; + d.port_ops = &pmac_ide_ata6_port_ops; d.udma_mask = ATA_UDMA5; } else if (of_device_is_compatible(np, "K2-UATA")) { pmif->kind = controller_k2_ata6; + d.port_ops = &pmac_ide_ata6_port_ops; d.udma_mask = ATA_UDMA5; } else if (of_device_is_compatible(np, "keylargo-ata")) { if (strcmp(np->name, "ata-4") == 0) { @@ -1088,7 +1024,8 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw) if (np->parent && np->parent->name && strcasecmp(np->parent->name, "media-bay") == 0) { #ifdef CONFIG_PMAC_MEDIABAY - media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq, hwif->index); + media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq, + hwif); #endif /* CONFIG_PMAC_MEDIABAY */ pmif->mediabay = 1; if (!bidp) @@ -1114,38 +1051,29 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw) default_hwif_mmiops(hwif); hwif->OUTBSYNC = pmac_outbsync; - /* Tell common code _not_ to mess with resources */ - hwif->mmio = 1; hwif->hwif_data = pmif; ide_init_port_hw(hwif, hw); - hwif->noprobe = pmif->mediabay; - hwif->hold = pmif->mediabay; hwif->cbl = pmif->cable_80 ? ATA_CBL_PATA80 : ATA_CBL_PATA40; - hwif->set_pio_mode = pmac_ide_set_pio_mode; - if (pmif->kind == controller_un_ata6 - || pmif->kind == controller_k2_ata6 - || pmif->kind == controller_sh_ata6) - hwif->selectproc = pmac_ide_kauai_selectproc; - else - hwif->selectproc = pmac_ide_selectproc; - hwif->set_dma_mode = pmac_ide_set_dma_mode; printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n", hwif->index, model_name[pmif->kind], pmif->aapl_bus_id, pmif->mediabay ? " (mediabay)" : "", hwif->irq); - + + if (pmif->mediabay) { #ifdef CONFIG_PMAC_MEDIABAY - if (pmif->mediabay && check_media_bay_by_base(pmif->regbase, MB_CD) == 0) - hwif->noprobe = 0; -#endif /* CONFIG_PMAC_MEDIABAY */ + if (check_media_bay_by_base(pmif->regbase, MB_CD)) { +#else + if (1) { +#endif + hwif->drives[0].noprobe = 1; + hwif->drives[1].noprobe = 1; + } + } #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC if (pmif->cable_80 == 0) d.udma_mask &= ATA_UDMA2; - /* has a DBDMA controller channel */ - if (pmif->dma_regs == 0 || pmac_ide_setup_dma(pmif, hwif) < 0) #endif - d.udma_mask = d.mwdma_mask = 0; idx[0] = hwif->index; @@ -1154,6 +1082,16 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw) return 0; } +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_array[i] = base + i * 0x10; + + hw->io_ports.ctl_addr = base + 0x160; +} + /* * Attach to a macio probed interface */ @@ -1162,35 +1100,36 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match) { void __iomem *base; unsigned long regbase; - int irq; ide_hwif_t *hwif; pmac_ide_hwif_t *pmif; - int i, rc; + int irq, rc; hw_regs_t hw; - i = 0; - while (i < MAX_HWIFS && (ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0 - || pmac_ide[i].node != NULL)) - ++i; - if (i >= MAX_HWIFS) { + pmif = kzalloc(sizeof(*pmif), GFP_KERNEL); + if (pmif == NULL) + return -ENOMEM; + + hwif = ide_find_port(); + if (hwif == NULL) { printk(KERN_ERR "ide-pmac: MacIO interface attach with no slot\n"); printk(KERN_ERR " %s\n", mdev->ofdev.node->full_name); - return -ENODEV; + rc = -ENODEV; + goto out_free_pmif; } - pmif = &pmac_ide[i]; - hwif = &ide_hwifs[i]; - if (macio_resource_count(mdev) == 0) { - printk(KERN_WARNING "ide%d: no address for %s\n", - i, mdev->ofdev.node->full_name); - return -ENXIO; + printk(KERN_WARNING "ide-pmac: no address for %s\n", + mdev->ofdev.node->full_name); + rc = -ENXIO; + goto out_free_pmif; } /* Request memory resource for IO ports */ if (macio_request_resource(mdev, 0, "ide-pmac (ports)")) { - printk(KERN_ERR "ide%d: can't request mmio resource !\n", i); - return -EBUSY; + printk(KERN_ERR "ide-pmac: can't request MMIO resource for " + "%s!\n", mdev->ofdev.node->full_name); + rc = -EBUSY; + goto out_free_pmif; } /* XXX This is bogus. Should be fixed in the registry by checking @@ -1199,8 +1138,8 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match) * where that happens though... */ if (macio_irq_count(mdev) == 0) { - printk(KERN_WARNING "ide%d: no intrs for device %s, using 13\n", - i, mdev->ofdev.node->full_name); + printk(KERN_WARNING "ide-pmac: no intrs for device %s, using " + "13\n", mdev->ofdev.node->full_name); irq = irq_create_mapping(NULL, 13); } else irq = macio_irq(mdev, 0); @@ -1218,7 +1157,9 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match) #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC if (macio_resource_count(mdev) >= 2) { if (macio_request_resource(mdev, 1, "ide-pmac (dma)")) - printk(KERN_WARNING "ide%d: can't request DMA resource !\n", i); + printk(KERN_WARNING "ide-pmac: can't request DMA " + "resource for %s!\n", + mdev->ofdev.node->full_name); else pmif->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x1000); } else @@ -1227,7 +1168,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match) dev_set_drvdata(&mdev->ofdev.dev, hwif); memset(&hw, 0, sizeof(hw)); - pmac_ide_init_hwif_ports(&hw, pmif->regbase, 0, NULL); + pmac_ide_init_ports(&hw, pmif->regbase); hw.irq = irq; hw.dev = &mdev->ofdev.dev; @@ -1240,11 +1181,15 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match) iounmap(pmif->dma_regs); macio_release_resource(mdev, 1); } - memset(pmif, 0, sizeof(*pmif)); macio_release_resource(mdev, 0); + kfree(pmif); } return rc; + +out_free_pmif: + kfree(pmif); + return rc; } static int @@ -1289,7 +1234,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id) pmac_ide_hwif_t *pmif; void __iomem *base; unsigned long rbase, rlen; - int i, rc; + int rc; hw_regs_t hw; np = pci_device_to_OF_node(pdev); @@ -1297,30 +1242,32 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id) printk(KERN_ERR "ide-pmac: cannot find MacIO node for Kauai ATA interface\n"); return -ENODEV; } - i = 0; - while (i < MAX_HWIFS && (ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0 - || pmac_ide[i].node != NULL)) - ++i; - if (i >= MAX_HWIFS) { + + pmif = kzalloc(sizeof(*pmif), GFP_KERNEL); + if (pmif == NULL) + return -ENOMEM; + + hwif = ide_find_port(); + if (hwif == NULL) { printk(KERN_ERR "ide-pmac: PCI interface attach with no slot\n"); printk(KERN_ERR " %s\n", np->full_name); - return -ENODEV; + rc = -ENODEV; + goto out_free_pmif; } - pmif = &pmac_ide[i]; - hwif = &ide_hwifs[i]; - if (pci_enable_device(pdev)) { - printk(KERN_WARNING "ide%i: Can't enable PCI device for %s\n", - i, np->full_name); - return -ENXIO; + printk(KERN_WARNING "ide-pmac: Can't enable PCI device for " + "%s\n", np->full_name); + rc = -ENXIO; + goto out_free_pmif; } pci_set_master(pdev); if (pci_request_regions(pdev, "Kauai ATA")) { - printk(KERN_ERR "ide%d: Cannot obtain PCI resources for %s\n", - i, np->full_name); - return -ENXIO; + printk(KERN_ERR "ide-pmac: Cannot obtain PCI resources for " + "%s\n", np->full_name); + rc = -ENXIO; + goto out_free_pmif; } hwif->dev = &pdev->dev; @@ -1341,7 +1288,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_drvdata(pdev, hwif); memset(&hw, 0, sizeof(hw)); - pmac_ide_init_hwif_ports(&hw, pmif->regbase, 0, NULL); + pmac_ide_init_ports(&hw, pmif->regbase); hw.irq = pdev->irq; hw.dev = &pdev->dev; @@ -1350,11 +1297,15 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id) /* The inteface is released to the common IDE layer */ pci_set_drvdata(pdev, NULL); iounmap(base); - memset(pmif, 0, sizeof(*pmif)); pci_release_regions(pdev); + kfree(pmif); } return rc; + +out_free_pmif: + kfree(pmif); + return rc; } static int @@ -1726,18 +1677,31 @@ pmac_ide_dma_lost_irq (ide_drive_t *drive) printk(KERN_ERR "ide-pmac lost interrupt, dma status: %lx\n", status); } +static const struct ide_dma_ops pmac_dma_ops = { + .dma_host_set = pmac_ide_dma_host_set, + .dma_setup = pmac_ide_dma_setup, + .dma_exec_cmd = pmac_ide_dma_exec_cmd, + .dma_start = pmac_ide_dma_start, + .dma_end = pmac_ide_dma_end, + .dma_test_irq = pmac_ide_dma_test_irq, + .dma_timeout = ide_dma_timeout, + .dma_lost_irq = pmac_ide_dma_lost_irq, +}; + /* * Allocate the data structures needed for using DMA with an interface * and fill the proper list of functions pointers */ -static int __devinit pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) +static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif, + const struct ide_port_info *d) { + pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data; struct pci_dev *dev = to_pci_dev(hwif->dev); /* We won't need pci_dev if we switch to generic consistent * DMA routines ... */ - if (dev == NULL) + if (dev == NULL || pmif->dma_regs == 0) return -ENODEV; /* * Allocate space for the DBDMA commands. @@ -1756,18 +1720,14 @@ static int __devinit pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) hwif->sg_max_nents = MAX_DCMDS; - hwif->dma_host_set = &pmac_ide_dma_host_set; - hwif->dma_setup = &pmac_ide_dma_setup; - hwif->dma_exec_cmd = &pmac_ide_dma_exec_cmd; - hwif->dma_start = &pmac_ide_dma_start; - hwif->ide_dma_end = &pmac_ide_dma_end; - hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq; - hwif->dma_timeout = &ide_dma_timeout; - hwif->dma_lost_irq = &pmac_ide_dma_lost_irq; - return 0; } - +#else +static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif, + const struct ide_port_info *d) +{ + return -EOPNOTSUPP; +} #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ module_init(pmac_ide_probe); diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 634e3f6a9608..5171601fb255 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -20,84 +20,6 @@ #include <asm/io.h> #include <asm/irq.h> - -/** - * ide_match_hwif - match a PCI IDE against an ide_hwif - * @io_base: I/O base of device - * @bootable: set if its bootable - * @name: name of device - * - * Match a PCI IDE port against an entry in ide_hwifs[], - * based on io_base port if possible. Return the matching hwif, - * or a new hwif. If we find an error (clashing, out of devices, etc) - * return NULL - * - * FIXME: we need to handle mmio matches here too - */ - -static ide_hwif_t *ide_match_hwif(unsigned long io_base, u8 bootable, const char *name) -{ - int h; - ide_hwif_t *hwif; - - /* - * Look for a hwif with matching io_base specified using - * parameters to ide_setup(). - */ - for (h = 0; h < MAX_HWIFS; ++h) { - hwif = &ide_hwifs[h]; - if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) { - if (hwif->chipset == ide_forced) - return hwif; /* a perfect match */ - } - } - /* - * Look for a hwif with matching io_base default value. - * If chipset is "ide_unknown", then claim that hwif slot. - * Otherwise, some other chipset has already claimed it.. :( - */ - for (h = 0; h < MAX_HWIFS; ++h) { - hwif = &ide_hwifs[h]; - if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) { - if (hwif->chipset == ide_unknown) - return hwif; /* match */ - printk(KERN_ERR "%s: port 0x%04lx already claimed by %s\n", - name, io_base, hwif->name); - return NULL; /* already claimed */ - } - } - /* - * Okay, there is no hwif matching our io_base, - * so we'll just claim an unassigned slot. - * Give preference to claiming other slots before claiming ide0/ide1, - * just in case there's another interface yet-to-be-scanned - * which uses ports 1f0/170 (the ide0/ide1 defaults). - * - * Unless there is a bootable card that does not use the standard - * ports 1f0/170 (the ide0/ide1 defaults). The (bootable) flag. - */ - if (bootable) { - for (h = 0; h < MAX_HWIFS; ++h) { - hwif = &ide_hwifs[h]; - if (hwif->chipset == ide_unknown) - return hwif; /* pick an unused entry */ - } - } else { - for (h = 2; h < MAX_HWIFS; ++h) { - hwif = ide_hwifs + h; - if (hwif->chipset == ide_unknown) - return hwif; /* pick an unused entry */ - } - } - for (h = 0; h < 2 && h < MAX_HWIFS; ++h) { - hwif = ide_hwifs + h; - if (hwif->chipset == ide_unknown) - return hwif; /* pick an unused entry */ - } - printk(KERN_ERR "%s: too many IDE interfaces, no room in table\n", name); - return NULL; -} - /** * ide_setup_pci_baseregs - place a PCI IDE controller native * @dev: PCI device of interface to switch native @@ -105,13 +27,13 @@ static ide_hwif_t *ide_match_hwif(unsigned long io_base, u8 bootable, const char * * We attempt to place the PCI interface into PCI native mode. If * we succeed the BARs are ok and the controller is in PCI mode. - * Returns 0 on success or an errno code. + * Returns 0 on success or an errno code. * * FIXME: if we program the interface and then fail to set the BARS * we don't switch it back to legacy mode. Do we actually care ?? */ - -static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name) + +static int ide_setup_pci_baseregs(struct pci_dev *dev, const char *name) { u8 progif = 0; @@ -150,16 +72,16 @@ static void ide_pci_clear_simplex(unsigned long dma_base, const char *name) } /** - * ide_get_or_set_dma_base - setup BMIBA - * @d: IDE port info + * ide_pci_dma_base - setup BMIBA * @hwif: IDE interface + * @d: IDE port info * * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space. * Where a device has a partner that is already in DMA mode we check * and enforce IDE simplex rules. */ -static unsigned long ide_get_or_set_dma_base(const struct ide_port_info *d, ide_hwif_t *hwif) +unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d) { struct pci_dev *dev = to_pci_dev(hwif->dev); unsigned long dma_base = 0; @@ -210,6 +132,31 @@ static unsigned long ide_get_or_set_dma_base(const struct ide_port_info *d, ide_ out: return dma_base; } +EXPORT_SYMBOL_GPL(ide_pci_dma_base); + +/* + * Set up BM-DMA capability (PnP BIOS should have done this) + */ +int ide_pci_set_master(struct pci_dev *dev, const char *name) +{ + u16 pcicmd; + + pci_read_config_word(dev, PCI_COMMAND, &pcicmd); + + if ((pcicmd & PCI_COMMAND_MASTER) == 0) { + pci_set_master(dev); + + if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || + (pcicmd & PCI_COMMAND_MASTER) == 0) { + printk(KERN_ERR "%s: error updating PCICMD on %s\n", + name, pci_name(dev)); + return -EIO; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(ide_pci_set_master); #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ void ide_setup_pci_noise(struct pci_dev *dev, const struct ide_port_info *d) @@ -218,7 +165,6 @@ void ide_setup_pci_noise(struct pci_dev *dev, const struct ide_port_info *d) " PCI slot %s\n", d->name, dev->vendor, dev->device, dev->revision, pci_name(dev)); } - EXPORT_SYMBOL_GPL(ide_setup_pci_noise); @@ -231,13 +177,13 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise); * but if that fails then we only need IO space. The PCI code should * have setup the proper resources for us already for controllers in * legacy mode. - * + * * Returns zero on success or an error code */ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d) { - int ret; + int ret, bars; if (pci_enable_device(dev)) { ret = pci_enable_device_io(dev); @@ -260,13 +206,21 @@ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d) goto out; } - /* FIXME: Temporary - until we put in the hotplug interface logic - Check that the bits we want are not in use by someone else. */ - ret = pci_request_region(dev, 4, "ide_tmp"); - if (ret < 0) - goto out; + if (d->host_flags & IDE_HFLAG_SINGLE) + bars = (1 << 2) - 1; + else + bars = (1 << 4) - 1; + + if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) { + if (d->host_flags & IDE_HFLAG_CS5520) + bars |= (1 << 2); + else + bars |= (1 << 4); + } - pci_release_region(dev, 4); + ret = pci_request_selected_regions(dev, bars, d->name); + if (ret < 0) + printk(KERN_ERR "%s: can't reserve resources\n", d->name); out: return ret; } @@ -290,8 +244,8 @@ static int ide_pci_configure(struct pci_dev *dev, const struct ide_port_info *d) * Maybe the user deliberately *disabled* the device, * but we'll eventually ignore it again if no drives respond. */ - if (ide_setup_pci_baseregs(dev, d->name) || pci_write_config_word(dev, PCI_COMMAND, pcicmd|PCI_COMMAND_IO)) - { + if (ide_setup_pci_baseregs(dev, d->name) || + pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) { printk(KERN_INFO "%s: device disabled (BIOS)\n", d->name); return -ENODEV; } @@ -312,26 +266,24 @@ static int ide_pci_configure(struct pci_dev *dev, const struct ide_port_info *d) * @d: IDE port info * @bar: BAR number * - * Checks if a BAR is configured and points to MMIO space. If so - * print an error and return an error code. Otherwise return 0 + * Checks if a BAR is configured and points to MMIO space. If so, + * return an error code. Otherwise return 0 */ -static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *d, int bar) +static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *d, + int bar) { ulong flags = pci_resource_flags(dev, bar); - + /* Unconfigured ? */ if (!flags || pci_resource_len(dev, bar) == 0) return 0; - /* I/O space */ - if(flags & PCI_BASE_ADDRESS_IO_MASK) + /* I/O space */ + if (flags & IORESOURCE_IO) return 0; - + /* Bad */ - printk(KERN_ERR "%s: IO baseregs (BIOS) are reported " - "as MEM, report to " - "<andre@linux-ide.org>.\n", d->name); return -EINVAL; } @@ -355,15 +307,16 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, { unsigned long ctl = 0, base = 0; ide_hwif_t *hwif; - u8 bootable = (d->host_flags & IDE_HFLAG_BOOTABLE) ? 1 : 0; - u8 oldnoprobe = 0; struct hw_regs_s hw; if ((d->host_flags & IDE_HFLAG_ISA_PORTS) == 0) { - /* Possibly we should fail if these checks report true */ - ide_pci_check_iomem(dev, d, 2*port); - ide_pci_check_iomem(dev, d, 2*port+1); - + if (ide_pci_check_iomem(dev, d, 2 * port) || + ide_pci_check_iomem(dev, d, 2 * port + 1)) { + printk(KERN_ERR "%s: I/O baseregs (BIOS) are reported " + "as MEM for port %d!\n", d->name, port); + return NULL; + } + ctl = pci_resource_start(dev, 2*port+1); base = pci_resource_start(dev, 2*port); if ((ctl && !base) || (base && !ctl)) { @@ -372,31 +325,28 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, return NULL; } } - if (!ctl) - { + if (!ctl) { /* Use default values */ ctl = port ? 0x374 : 0x3f4; base = port ? 0x170 : 0x1f0; } - if ((hwif = ide_match_hwif(base, bootable, d->name)) == NULL) - return NULL; /* no room in ide_hwifs[] */ + + hwif = ide_find_port_slot(d); + if (hwif == NULL) { + printk(KERN_ERR "%s: too many IDE interfaces, no room in " + "table\n", d->name); + return NULL; + } memset(&hw, 0, sizeof(hw)); - hw.irq = hwif->irq ? hwif->irq : irq; + hw.irq = irq; hw.dev = &dev->dev; hw.chipset = d->chipset ? d->chipset : ide_pci; ide_std_init_ports(&hw, base, ctl | 2); - if (hwif->io_ports[IDE_DATA_OFFSET] == base && - hwif->io_ports[IDE_CONTROL_OFFSET] == (ctl | 2)) - oldnoprobe = hwif->noprobe; - ide_init_port_hw(hwif, &hw); - hwif->noprobe = oldnoprobe; - hwif->dev = &dev->dev; - hwif->cds = d; return hwif; } @@ -412,40 +362,33 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, * state */ -void ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d) +int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d) { struct pci_dev *dev = to_pci_dev(hwif->dev); - u16 pcicmd; - - pci_read_config_word(dev, PCI_COMMAND, &pcicmd); if ((d->host_flags & IDE_HFLAG_NO_AUTODMA) == 0 || ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) { - unsigned long dma_base = ide_get_or_set_dma_base(d, hwif); - if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) { - /* - * Set up BM-DMA capability - * (PnP BIOS should have done this) - */ - pci_set_master(dev); - if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) { - printk(KERN_ERR "%s: %s error updating PCICMD\n", - hwif->name, d->name); - dma_base = 0; - } - } - if (dma_base) { - if (d->init_dma) { - d->init_dma(hwif, dma_base); - } else { - ide_setup_dma(hwif, dma_base); - } - } else { - printk(KERN_INFO "%s: %s Bus-Master DMA disabled " - "(BIOS)\n", hwif->name, d->name); - } + unsigned long base = ide_pci_dma_base(hwif, d); + + if (base == 0 || ide_pci_set_master(dev, d->name) < 0) + return -1; + + if (hwif->mmio) + printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name); + else + printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx\n", + hwif->name, base, base + 7); + + hwif->extra_base = base + (hwif->channel ? 8 : 16); + + if (ide_allocate_dma_engine(hwif)) + return -1; + + ide_setup_dma(hwif, base); } + + return 0; } #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ @@ -532,7 +475,6 @@ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int *(idx + port) = hwif->index; } } - EXPORT_SYMBOL_GPL(ide_pci_setup_ports); /* @@ -615,7 +557,6 @@ int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d) return ret; } - EXPORT_SYMBOL_GPL(ide_setup_pci_device); int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2, @@ -639,5 +580,4 @@ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2, out: return ret; } - EXPORT_SYMBOL_GPL(ide_setup_pci_devices); |