Merge git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6: (76 commits)
  IDE: Report errors during drive reset back to user space
  Update documentation of HDIO_DRIVE_RESET ioctl
  IDE: Remove unused code
  IDE: Fix HDIO_DRIVE_RESET handling
  hd.c: remove the #include <linux/mc146818rtc.h>
  update the BLK_DEV_HD help text
  move ide/legacy/hd.c to drivers/block/
  ide/legacy/hd.c: use late_initcall()
  remove BLK_DEV_HD_ONLY
  ide: endian annotations in ide-floppy.c
  ide-floppy: zero out the whole struct ide_atapi_pc on init
  ide-floppy: fold idefloppy_create_test_unit_ready_cmd into idefloppy_open
  ide-cd: move request prep chunk from cdrom_do_newpc_cont to rq issue path
  ide-cd: move request prep from cdrom_start_rw_cont to rq issue path
  ide-cd: move request prep from cdrom_start_seek_continuation to rq issue path
  ide-cd: fold cdrom_start_seek into ide_cd_do_request
  ide-cd: simplify request issuing path
  ide-cd: mv ide_do_rw_cdrom ide_cd_do_request
  ide-cd: cdrom_start_seek: remove unused argument block
  ide-cd: ide_do_rw_cdrom: add the catch-all bad request case to the if-else block
  ...
This commit is contained in:
Linus Torvalds 2008-07-16 14:53:54 -07:00
commit 42fdd144a4
58 changed files with 694 additions and 1870 deletions

View File

@ -508,12 +508,13 @@ HDIO_DRIVE_RESET execute a device reset
error returns:
EACCES Access denied: requires CAP_SYS_ADMIN
ENXIO No such device: phy dead or ctl_addr == 0
EIO I/O error: reset timed out or hardware error
notes:
Abort any current command, prevent anything else from being
queued, execute a reset on the device, and issue BLKRRPART
ioctl on the block device.
Execute a reset on the device as soon as the current IO
operation has completed.
Executes an ATAPI soft reset if applicable, otherwise
executes an ATA soft reset on the controller.

View File

@ -433,4 +433,16 @@ config VIRTIO_BLK
This is the virtual block driver for virtio. It can be used with
lguest or QEMU based VMMs (like KVM or Xen). Say Y or M.
config BLK_DEV_HD
bool "Very old hard disk (MFM/RLL/IDE) driver"
depends on HAVE_IDE
depends on !ARM || ARCH_RPC || ARCH_SHARK || BROKEN
help
This is a very old hard disk driver that lacks the enhanced
functionality of the newer ones.
It is required for systems with ancient MFM/RLL/ESDI drives.
If unsure, say N.
endif # BLK_DEV

View File

@ -29,5 +29,6 @@ obj-$(CONFIG_VIRTIO_BLK) += virtio_blk.o
obj-$(CONFIG_VIODASD) += viodasd.o
obj-$(CONFIG_BLK_DEV_SX8) += sx8.o
obj-$(CONFIG_BLK_DEV_UB) += ub.o
obj-$(CONFIG_BLK_DEV_HD) += hd.o
obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o

View File

@ -37,7 +37,6 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/mc146818rtc.h> /* CMOS defines */
#include <linux/init.h>
#include <linux/blkpg.h>
#include <linux/hdreg.h>
@ -812,4 +811,4 @@ static int __init parse_hd_setup(char *line)
}
__setup("hd=", parse_hd_setup);
module_init(hd_init);
late_initcall(hd_init);

View File

@ -98,6 +98,9 @@ if BLK_DEV_IDE
comment "Please see Documentation/ide/ide.txt for help/info on IDE drives"
config IDE_TIMINGS
bool
config IDE_ATAPI
bool
@ -326,6 +329,7 @@ config BLK_DEV_PLATFORM
config BLK_DEV_CMD640
tristate "CMD640 chipset bugfix/support"
depends on X86
select IDE_TIMINGS
---help---
The CMD-Technologies CMD640 IDE chip is used on many common 486 and
Pentium motherboards, usually in combination with a "Neptune" or
@ -455,6 +459,7 @@ config BLK_DEV_AEC62XX
config BLK_DEV_ALI15X3
tristate "ALI M15x3 chipset support"
select IDE_TIMINGS
select BLK_DEV_IDEDMA_PCI
help
This driver ensures (U)DMA support for ALI 1533, 1543 and 1543C
@ -469,6 +474,7 @@ config BLK_DEV_ALI15X3
config BLK_DEV_AMD74XX
tristate "AMD and nVidia IDE support"
depends on !ARM
select IDE_TIMINGS
select BLK_DEV_IDEDMA_PCI
help
This driver adds explicit support for AMD-7xx and AMD-8111 chips
@ -489,6 +495,7 @@ config BLK_DEV_ATIIXP
config BLK_DEV_CMD64X
tristate "CMD64{3|6|8|9} chipset support"
select IDE_TIMINGS
select BLK_DEV_IDEDMA_PCI
help
Say Y here if you have an IDE controller which uses any of these
@ -503,6 +510,7 @@ config BLK_DEV_TRIFLEX
config BLK_DEV_CY82C693
tristate "CY82C693 chipset support"
select IDE_TIMINGS
select BLK_DEV_IDEDMA_PCI
help
This driver adds detection and support for the CY82C693 chipset
@ -695,6 +703,7 @@ config BLK_DEV_SIS5513
config BLK_DEV_SL82C105
tristate "Winbond SL82c105 support"
depends on (PPC || ARM)
select IDE_TIMINGS
select BLK_DEV_IDEDMA_PCI
help
If you have a Winbond SL82c105 IDE controller, say Y here to enable
@ -725,6 +734,7 @@ config BLK_DEV_TRM290
config BLK_DEV_VIA82CXXX
tristate "VIA82CXXX chipset support"
select IDE_TIMINGS
select BLK_DEV_IDEDMA_PCI
help
This driver adds explicit support for VIA BusMastering IDE chips.
@ -751,6 +761,7 @@ endif
config BLK_DEV_IDE_PMAC
tristate "PowerMac on-board IDE support"
depends on PPC_PMAC && IDE=y && BLK_DEV_IDE=y
select IDE_TIMINGS
help
This driver provides support for the on-board IDE controller on
most of the recent Apple Power Macintoshes and PowerBooks.
@ -829,13 +840,6 @@ config BLK_DEV_IDE_RAPIDE
Say Y here if you want to support the Yellowstone RapIDE controller
manufactured for use with Acorn computers.
config BLK_DEV_IDE_BAST
tristate "Simtec BAST / Thorcom VR1000 IDE support"
depends on ARM && (ARCH_BAST || MACH_VR1000)
help
Say Y here if you want to support the onboard IDE channels on the
Simtec BAST or the Thorcom VR1000
config IDE_H8300
tristate "H8300 IDE support"
depends on H8300
@ -919,51 +923,12 @@ config BLK_DEV_Q40IDE
config BLK_DEV_PALMCHIP_BK3710
tristate "Palmchip bk3710 IDE controller support"
depends on ARCH_DAVINCI
select IDE_TIMINGS
select BLK_DEV_IDEDMA_SFF
help
Say Y here if you want to support the onchip IDE controller on the
TI DaVinci SoC
config BLK_DEV_MPC8xx_IDE
tristate "MPC8xx IDE support"
depends on 8xx && (LWMON || IVMS8 || IVML24 || TQM8xxL) && IDE=y && BLK_DEV_IDE=y && !PPC_MERGE
help
This option provides support for IDE on Motorola MPC8xx Systems.
Please see 'Type of MPC8xx IDE interface' for details.
If unsure, say N.
choice
prompt "Type of MPC8xx IDE interface"
depends on BLK_DEV_MPC8xx_IDE
default IDE_8xx_PCCARD
config IDE_8xx_PCCARD
bool "8xx_PCCARD"
---help---
Select how the IDE devices are connected to the MPC8xx system:
8xx_PCCARD uses the 8xx internal PCMCIA interface in combination
with a PC Card (e.g. ARGOSY portable Hard Disk Adapter),
ATA PC Card HDDs or ATA PC Flash Cards (example: TQM8xxL
systems)
8xx_DIRECT is used for directly connected IDE devices using the 8xx
internal PCMCIA interface (example: IVMS8 systems)
EXT_DIRECT is used for IDE devices directly connected to the 8xx
bus using some glue logic, but _not_ the 8xx internal
PCMCIA interface (example: IDIF860 systems)
config IDE_8xx_DIRECT
bool "8xx_DIRECT"
config IDE_EXT_DIRECT
bool "EXT_DIRECT"
endchoice
# no isa -> no vlb
if ISA && (ALPHA || X86 || MIPS)
@ -981,6 +946,7 @@ config BLK_DEV_4DRIVES
config BLK_DEV_ALI14XX
tristate "ALI M14xx support"
select IDE_TIMINGS
help
This driver is enabled at runtime using the "ali14xx.probe" kernel
boot parameter. It enables support for the secondary IDE interface
@ -1000,6 +966,7 @@ config BLK_DEV_DTC2278
config BLK_DEV_HT6560B
tristate "Holtek HT6560B support"
select IDE_TIMINGS
help
This driver is enabled at runtime using the "ht6560b.probe" kernel
boot parameter. It enables support for the secondary IDE interface
@ -1009,6 +976,7 @@ config BLK_DEV_HT6560B
config BLK_DEV_QD65XX
tristate "QDI QD65xx support"
select IDE_TIMINGS
help
This driver is enabled at runtime using the "qd65xx.probe" kernel
boot parameter. It permits faster I/O speeds to be set. See the
@ -1032,30 +1000,4 @@ config BLK_DEV_IDEDMA
endif
config BLK_DEV_HD_ONLY
bool "Old hard disk (MFM/RLL/IDE) driver"
depends on !ARM || ARCH_RPC || ARCH_SHARK || BROKEN
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
reasons. Some older systems have strange timing problems and seem to
work only with the old driver (which itself does not work with some
newer systems). The other reason is that the old driver is smaller,
since it lacks the enhanced functionality of the new one. This makes
it a good choice for systems with very tight memory restrictions, or
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_ONLY
endif # IDE

View File

@ -11,9 +11,11 @@
EXTRA_CFLAGS += -Idrivers/ide
ide-core-y += ide.o ide-io.o ide-iops.o ide-lib.o ide-probe.o ide-taskfile.o
ide-core-y += ide.o ide-io.o ide-iops.o ide-lib.o ide-probe.o ide-taskfile.o \
ide-pio-blacklist.o
# core IDE code
ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o
ide-core-$(CONFIG_IDE_ATAPI) += ide-atapi.o
ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o
ide-core-$(CONFIG_BLK_DEV_IDEDMA) += ide-dma.o
@ -59,9 +61,3 @@ ifeq ($(CONFIG_BLK_DEV_PLATFORM), y)
endif
obj-$(CONFIG_BLK_DEV_IDE) += arm/ mips/
# old hd driver must be last
ifeq ($(CONFIG_BLK_DEV_HD), y)
hd-core-y += legacy/hd.o
obj-y += hd-core.o
endif

View File

@ -1,7 +1,6 @@
obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o
obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o
obj-$(CONFIG_BLK_DEV_IDE_BAST) += bast-ide.o
obj-$(CONFIG_BLK_DEV_PALMCHIP_BK3710) += palm_bk3710.o
ifeq ($(CONFIG_IDE_ARM), m)

View File

@ -1,90 +0,0 @@
/*
* Copyright (c) 2003-2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <asm/mach-types.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/arch/map.h>
#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;
hw_regs_t hw;
int i;
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
memset(&hw, 0, sizeof(hw));
base += BAST_IDE_CS;
aux += BAST_IDE_CS;
for (i = 0; i <= 7; i++) {
hw.io_ports_array[i] = (unsigned long)base;
base += 0x20;
}
hw.io_ports.ctl_addr = aux + (6 * 0x20);
hw.irq = irq;
hw.chipset = ide_generic;
hwif = ide_find_port();
if (hwif == NULL)
goto out;
i = hwif->index;
ide_init_port_data(hwif, i);
ide_init_port_hw(hwif, &hw);
hwif->port_ops = NULL;
idx[0] = i;
ide_device_add(idx, NULL);
out:
return 0;
}
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()))
return 0;
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);
return 0;
}
module_init(bastide_init);
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Simtec BAST / Thorcom VR1000 IDE driver");

View File

@ -21,6 +21,8 @@
#include <asm/dma.h>
#include <asm/ecard.h>
#define DRV_NAME "icside"
#define ICS_IDENT_OFFSET 0x2280
#define ICS_ARCIN_V5_INTRSTAT 0x0000
@ -68,6 +70,7 @@ struct icside_state {
unsigned int enabled;
void __iomem *irq_port;
void __iomem *ioc_base;
unsigned int sel;
unsigned int type;
ide_hwif_t *hwif[2];
};
@ -165,7 +168,8 @@ static const expansioncard_ops_t icside_ops_arcin_v6 = {
static void icside_maskproc(ide_drive_t *drive, int mask)
{
ide_hwif_t *hwif = HWIF(drive);
struct icside_state *state = hwif->hwif_data;
struct expansion_card *ec = ECARD_DEV(hwif->dev);
struct icside_state *state = ecard_get_drvdata(ec);
unsigned long flags;
local_irq_save(flags);
@ -308,6 +312,7 @@ static int icside_dma_setup(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
struct expansion_card *ec = ECARD_DEV(hwif->dev);
struct icside_state *state = ecard_get_drvdata(ec);
struct request *rq = hwif->hwgroup->rq;
unsigned int dma_mode;
@ -331,7 +336,7 @@ static int icside_dma_setup(ide_drive_t *drive)
/*
* Route the DMA signals to the correct interface.
*/
writeb(hwif->select_data, hwif->config_data);
writeb(state->sel | hwif->channel, state->ioc_base);
/*
* Select the correct timing for this drive.
@ -359,7 +364,8 @@ static void icside_dma_exec_cmd(ide_drive_t *drive, u8 cmd)
static int icside_dma_test_irq(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
struct icside_state *state = hwif->hwif_data;
struct expansion_card *ec = ECARD_DEV(hwif->dev);
struct icside_state *state = ecard_get_drvdata(ec);
return readb(state->irq_port +
(hwif->channel ?
@ -411,36 +417,24 @@ 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)
static void icside_setup_ports(hw_regs_t *hw, 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();
if (hwif) {
/*
* Ensure we're using MMIO
*/
default_hwif_mmiops(hwif);
hw->io_ports.data_addr = port;
hw->io_ports.error_addr = port + (1 << info->stepping);
hw->io_ports.nsect_addr = port + (2 << info->stepping);
hw->io_ports.lbal_addr = port + (3 << info->stepping);
hw->io_ports.lbam_addr = port + (4 << info->stepping);
hw->io_ports.lbah_addr = port + (5 << info->stepping);
hw->io_ports.device_addr = port + (6 << info->stepping);
hw->io_ports.status_addr = port + (7 << info->stepping);
hw->io_ports.ctl_addr = (unsigned long)base + info->ctrloffset;
hwif->io_ports.data_addr = port;
hwif->io_ports.error_addr = port + (1 << info->stepping);
hwif->io_ports.nsect_addr = port + (2 << info->stepping);
hwif->io_ports.lbal_addr = port + (3 << info->stepping);
hwif->io_ports.lbam_addr = port + (4 << info->stepping);
hwif->io_ports.lbah_addr = port + (5 << info->stepping);
hwif->io_ports.device_addr = port + (6 << info->stepping);
hwif->io_ports.status_addr = port + (7 << info->stepping);
hwif->io_ports.ctl_addr =
(unsigned long)base + info->ctrloffset;
hwif->irq = ec->irq;
hwif->chipset = ide_acorn;
hwif->gendev.parent = &ec->dev;
hwif->dev = &ec->dev;
}
return hwif;
hw->irq = ec->irq;
hw->dev = &ec->dev;
hw->chipset = ide_acorn;
}
static int __init
@ -449,6 +443,7 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec)
ide_hwif_t *hwif;
void __iomem *base;
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
hw_regs_t hw;
base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
if (!base)
@ -466,12 +461,19 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec)
*/
icside_irqdisable_arcin_v5(ec, 0);
hwif = icside_setup(base, &icside_cardinfo_v5, ec);
icside_setup_ports(&hw, base, &icside_cardinfo_v5, ec);
hwif = ide_find_port();
if (!hwif)
return -ENODEV;
ide_init_port_hw(hwif, &hw);
default_hwif_mmiops(hwif);
state->hwif[0] = hwif;
ecard_set_drvdata(ec, state);
idx[0] = hwif->index;
ide_device_add(idx, NULL);
@ -497,6 +499,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
int ret;
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
struct ide_port_info d = icside_v6_port_info;
hw_regs_t hw[2];
ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
if (!ioc_base) {
@ -525,43 +528,47 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
state->irq_port = easi_base;
state->ioc_base = ioc_base;
state->sel = sel;
/*
* Be on the safe side - disable interrupts
*/
icside_irqdisable_arcin_v6(ec, 0);
icside_setup_ports(&hw[0], easi_base, &icside_cardinfo_v6_1, ec);
icside_setup_ports(&hw[1], easi_base, &icside_cardinfo_v6_2, ec);
/*
* Find and register the interfaces.
*/
hwif = icside_setup(easi_base, &icside_cardinfo_v6_1, ec);
mate = icside_setup(easi_base, &icside_cardinfo_v6_2, ec);
hwif = ide_find_port();
if (hwif == NULL)
return -ENODEV;
if (!hwif || !mate) {
ret = -ENODEV;
goto out;
ide_init_port_hw(hwif, &hw[0]);
default_hwif_mmiops(hwif);
idx[0] = hwif->index;
mate = ide_find_port();
if (mate) {
ide_init_port_hw(mate, &hw[1]);
default_hwif_mmiops(mate);
idx[1] = mate->index;
}
state->hwif[0] = hwif;
state->hwif[1] = mate;
hwif->hwif_data = state;
hwif->config_data = (unsigned long)ioc_base;
hwif->select_data = sel;
ecard_set_drvdata(ec, state);
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)) {
if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) {
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;
ide_device_add(idx, &d);
return 0;
@ -627,10 +634,8 @@ icside_probe(struct expansion_card *ec, const struct ecard_id *id)
break;
}
if (ret == 0) {
ecard_set_drvdata(ec, state);
if (ret == 0)
goto out;
}
kfree(state);
release:

View File

@ -74,8 +74,6 @@ struct palm_bk3710_udmatiming {
#define BK3710_IORDYTMP 0x78
#define BK3710_IORDYTMS 0x7C
#include "../ide-timing.h"
static unsigned ideclk_period; /* in nanoseconds */
static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = {
@ -402,7 +400,6 @@ static int __devinit palm_bk3710_probe(struct platform_device *pdev)
i = hwif->index;
ide_init_port_data(hwif, i);
ide_init_port_hw(hwif, &hw);
default_hwif_mmiops(hwif);

View File

@ -11,6 +11,10 @@
#include <asm/ecard.h>
static struct const ide_port_info rapide_port_info = {
.host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
};
static void rapide_setup_ports(hw_regs_t *hw, void __iomem *base,
void __iomem *ctrl, unsigned int sz, int irq)
{
@ -44,26 +48,27 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
goto release;
}
memset(&hw, 0, sizeof(hw));
rapide_setup_ports(&hw, base, base + 0x818, 1 << 6, ec->irq);
hw.chipset = ide_generic;
hw.dev = &ec->dev;
hwif = ide_find_port();
if (hwif) {
memset(&hw, 0, sizeof(hw));
rapide_setup_ports(&hw, base, base + 0x818, 1 << 6, ec->irq);
hw.chipset = ide_generic;
hw.dev = &ec->dev;
ide_init_port_hw(hwif, &hw);
hwif->host_flags = IDE_HFLAG_MMIO;
default_hwif_mmiops(hwif);
idx[0] = hwif->index;
ide_device_add(idx, NULL);
ecard_set_drvdata(ec, hwif);
goto out;
if (hwif == NULL) {
ret = -ENOENT;
goto release;
}
ide_init_port_hw(hwif, &hw);
default_hwif_mmiops(hwif);
idx[0] = hwif->index;
ide_device_add(idx, &rapide_port_info);
ecard_set_drvdata(ec, hwif);
goto out;
release:
ecard_release_resources(ec);
out:

View File

@ -8,6 +8,8 @@
#include <asm/io.h>
#include <asm/irq.h>
#define DRV_NAME "ide-h8300"
#define bswap(d) \
({ \
u16 r; \
@ -176,6 +178,10 @@ static inline void hwif_setup(ide_hwif_t *hwif)
hwif->output_data = h8300_output_data;
}
static const struct ide_port_info h8300_port_info = {
.host_flags = IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_NO_DMA,
};
static int __init h8300_ide_init(void)
{
hw_regs_t hw;
@ -183,6 +189,8 @@ static int __init h8300_ide_init(void)
int index;
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
printk(KERN_INFO DRV_NAME ": H8/300 generic IDE interface\n");
if (!request_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8, "ide-h8300"))
goto out_busy;
if (!request_region(CONFIG_H8300_IDE_ALT, H8300_IDE_GAP, "ide-h8300")) {
@ -192,22 +200,17 @@ static int __init h8300_ide_init(void)
hw_setup(&hw);
hwif = ide_find_port();
if (hwif == NULL) {
printk(KERN_ERR "ide-h8300: IDE I/F register failed\n");
hwif = ide_find_port_slot(&h8300_port_info);
if (hwif == NULL)
return -ENOENT;
}
index = hwif->index;
ide_init_port_data(hwif, index);
ide_init_port_hw(hwif, &hw);
hwif_setup(hwif);
hwif->host_flags = IDE_HFLAG_NO_IO_32BIT;
printk(KERN_INFO "ide%d: H8/300 generic IDE interface\n", index);
idx[0] = index;
ide_device_add(idx, NULL);
ide_device_add(idx, &h8300_port_info);
return 0;

View File

@ -517,14 +517,9 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
int xferlen,
ide_handler_t *handler)
{
ide_startstop_t startstop;
struct cdrom_info *info = drive->driver_data;
ide_hwif_t *hwif = drive->hwif;
/* 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_ops->dma_setup(drive);
@ -603,28 +598,6 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *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, NULL, &dum, sizeof(dum));
len -= sizeof(dum);
}
}
static void ide_cd_drain_data(ide_drive_t *drive, int nsects)
{
while (nsects > 0) {
static char dum[SECTOR_SIZE];
drive->hwif->input_data(drive, NULL, dum, sizeof(dum));
nsects--;
}
}
/*
* Check the contents of the interrupt reason register from the cdrom
* and attempt to recover if there are problems. Returns 0 if everything's
@ -640,15 +613,12 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
if (ireason == (!rw << 1))
return 0;
else if (ireason == (rw << 1)) {
ide_hwif_t *hwif = drive->hwif;
xfer_func_t *xf;
/* whoops... */
printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
drive->name, __func__);
xf = rw ? hwif->output_data : hwif->input_data;
ide_cd_pad_transfer(drive, xf, len);
ide_pad_transfer(drive, rw, len);
} else if (rw == 0 && ireason == 1) {
/*
* Some drives (ASUS) seem to tell us that status info is
@ -696,16 +666,9 @@ static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
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.
*/
static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive,
struct request *rq)
{
struct request *rq = HWGROUP(drive)->rq;
if (rq_data_dir(rq) == READ) {
unsigned short sectors_per_frame =
queue_hardsect_size(drive->queue) >> SECTOR_BITS;
@ -742,6 +705,19 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
/* set up the command */
rq->timeout = ATAPI_WAIT_PC;
return ide_started;
}
/*
* 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)
{
struct request *rq = drive->hwif->hwgroup->rq;
/* send the command to the drive and return */
return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
}
@ -768,9 +744,8 @@ static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive)
return ide_stopped;
}
static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive)
static void ide_cd_prepare_seek_request(ide_drive_t *drive, struct request *rq)
{
struct request *rq = HWGROUP(drive)->rq;
sector_t frame = rq->sector;
sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS);
@ -780,17 +755,13 @@ static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive)
put_unaligned(cpu_to_be32(frame), (unsigned int *) &rq->cmd[2]);
rq->timeout = ATAPI_WAIT_PC;
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_continuation(ide_drive_t *drive)
{
struct cdrom_info *info = drive->driver_data;
struct request *rq = drive->hwif->hwgroup->rq;
info->dma = 0;
info->start_seek = jiffies;
return cdrom_start_packet_command(drive, 0,
cdrom_start_seek_continuation);
return cdrom_transfer_packet_command(drive, rq, &cdrom_seek_intr);
}
/*
@ -1011,7 +982,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
- bio_cur_sectors(rq->bio),
thislen >> 9);
if (nskip > 0) {
ide_cd_drain_data(drive, nskip);
ide_pad_transfer(drive, write, nskip << 9);
rq->current_nr_sectors -= nskip;
thislen -= (nskip << 9);
}
@ -1048,7 +1019,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
* If the buffers are full, pipe the rest into
* oblivion.
*/
ide_cd_drain_data(drive, thislen >> 9);
ide_pad_transfer(drive, 0, thislen);
else {
printk(KERN_ERR "%s: confused, missing data\n",
drive->name);
@ -1096,7 +1067,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
/* pad, if necessary */
if (!blk_fs_request(rq) && len > 0)
ide_cd_pad_transfer(drive, xferfunc, len);
ide_pad_transfer(drive, write, len);
if (blk_pc_request(rq)) {
timeout = rq->timeout;
@ -1165,21 +1136,17 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
if (write)
cd->devinfo.media_written = 1;
/* start sending the read/write request to the drive */
return cdrom_start_packet_command(drive, 32768, cdrom_start_rw_cont);
return ide_started;
}
static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive)
{
struct request *rq = HWGROUP(drive)->rq;
if (!rq->timeout)
rq->timeout = ATAPI_WAIT_PC;
return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
}
static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
{
struct cdrom_info *info = drive->driver_data;
@ -1191,10 +1158,16 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
info->dma = 0;
/* sg request */
if (rq->bio) {
int mask = drive->queue->dma_alignment;
unsigned long addr =
(unsigned long)page_address(bio_page(rq->bio));
if (rq->bio || ((rq->cmd_type == REQ_TYPE_ATA_PC) && rq->data_len)) {
struct request_queue *q = drive->queue;
unsigned int alignment;
unsigned long addr;
unsigned long stack_mask = ~(THREAD_SIZE - 1);
if (rq->bio)
addr = (unsigned long)bio_data(rq->bio);
else
addr = (unsigned long)rq->data;
info->dma = drive->using_dma;
@ -1204,23 +1177,25 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
* NOTE! The "len" and "addr" checks should possibly have
* separate masks.
*/
if ((rq->data_len & 15) || (addr & mask))
alignment = queue_dma_alignment(q) | q->dma_pad_mask;
if (addr & alignment || rq->data_len & alignment)
info->dma = 0;
if (!((addr & stack_mask) ^
((unsigned long)current->stack & stack_mask)))
info->dma = 0;
}
/* 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,
static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
sector_t block)
{
ide_startstop_t action;
struct cdrom_info *info = drive->driver_data;
ide_handler_t *fn;
int xferlen;
if (blk_fs_request(rq)) {
if (info->cd_flags & IDE_CD_FLAG_SEEKING) {
@ -1240,29 +1215,48 @@ static ide_startstop_t ide_do_rw_cdrom(ide_drive_t *drive, struct request *rq,
}
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
action = cdrom_start_rw(drive, rq);
IDECD_SEEK_THRESHOLD) &&
drive->dsc_overlap) {
xferlen = 0;
fn = cdrom_start_seek_continuation;
info->dma = 0;
info->start_seek = jiffies;
ide_cd_prepare_seek_request(drive, rq);
} else {
xferlen = 32768;
fn = cdrom_start_rw_cont;
if (cdrom_start_rw(drive, rq) == ide_stopped)
return ide_stopped;
if (ide_cd_prepare_rw_request(drive, rq) == ide_stopped)
return ide_stopped;
}
info->last_block = block;
return action;
} else if (blk_sense_request(rq) || blk_pc_request(rq) ||
rq->cmd_type == REQ_TYPE_ATA_PC) {
return cdrom_do_block_pc(drive, rq);
xferlen = rq->data_len;
fn = cdrom_do_newpc_cont;
if (!rq->timeout)
rq->timeout = ATAPI_WAIT_PC;
cdrom_do_block_pc(drive, rq);
} else if (blk_special_request(rq)) {
/* right now this can only be a reset... */
cdrom_end_request(drive, 1);
return ide_stopped;
} else {
blk_dump_rq_flags(rq, "ide-cd bad flags");
cdrom_end_request(drive, 0);
return ide_stopped;
}
blk_dump_rq_flags(rq, "ide-cd bad flags");
cdrom_end_request(drive, 0);
return ide_stopped;
return cdrom_start_packet_command(drive, xferlen, fn);
}
/*
* Ioctl handling.
*
@ -1872,6 +1866,7 @@ static int ide_cdrom_setup(ide_drive_t *drive)
blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn);
blk_queue_dma_alignment(drive->queue, 31);
blk_queue_update_dma_pad(drive->queue, 15);
drive->queue->unplug_delay = (1 * HZ) / 1000;
if (!drive->queue->unplug_delay)
drive->queue->unplug_delay = 1;
@ -1954,10 +1949,9 @@ static ide_driver_t ide_cdrom_driver = {
.version = IDECD_VERSION,
.media = ide_cdrom,
.supports_dsc_overlap = 1,
.do_request = ide_do_rw_cdrom,
.do_request = ide_cd_do_request,
.end_request = ide_end_request,
.error = __ide_error,
.abort = __ide_abort,
#ifdef CONFIG_IDE_PROC_FS
.proc = idecd_proc,
#endif

View File

@ -985,7 +985,6 @@ static ide_driver_t idedisk_driver = {
.do_request = ide_do_rw_disk,
.end_request = ide_end_request,
.error = __ide_error,
.abort = __ide_abort,
#ifdef CONFIG_IDE_PROC_FS
.proc = idedisk_proc,
#endif

View File

@ -351,10 +351,7 @@ static void ide_floppy_callback(ide_drive_t *drive)
static void idefloppy_init_pc(struct ide_atapi_pc *pc)
{
memset(pc->c, 0, 12);
pc->retries = 0;
pc->flags = 0;
pc->req_xfer = 0;
memset(pc, 0, sizeof(*pc));
pc->buf = pc->pc_buf;
pc->buf_size = IDEFLOPPY_PC_BUFFER_SIZE;
pc->callback = ide_floppy_callback;
@ -561,12 +558,6 @@ static void idefloppy_create_start_stop_cmd(struct ide_atapi_pc *pc, int start)
pc->c[4] = start;
}
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,
struct ide_atapi_pc *pc, struct request *rq,
unsigned long sector)
@ -711,10 +702,10 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
set_disk_ro(floppy->disk, floppy->wp);
page = &pc.buf[8];
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]);
transfer_rate = be16_to_cpup((__be16 *)&pc.buf[8 + 2]);
sector_size = be16_to_cpup((__be16 *)&pc.buf[8 + 6]);
cyls = be16_to_cpup((__be16 *)&pc.buf[8 + 8]);
rpm = be16_to_cpup((__be16 *)&pc.buf[8 + 28]);
heads = pc.buf[8 + 4];
sectors = pc.buf[8 + 5];
@ -789,8 +780,8 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
for (i = 0; i < desc_cnt; i++) {
unsigned int desc_start = 4 + i*8;
blocks = be32_to_cpu(*(u32 *)&pc.buf[desc_start]);
length = be16_to_cpu(*(u16 *)&pc.buf[desc_start + 6]);
blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]);
length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]);
debug_log("Descriptor %d: %dkB, %d blocks, %d sector size\n",
i, blocks * length / 1024, blocks, length);
@ -911,8 +902,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.buf[desc_start]);
length = be16_to_cpu(*(u16 *)&pc.buf[desc_start + 6]);
blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]);
length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]);
if (put_user(blocks, argp))
return(-EFAULT);
@ -1138,7 +1129,6 @@ static ide_driver_t idefloppy_driver = {
.do_request = idefloppy_do_request,
.end_request = idefloppy_end_request,
.error = __ide_error,
.abort = __ide_abort,
#ifdef CONFIG_IDE_PROC_FS
.proc = idefloppy_proc,
#endif
@ -1166,7 +1156,9 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
/* Just in case */
idefloppy_create_test_unit_ready_cmd(&pc);
idefloppy_init_pc(&pc);
pc.c[0] = GPCMD_TEST_UNIT_READY;
if (idefloppy_queue_pc_tail(drive, &pc)) {
idefloppy_create_start_stop_cmd(&pc, 1);
(void) idefloppy_queue_pc_tail(drive, &pc);

View File

@ -504,55 +504,6 @@ ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat)
EXPORT_SYMBOL_GPL(ide_error);
ide_startstop_t __ide_abort(ide_drive_t *drive, struct request *rq)
{
if (drive->media != ide_disk)
rq->errors |= ERROR_RESET;
ide_kill_rq(drive, rq);
return ide_stopped;
}
EXPORT_SYMBOL_GPL(__ide_abort);
/**
* ide_abort - abort pending IDE operations
* @drive: drive the error occurred on
* @msg: message to report
*
* ide_abort kills and cleans up when we are about to do a
* host initiated reset on active commands. Longer term we
* want handlers to have sensible abort handling themselves
*
* This differs fundamentally from ide_error because in
* this case the command is doing just fine when we
* blow it away.
*/
ide_startstop_t ide_abort(ide_drive_t *drive, const char *msg)
{
struct request *rq;
if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
return ide_stopped;
/* retry only "normal" I/O: */
if (!blk_fs_request(rq)) {
rq->errors = 1;
ide_end_drive_cmd(drive, BUSY_STAT, 0);
return ide_stopped;
}
if (rq->rq_disk) {
ide_driver_t *drv;
drv = *(ide_driver_t **)rq->rq_disk->private_data;
return drv->abort(drive, rq);
} else
return __ide_abort(drive, rq);
}
static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
{
tf->nsect = drive->sect;
@ -766,6 +717,18 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
return ide_stopped;
}
static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq)
{
switch (rq->cmd[0]) {
case REQ_DRIVE_RESET:
return ide_do_reset(drive);
default:
blk_dump_rq_flags(rq, "ide_special_rq - bad request");
ide_end_request(drive, 0, 0);
return ide_stopped;
}
}
static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
{
struct request_pm_state *pm = rq->data;
@ -869,7 +832,16 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
pm->pm_step == ide_pm_state_completed)
ide_complete_pm_request(drive, rq);
return startstop;
}
} else if (!rq->rq_disk && blk_special_request(rq))
/*
* TODO: Once all ULDs have been modified to
* check for specific op codes rather than
* blindly accepting any special request, the
* check for ->rq_disk above may be replaced
* by a more suitable mechanism or even
* dropped entirely.
*/
return ide_special_rq(drive, rq);
drv = *(ide_driver_t **)rq->rq_disk->private_data;
return drv->do_request(drive, rq, block);

View File

@ -905,6 +905,14 @@ void ide_execute_pkt_cmd(ide_drive_t *drive)
}
EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd);
static inline void ide_complete_drive_reset(ide_drive_t *drive, int err)
{
struct request *rq = drive->hwif->hwgroup->rq;
if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET)
ide_end_request(drive, err ? err : 1, 0);
}
/* needed below */
static ide_startstop_t do_reset1 (ide_drive_t *, int);
@ -940,7 +948,7 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
}
/* done polling */
hwgroup->polling = 0;
hwgroup->resetting = 0;
ide_complete_drive_reset(drive, 0);
return ide_stopped;
}
@ -956,12 +964,14 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
ide_hwif_t *hwif = HWIF(drive);
const struct ide_port_ops *port_ops = hwif->port_ops;
u8 tmp;
int err = 0;
if (port_ops && port_ops->reset_poll) {
if (port_ops->reset_poll(drive)) {
err = port_ops->reset_poll(drive);
if (err) {
printk(KERN_ERR "%s: host reset_poll failure for %s.\n",
hwif->name, drive->name);
return ide_stopped;
goto out;
}
}
@ -975,6 +985,7 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
}
printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp);
drive->failures++;
err = -EIO;
} else {
printk("%s: reset: ", hwif->name);
tmp = ide_read_error(drive);
@ -1001,10 +1012,12 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
if (tmp & 0x80)
printk("; slave: failed");
printk("\n");
err = -EIO;
}
}
out:
hwgroup->polling = 0; /* done polling */
hwgroup->resetting = 0; /* done reset attempt */
ide_complete_drive_reset(drive, err);
return ide_stopped;
}
@ -1090,7 +1103,6 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
/* For an ATAPI device, first try an ATAPI SRST. */
if (drive->media != ide_disk && !do_not_try_atapi) {
hwgroup->resetting = 1;
pre_reset(drive);
SELECT_DRIVE(drive);
udelay (20);
@ -1112,10 +1124,10 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
if (io_ports->ctl_addr == 0) {
spin_unlock_irqrestore(&ide_lock, flags);
ide_complete_drive_reset(drive, -ENXIO);
return ide_stopped;
}
hwgroup->resetting = 1;
/*
* Note that we also set nIEN while resetting the device,
* to mask unwanted interrupts from the interface during the reset.

View File

@ -1,26 +1,11 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/genhd.h>
#include <linux/blkpg.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/bitops.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm/io.h>
static const char *udma_str[] =
{ "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44",
"UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" };
@ -90,142 +75,6 @@ static u8 ide_rate_filter(ide_drive_t *drive, u8 speed)
return min(speed, mode);
}
/*
* Standard (generic) timings for PIO modes, from ATA2 specification.
* These timings are for access to the IDE data port register *only*.
* Some drives may specify a mode, while also specifying a different
* value for cycle_time (from drive identification data).
*/
const ide_pio_timings_t ide_pio_timings[6] = {
{ 70, 165, 600 }, /* PIO Mode 0 */
{ 50, 125, 383 }, /* PIO Mode 1 */
{ 30, 100, 240 }, /* PIO Mode 2 */
{ 30, 80, 180 }, /* PIO Mode 3 with IORDY */
{ 25, 70, 120 }, /* PIO Mode 4 with IORDY */
{ 20, 50, 100 } /* PIO Mode 5 with IORDY (nonstandard) */
};
EXPORT_SYMBOL_GPL(ide_pio_timings);
/*
* Shared data/functions for determining best PIO mode for an IDE drive.
* Most of this stuff originally lived in cmd640.c, and changes to the
* ide_pio_blacklist[] table should be made with EXTREME CAUTION to avoid
* breaking the fragile cmd640.c support.
*/
/*
* Black list. Some drives incorrectly report their maximal PIO mode,
* at least in respect to CMD640. Here we keep info on some known drives.
*/
static struct ide_pio_info {
const char *name;
int pio;
} ide_pio_blacklist [] = {
{ "Conner Peripherals 540MB - CFS540A", 3 },
{ "WDC AC2700", 3 },
{ "WDC AC2540", 3 },
{ "WDC AC2420", 3 },
{ "WDC AC2340", 3 },
{ "WDC AC2250", 0 },
{ "WDC AC2200", 0 },
{ "WDC AC21200", 4 },
{ "WDC AC2120", 0 },
{ "WDC AC2850", 3 },
{ "WDC AC1270", 3 },
{ "WDC AC1170", 1 },
{ "WDC AC1210", 1 },
{ "WDC AC280", 0 },
{ "WDC AC31000", 3 },
{ "WDC AC31200", 3 },
{ "Maxtor 7131 AT", 1 },
{ "Maxtor 7171 AT", 1 },
{ "Maxtor 7213 AT", 1 },
{ "Maxtor 7245 AT", 1 },
{ "Maxtor 7345 AT", 1 },
{ "Maxtor 7546 AT", 3 },
{ "Maxtor 7540 AV", 3 },
{ "SAMSUNG SHD-3121A", 1 },
{ "SAMSUNG SHD-3122A", 1 },
{ "SAMSUNG SHD-3172A", 1 },
{ "ST5660A", 3 },
{ "ST3660A", 3 },
{ "ST3630A", 3 },
{ "ST3655A", 3 },
{ "ST3391A", 3 },
{ "ST3390A", 1 },
{ "ST3600A", 1 },
{ "ST3290A", 0 },
{ "ST3144A", 0 },
{ "ST3491A", 1 }, /* reports 3, should be 1 or 2 (depending on */
/* drive) according to Seagates FIND-ATA program */
{ "QUANTUM ELS127A", 0 },
{ "QUANTUM ELS170A", 0 },
{ "QUANTUM LPS240A", 0 },
{ "QUANTUM LPS210A", 3 },
{ "QUANTUM LPS270A", 3 },
{ "QUANTUM LPS365A", 3 },
{ "QUANTUM LPS540A", 3 },
{ "QUANTUM LIGHTNING 540A", 3 },
{ "QUANTUM LIGHTNING 730A", 3 },
{ "QUANTUM FIREBALL_540", 3 }, /* Older Quantum Fireballs don't work */
{ "QUANTUM FIREBALL_640", 3 },
{ "QUANTUM FIREBALL_1080", 3 },
{ "QUANTUM FIREBALL_1280", 3 },
{ NULL, 0 }
};
/**
* ide_scan_pio_blacklist - check for a blacklisted drive
* @model: Drive model string
*
* This routine searches the ide_pio_blacklist for an entry
* matching the start/whole of the supplied model name.
*
* Returns -1 if no match found.
* Otherwise returns the recommended PIO mode from ide_pio_blacklist[].
*/
static int ide_scan_pio_blacklist (char *model)
{
struct ide_pio_info *p;
for (p = ide_pio_blacklist; p->name != NULL; p++) {
if (strncmp(p->name, model, strlen(p->name)) == 0)
return p->pio;
}
return -1;
}
unsigned int ide_pio_cycle_time(ide_drive_t *drive, u8 pio)
{
struct hd_driveid *id = drive->id;
int cycle_time = 0;
if (id->field_valid & 2) {
if (id->capability & 8)
cycle_time = id->eide_pio_iordy;
else
cycle_time = id->eide_pio;
}
/* conservative "downgrade" for all pre-ATA2 drives */
if (pio < 3) {
if (cycle_time && cycle_time < ide_pio_timings[pio].cycle_time)
cycle_time = 0; /* use standard timing */
}
return cycle_time ? cycle_time : ide_pio_timings[pio].cycle_time;
}
EXPORT_SYMBOL_GPL(ide_pio_cycle_time);
/**
* ide_get_best_pio_mode - get PIO mode from drive
* @drive: drive to consider

View File

@ -0,0 +1,94 @@
/*
* PIO blacklist. Some drives incorrectly report their maximal PIO mode,
* at least in respect to CMD640. Here we keep info on some known drives.
*
* Changes to the ide_pio_blacklist[] should be made with EXTREME CAUTION
* to avoid breaking the fragile cmd640.c support.
*/
#include <linux/string.h>
static struct ide_pio_info {
const char *name;
int pio;
} ide_pio_blacklist [] = {
{ "Conner Peripherals 540MB - CFS540A", 3 },
{ "WDC AC2700", 3 },
{ "WDC AC2540", 3 },
{ "WDC AC2420", 3 },
{ "WDC AC2340", 3 },
{ "WDC AC2250", 0 },
{ "WDC AC2200", 0 },
{ "WDC AC21200", 4 },
{ "WDC AC2120", 0 },
{ "WDC AC2850", 3 },
{ "WDC AC1270", 3 },
{ "WDC AC1170", 1 },
{ "WDC AC1210", 1 },
{ "WDC AC280", 0 },
{ "WDC AC31000", 3 },
{ "WDC AC31200", 3 },
{ "Maxtor 7131 AT", 1 },
{ "Maxtor 7171 AT", 1 },
{ "Maxtor 7213 AT", 1 },
{ "Maxtor 7245 AT", 1 },
{ "Maxtor 7345 AT", 1 },
{ "Maxtor 7546 AT", 3 },
{ "Maxtor 7540 AV", 3 },
{ "SAMSUNG SHD-3121A", 1 },
{ "SAMSUNG SHD-3122A", 1 },
{ "SAMSUNG SHD-3172A", 1 },
{ "ST5660A", 3 },
{ "ST3660A", 3 },
{ "ST3630A", 3 },
{ "ST3655A", 3 },
{ "ST3391A", 3 },
{ "ST3390A", 1 },
{ "ST3600A", 1 },
{ "ST3290A", 0 },
{ "ST3144A", 0 },
{ "ST3491A", 1 }, /* reports 3, should be 1 or 2 (depending on drive)
according to Seagate's FIND-ATA program */
{ "QUANTUM ELS127A", 0 },
{ "QUANTUM ELS170A", 0 },
{ "QUANTUM LPS240A", 0 },
{ "QUANTUM LPS210A", 3 },
{ "QUANTUM LPS270A", 3 },
{ "QUANTUM LPS365A", 3 },
{ "QUANTUM LPS540A", 3 },
{ "QUANTUM LIGHTNING 540A", 3 },
{ "QUANTUM LIGHTNING 730A", 3 },
{ "QUANTUM FIREBALL_540", 3 }, /* Older Quantum Fireballs don't work */
{ "QUANTUM FIREBALL_640", 3 },
{ "QUANTUM FIREBALL_1080", 3 },
{ "QUANTUM FIREBALL_1280", 3 },
{ NULL, 0 }
};
/**
* ide_scan_pio_blacklist - check for a blacklisted drive
* @model: Drive model string
*
* This routine searches the ide_pio_blacklist for an entry
* matching the start/whole of the supplied model name.
*
* Returns -1 if no match found.
* Otherwise returns the recommended PIO mode from ide_pio_blacklist[].
*/
int ide_scan_pio_blacklist(char *model)
{
struct ide_pio_info *p;
for (p = ide_pio_blacklist; p->name != NULL; p++) {
if (strncmp(p->name, model, strlen(p->name)) == 0)
return p->pio;
}
return -1;
}

View File

@ -33,6 +33,8 @@ static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
ide_hwif_t *hwif;
unsigned long base, ctl;
printk(KERN_INFO DRV_NAME ": generic PnP IDE interface\n");
if (!(pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && pnp_irq_valid(dev, 0)))
return -1;
@ -62,10 +64,8 @@ static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
u8 index = hwif->index;
u8 idx[4] = { index, 0xff, 0xff, 0xff };
ide_init_port_data(hwif, index);
ide_init_port_hw(hwif, &hw);
printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index);
pnp_set_drvdata(dev, hwif);
ide_device_add(idx, NULL);

View File

@ -39,6 +39,8 @@
#include <asm/uaccess.h>
#include <asm/io.h>
static ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */
/**
* generic_id - add a generic drive id
* @drive: drive to make an ID block for
@ -1318,10 +1320,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 (port_ops && port_ops->port_init_devs)
port_ops->port_init_devs(hwif);
if (port_ops && port_ops->init_dev)
port_ops->init_dev(drive);
}
}
static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
@ -1473,22 +1475,29 @@ ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d)
for (; i < MAX_HWIFS; i++) {
hwif = &ide_hwifs[i];
if (hwif->chipset == ide_unknown)
return hwif;
goto out_found;
}
} else {
for (i = 2; i < MAX_HWIFS; i++) {
hwif = &ide_hwifs[i];
if (hwif->chipset == ide_unknown)
return hwif;
goto out_found;
}
for (i = 0; i < 2 && i < MAX_HWIFS; i++) {
hwif = &ide_hwifs[i];
if (hwif->chipset == ide_unknown)
return hwif;
goto out_found;
}
}
printk(KERN_ERR "%s: no free slot for interface\n",
d ? d->name : "ide");
return NULL;
out_found:
ide_init_port_data(hwif, i);
return hwif;
}
EXPORT_SYMBOL_GPL(ide_find_port_slot);

View File

@ -2591,7 +2591,6 @@ static ide_driver_t idetape_driver = {
.do_request = idetape_do_request,
.end_request = idetape_end_request,
.error = __ide_error,
.abort = __ide_abort,
#ifdef CONFIG_IDE_PROC_FS
.proc = idetape_proc,
#endif

View File

@ -8,28 +8,18 @@
* The big the bad and the ugly.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/genhd.h>
#include <linux/blkpg.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/bitops.h>
#include <linux/scatterlist.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@ -62,25 +52,6 @@ int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
return ide_raw_taskfile(drive, &args, buf, 1);
}
static int inline task_dma_ok(ide_task_t *task)
{
if (blk_fs_request(task->rq) || (task->tf_flags & IDE_TFLAG_FLAGGED))
return 1;
switch (task->tf.command) {
case WIN_WRITEDMA_ONCE:
case WIN_WRITEDMA:
case WIN_WRITEDMA_EXT:
case WIN_READDMA_ONCE:
case WIN_READDMA:
case WIN_READDMA_EXT:
case WIN_IDENTIFY_DMA:
return 1;
}
return 0;
}
static ide_startstop_t task_no_data_intr(ide_drive_t *);
static ide_startstop_t set_geometry_intr(ide_drive_t *);
static ide_startstop_t recal_intr(ide_drive_t *);
@ -139,8 +110,7 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
WAIT_WORSTCASE, NULL);
return ide_started;
default:
if (task_dma_ok(task) == 0 || drive->using_dma == 0 ||
dma_ops->dma_setup(drive))
if (drive->using_dma == 0 || dma_ops->dma_setup(drive))
return ide_stopped;
dma_ops->dma_exec_cmd(drive, tf->command);
dma_ops->dma_start(drive);
@ -183,7 +153,6 @@ static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
if (stat & (ERR_STAT|DRQ_STAT))
return ide_error(drive, "set_geometry_intr", stat);
BUG_ON(HWGROUP(drive)->handler != NULL);
ide_set_handler(drive, &set_geometry_intr, WAIT_WORSTCASE, NULL);
return ide_started;
}

View File

@ -1,11 +1,7 @@
#ifndef _IDE_TIMING_H
#define _IDE_TIMING_H
/*
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
* Copyright (c) 2007-2008 Bartlomiej Zolnierkiewicz
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@ -27,27 +23,14 @@
#include <linux/kernel.h>
#include <linux/hdreg.h>
#define XFER_PIO_5 0x0d
#define XFER_UDMA_SLOW 0x4f
struct ide_timing {
short mode;
short setup; /* t1 */
short act8b; /* t2 for 8-bit io */
short rec8b; /* t2i for 8-bit io */
short cyc8b; /* t0 for 8-bit io */
short active; /* t2 or tD */
short recover; /* t2i or tK */
short cycle; /* t0 */
short udma; /* t2CYCTYP/2 */
};
#include <linux/ide.h>
#include <linux/module.h>
/*
* PIO 0-5, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds).
* These were taken from ATA/ATAPI-6 standard, rev 0a, except
* for PIO 5, which is a nonstandard extension and UDMA6, which
* is currently supported only by Maxtor drives.
* is currently supported only by Maxtor drives.
*/
static struct ide_timing ide_timing[] = {
@ -61,12 +44,10 @@ static struct ide_timing ide_timing[] = {
{ XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 80 },
{ XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 120 },
{ XFER_UDMA_SLOW, 0, 0, 0, 0, 0, 0, 0, 150 },
{ XFER_MW_DMA_2, 25, 0, 0, 0, 70, 25, 120, 0 },
{ XFER_MW_DMA_1, 45, 0, 0, 0, 80, 50, 150, 0 },
{ XFER_MW_DMA_0, 60, 0, 0, 0, 215, 215, 480, 0 },
{ XFER_SW_DMA_2, 60, 0, 0, 0, 120, 120, 240, 0 },
{ XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 480, 0 },
{ XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 960, 0 },
@ -81,29 +62,46 @@ static struct ide_timing ide_timing[] = {
{ XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960, 0 },
{ -1 }
{ 0xff }
};
#define IDE_TIMING_SETUP 0x01
#define IDE_TIMING_ACT8B 0x02
#define IDE_TIMING_REC8B 0x04
#define IDE_TIMING_CYC8B 0x08
#define IDE_TIMING_8BIT 0x0e
#define IDE_TIMING_ACTIVE 0x10
#define IDE_TIMING_RECOVER 0x20
#define IDE_TIMING_CYCLE 0x40
#define IDE_TIMING_UDMA 0x80
#define IDE_TIMING_ALL 0xff
struct ide_timing *ide_timing_find_mode(u8 speed)
{
struct ide_timing *t;
#define ENOUGH(v,unit) (((v)-1)/(unit)+1)
#define EZ(v,unit) ((v)?ENOUGH(v,unit):0)
for (t = ide_timing; t->mode != speed; t++)
if (t->mode == 0xff)
return NULL;
return t;
}
EXPORT_SYMBOL_GPL(ide_timing_find_mode);
#define XFER_MODE 0xf0
#define XFER_MWDMA 0x20
#define XFER_EPIO 0x01
#define XFER_PIO 0x00
u16 ide_pio_cycle_time(ide_drive_t *drive, u8 pio)
{
struct hd_driveid *id = drive->id;
struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
u16 cycle = 0;
static void ide_timing_quantize(struct ide_timing *t, struct ide_timing *q, int T, int UT)
if (id->field_valid & 2) {
if (id->capability & 8)
cycle = id->eide_pio_iordy;
else
cycle = id->eide_pio;
/* conservative "downgrade" for all pre-ATA2 drives */
if (pio < 3 && cycle < t->cycle)
cycle = 0; /* use standard timing */
}
return cycle ? cycle : t->cycle;
}
EXPORT_SYMBOL_GPL(ide_pio_cycle_time);
#define ENOUGH(v, unit) (((v) - 1) / (unit) + 1)
#define EZ(v, unit) ((v) ? ENOUGH(v, unit) : 0)
static void ide_timing_quantize(struct ide_timing *t, struct ide_timing *q,
int T, int UT)
{
q->setup = EZ(t->setup * 1000, T);
q->act8b = EZ(t->act8b * 1000, T);
@ -115,92 +113,83 @@ static void ide_timing_quantize(struct ide_timing *t, struct ide_timing *q, int
q->udma = EZ(t->udma * 1000, UT);
}
static void ide_timing_merge(struct ide_timing *a, struct ide_timing *b, struct ide_timing *m, unsigned int what)
void ide_timing_merge(struct ide_timing *a, struct ide_timing *b,
struct ide_timing *m, unsigned int what)
{
if (what & IDE_TIMING_SETUP ) m->setup = max(a->setup, b->setup);
if (what & IDE_TIMING_ACT8B ) m->act8b = max(a->act8b, b->act8b);
if (what & IDE_TIMING_REC8B ) m->rec8b = max(a->rec8b, b->rec8b);
if (what & IDE_TIMING_CYC8B ) m->cyc8b = max(a->cyc8b, b->cyc8b);
if (what & IDE_TIMING_ACTIVE ) m->active = max(a->active, b->active);
if (what & IDE_TIMING_RECOVER) m->recover = max(a->recover, b->recover);
if (what & IDE_TIMING_CYCLE ) m->cycle = max(a->cycle, b->cycle);
if (what & IDE_TIMING_UDMA ) m->udma = max(a->udma, b->udma);
if (what & IDE_TIMING_SETUP)
m->setup = max(a->setup, b->setup);
if (what & IDE_TIMING_ACT8B)
m->act8b = max(a->act8b, b->act8b);
if (what & IDE_TIMING_REC8B)
m->rec8b = max(a->rec8b, b->rec8b);
if (what & IDE_TIMING_CYC8B)
m->cyc8b = max(a->cyc8b, b->cyc8b);
if (what & IDE_TIMING_ACTIVE)
m->active = max(a->active, b->active);
if (what & IDE_TIMING_RECOVER)
m->recover = max(a->recover, b->recover);
if (what & IDE_TIMING_CYCLE)
m->cycle = max(a->cycle, b->cycle);
if (what & IDE_TIMING_UDMA)
m->udma = max(a->udma, b->udma);
}
EXPORT_SYMBOL_GPL(ide_timing_merge);
static struct ide_timing* ide_timing_find_mode(short speed)
{
struct ide_timing *t;
for (t = ide_timing; t->mode != speed; t++)
if (t->mode < 0)
return NULL;
return t;
}
static int ide_timing_compute(ide_drive_t *drive, short speed, struct ide_timing *t, int T, int UT)
int ide_timing_compute(ide_drive_t *drive, u8 speed,
struct ide_timing *t, int T, int UT)
{
struct hd_driveid *id = drive->id;
struct ide_timing *s, p;
/*
* Find the mode.
*/
if (!(s = ide_timing_find_mode(speed)))
/*
* Find the mode.
*/
s = ide_timing_find_mode(speed);
if (s == NULL)
return -EINVAL;
/*
* Copy the timing from the table.
*/
/*
* Copy the timing from the table.
*/
*t = *s;
/*
* If the drive is an EIDE drive, it can tell us it needs extended
* PIO/MWDMA cycle timing.
*/
/*
* If the drive is an EIDE drive, it can tell us it needs extended
* PIO/MWDMA cycle timing.
*/
if (id && id->field_valid & 2) { /* EIDE drive */
memset(&p, 0, sizeof(p));
switch (speed & XFER_MODE) {
case XFER_PIO:
if (speed <= XFER_PIO_2) p.cycle = p.cyc8b = id->eide_pio;
else p.cycle = p.cyc8b = id->eide_pio_iordy;
break;
case XFER_MWDMA:
p.cycle = id->eide_dma_min;
break;
}
if (speed <= XFER_PIO_2)
p.cycle = p.cyc8b = id->eide_pio;
else if (speed <= XFER_PIO_5)
p.cycle = p.cyc8b = id->eide_pio_iordy;
else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)
p.cycle = id->eide_dma_min;
ide_timing_merge(&p, t, t, IDE_TIMING_CYCLE | IDE_TIMING_CYC8B);
}
/*
* Convert the timing to bus clock counts.
*/
/*
* Convert the timing to bus clock counts.
*/
ide_timing_quantize(t, t, T, UT);
/*
* Even in DMA/UDMA modes we still use PIO access for IDENTIFY, S.M.A.R.T
* and some other commands. We have to ensure that the DMA cycle timing is
* slower/equal than the fastest PIO timing.
*/
if ((speed & XFER_MODE) != XFER_PIO) {
/*
* Even in DMA/UDMA modes we still use PIO access for IDENTIFY,
* S.M.A.R.T and some other commands. We have to ensure that the
* DMA cycle timing is slower/equal than the fastest PIO timing.
*/
if (speed >= XFER_SW_DMA_0) {
u8 pio = ide_get_best_pio_mode(drive, 255, 5);
ide_timing_compute(drive, XFER_PIO_0 + pio, &p, T, UT);
ide_timing_merge(&p, t, t, IDE_TIMING_ALL);
}
/*
* Lengthen active & recovery time so that cycle time is correct.
*/
/*
* Lengthen active & recovery time so that cycle time is correct.
*/
if (t->act8b + t->rec8b < t->cyc8b) {
t->act8b += (t->cyc8b - (t->act8b + t->rec8b)) / 2;
t->rec8b = t->cyc8b - t->act8b;
@ -213,5 +202,4 @@ static int ide_timing_compute(ide_drive_t *drive, short speed, struct ide_timing
return 0;
}
#endif
EXPORT_SYMBOL_GPL(ide_timing_compute);

View File

@ -50,29 +50,16 @@
#include <linux/types.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/genhd.h>
#include <linux/blkpg.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/completion.h>
#include <linux/reboot.h>
#include <linux/cdrom.h>
#include <linux/seq_file.h>
#include <linux/device.h>
#include <linux/bitops.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm/io.h>
/* default maximum number of failures */
@ -91,8 +78,6 @@ DEFINE_MUTEX(ide_cfg_mtx);
__cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);
EXPORT_SYMBOL(ide_lock);
ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */
static void ide_port_init_devices_data(ide_hwif_t *);
/*
@ -121,7 +106,6 @@ void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
ide_port_init_devices_data(hwif);
}
EXPORT_SYMBOL_GPL(ide_init_port_data);
static void ide_port_init_devices_data(ide_hwif_t *hwif)
{
@ -150,18 +134,6 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif)
}
}
static void __init init_ide_data (void)
{
unsigned int index;
/* Initialise all interface structures */
for (index = 0; index < MAX_HWIFS; ++index) {
ide_hwif_t *hwif = &ide_hwifs[index];
ide_init_port_data(hwif, index);
}
}
void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
{
ide_hwgroup_t *hwgroup = hwif->hwgroup;
@ -312,7 +284,8 @@ void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
memcpy(&hwif->io_ports, &hw->io_ports, sizeof(hwif->io_ports));
hwif->irq = hw->irq;
hwif->chipset = hw->chipset;
hwif->gendev.parent = hw->dev;
hwif->dev = hw->dev;
hwif->gendev.parent = hw->parent ? hw->parent : hw->dev;
hwif->ack_intr = hw->ack_intr;
}
EXPORT_SYMBOL_GPL(ide_init_port_hw);
@ -556,6 +529,22 @@ static int generic_ide_resume(struct device *dev)
return err;
}
static int generic_drive_reset(ide_drive_t *drive)
{
struct request *rq;
int ret = 0;
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_SPECIAL;
rq->cmd_len = 1;
rq->cmd[0] = REQ_DRIVE_RESET;
rq->cmd_flags |= REQ_SOFTBARRIER;
if (blk_execute_rq(drive->queue, NULL, rq, 1))
ret = rq->errors;
blk_put_request(rq);
return ret;
}
int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev,
unsigned int cmd, unsigned long arg)
{
@ -630,33 +619,8 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
/*
* Abort the current command on the
* group if there is one, taking
* care not to allow anything else
* to be queued and to die on the
* spot if we miss one somehow
*/
return generic_drive_reset(drive);
spin_lock_irqsave(&ide_lock, flags);
if (HWGROUP(drive)->resetting) {
spin_unlock_irqrestore(&ide_lock, flags);
return -EBUSY;
}
ide_abort(drive, "drive reset");
BUG_ON(HWGROUP(drive)->handler);
/* Ensure nothing gets queued after we
drop the lock. Reset will clear the busy */
HWGROUP(drive)->busy = 1;
spin_unlock_irqrestore(&ide_lock, flags);
(void) ide_do_reset(drive);
return 0;
case HDIO_GET_BUSSTATE:
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
@ -1021,8 +985,6 @@ static int __init ide_init(void)
goto out_port_class;
}
init_ide_data();
proc_ide_create();
return 0;

View File

@ -117,10 +117,11 @@ static void ali14xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
u8 param1, param2, param3, param4;
unsigned long flags;
int bus_speed = ide_vlb_clk ? ide_vlb_clk : 50;
struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
/* calculate timing, according to PIO mode */
time1 = ide_pio_cycle_time(drive, pio);
time2 = ide_pio_timings[pio].active_time;
time2 = t->active;
param3 = param1 = (time2 * bus_speed + 999) / 1000;
param4 = param2 = (time1 * bus_speed + 999) / 1000 - param1;
if (pio < 3) {

View File

@ -227,7 +227,6 @@ fail_base2:
if (hwif) {
u8 index = hwif->index;
ide_init_port_data(hwif, index);
ide_init_port_hw(hwif, &hw);
idx[i] = index;

View File

@ -111,7 +111,6 @@ static int __init falconide_init(void)
u8 index = hwif->index;
u8 idx[4] = { index, 0xff, 0xff, 0xff };
ide_init_port_data(hwif, index);
ide_init_port_hw(hwif, &hw);
/* Atari has a byte-swapped IDE interface */

View File

@ -185,7 +185,6 @@ found:
if (hwif) {
u8 index = hwif->index;
ide_init_port_data(hwif, index);
ide_init_port_hw(hwif, &hw);
idx[i] = index;

View File

@ -216,6 +216,7 @@ static u8 ht_pio2timings(ide_drive_t *drive, const u8 pio)
if (pio) {
unsigned int cycle_time;
struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
cycle_time = ide_pio_cycle_time(drive, pio);
@ -224,10 +225,8 @@ static u8 ht_pio2timings(ide_drive_t *drive, const u8 pio)
* actual cycle time for recovery and activity
* according system bus speed.
*/
active_time = ide_pio_timings[pio].active_time;
recovery_time = cycle_time
- active_time
- ide_pio_timings[pio].setup_time;
active_time = t->active;
recovery_time = cycle_time - active_time - t->setup;
/*
* Cycle times should be Vesa bus cycles
*/
@ -311,16 +310,16 @@ static void ht6560b_set_pio_mode(ide_drive_t *drive, const u8 pio)
#endif
}
static void __init ht6560b_port_init_devs(ide_hwif_t *hwif)
static void __init ht6560b_init_dev(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
/* Setting default configurations for drives. */
int t = (HT_CONFIG_DEFAULT << 8) | HT_TIMING_DEFAULT;
if (hwif->channel)
t |= (HT_SECONDARY_IF << 8);
hwif->drives[0].drive_data = t;
hwif->drives[1].drive_data = t;
drive->drive_data = t;
}
static int probe_ht6560b;
@ -329,7 +328,7 @@ 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,
.init_dev = ht6560b_init_dev,
.set_pio_mode = ht6560b_set_pio_mode,
.selectproc = ht6560b_selectproc,
};

View File

@ -11,6 +11,21 @@ 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 void ide_4drives_init_dev(ide_drive_t *drive)
{
if (drive->hwif->channel)
drive->select.all ^= 0x20;
}
static const struct ide_port_ops ide_4drives_port_ops = {
.init_dev = ide_4drives_init_dev,
};
static const struct ide_port_info ide_4drives_port_info = {
.port_ops = &ide_4drives_port_ops,
.host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA,
};
static int __init ide_4drives_init(void)
{
ide_hwif_t *hwif, *mate;
@ -49,18 +64,10 @@ static int __init ide_4drives_init(void)
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);
ide_device_add(idx, &ide_4drives_port_info);
return 0;
}

View File

@ -154,6 +154,11 @@ static const struct ide_port_ops idecs_port_ops = {
.quirkproc = ide_undecoded_slave,
};
static const struct ide_port_info idecs_port_info = {
.port_ops = &idecs_port_ops,
.host_flags = IDE_HFLAG_NO_DMA,
};
static ide_hwif_t *idecs_register(unsigned long io, unsigned long ctl,
unsigned long irq, struct pcmcia_device *handle)
{
@ -187,13 +192,11 @@ static ide_hwif_t *idecs_register(unsigned long io, unsigned long ctl,
i = hwif->index;
ide_init_port_data(hwif, i);
ide_init_port_hw(hwif, &hw);
hwif->port_ops = &idecs_port_ops;
idx[0] = i;
ide_device_add(idx, NULL);
ide_device_add(idx, &idecs_port_info);
if (hwif->present)
return hwif;

View File

@ -44,6 +44,10 @@ static void __devinit plat_ide_setup_ports(hw_regs_t *hw,
hw->chipset = ide_generic;
}
static const struct ide_port_info platform_ide_port_info = {
.host_flags = IDE_HFLAG_NO_DMA,
};
static int __devinit plat_ide_probe(struct platform_device *pdev)
{
struct resource *res_base, *res_alt, *res_irq;
@ -54,6 +58,7 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
int ret = 0;
int mmio = 0;
hw_regs_t hw;
struct ide_port_info d = platform_ide_port_info;
pdata = pdev->dev.platform_data;
@ -102,13 +107,13 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
ide_init_port_hw(hwif, &hw);
if (mmio) {
hwif->host_flags = IDE_HFLAG_MMIO;
d.host_flags |= IDE_HFLAG_MMIO;
default_hwif_mmiops(hwif);
}
idx[0] = hwif->index;
ide_device_add(idx, NULL);
ide_device_add(idx, &d);
platform_set_drvdata(pdev, hwif);

View File

@ -130,7 +130,6 @@ static int __init macide_init(void)
u8 index = hwif->index;
u8 idx[4] = { index, 0xff, 0xff, 0xff };
ide_init_port_data(hwif, index);
ide_init_port_hw(hwif, &hw);
ide_device_add(idx, NULL);

View File

@ -142,7 +142,6 @@ static int __init q40ide_init(void)
hwif = ide_find_port();
if (hwif) {
ide_init_port_data(hwif, hwif->index);
ide_init_port_hw(hwif, &hw);
/* Q40 has a byte-swapped IDE interface */

View File

@ -207,6 +207,7 @@ 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)
{
ide_hwif_t *hwif = drive->hwif;
struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
unsigned int cycle_time;
int active_time = 175;
int recovery_time = 415; /* worst case values from the dos driver */
@ -236,7 +237,7 @@ static void qd6580_set_pio_mode(ide_drive_t *drive, const u8 pio)
active_time = 110;
recovery_time = cycle_time - 120;
} else {
active_time = ide_pio_timings[pio].active_time;
active_time = t->active;
recovery_time = cycle_time - active_time;
}
}
@ -281,17 +282,18 @@ static int __init qd_testreg(int port)
return (readreg != QD_TESTVAL);
}
static void __init qd6500_port_init_devs(ide_hwif_t *hwif)
static void __init qd6500_init_dev(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->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;
drive->drive_data = QD6500_DEF_DATA;
}
static void __init qd6580_port_init_devs(ide_hwif_t *hwif)
static void __init qd6580_init_dev(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
u16 t1, t2;
u8 base = (hwif->config_data & 0xff00) >> 8;
u8 config = QD_CONFIG(hwif);
@ -302,18 +304,17 @@ static void __init qd6580_port_init_devs(ide_hwif_t *hwif)
} else
t2 = t1 = hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA;
hwif->drives[0].drive_data = t1;
hwif->drives[1].drive_data = t2;
drive->drive_data = drive->select.b.unit ? t2 : t1;
}
static const struct ide_port_ops qd6500_port_ops = {
.port_init_devs = qd6500_port_init_devs,
.init_dev = qd6500_init_dev,
.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,
.init_dev = qd6580_init_dev,
.set_pio_mode = qd6580_set_pio_mode,
.selectproc = qd65xx_select,
};

View File

@ -213,10 +213,8 @@ static int auide_build_dmatable(ide_drive_t *drive)
{
int i, iswrite, count = 0;
ide_hwif_t *hwif = HWIF(drive);
struct request *rq = HWGROUP(drive)->rq;
_auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data;
_auide_hwif *ahwif = &auide_hwif;
struct scatterlist *sg;
iswrite = (rq_data_dir(rq) == WRITE);
@ -402,7 +400,7 @@ static const struct ide_dma_ops au1xxx_dma_ops = {
static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
{
_auide_hwif *auide = (_auide_hwif *)hwif->hwif_data;
_auide_hwif *auide = &auide_hwif;
dbdev_tab_t source_dev_tab, target_dev_tab;
u32 dev_id, tsize, devwidth, flags;
@ -463,7 +461,7 @@ static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
#else
static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
{
_auide_hwif *auide = (_auide_hwif *)hwif->hwif_data;
_auide_hwif *auide = &auide_hwif;
dbdev_tab_t source_dev_tab;
int flags;
@ -600,8 +598,6 @@ static int au_ide_probe(struct device *dev)
ide_init_port_hw(hwif, &hw);
hwif->dev = dev;
/* If the user has selected DDMA assisted copies,
then set up a few local I/O function entry points
*/
@ -610,11 +606,8 @@ static int au_ide_probe(struct device *dev)
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 */
auide_hwif.hwif = hwif;
hwif->hwif_data = &auide_hwif;
idx[0] = hwif->index;

View File

@ -61,6 +61,11 @@ static struct resource swarm_ide_resource = {
static struct platform_device *swarm_ide_dev;
static const struct ide_port_info swarm_port_info = {
.name = DRV_NAME,
.host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
};
/*
* swarm_ide_probe - if the board header indicates the existence of
* Generic Bus IDE, allocate a HWIF for it.
@ -77,12 +82,6 @@ static int __devinit swarm_ide_probe(struct device *dev)
if (!SIBYTE_HAVE_IDE)
return -ENODEV;
hwif = ide_find_port();
if (hwif == NULL) {
printk(KERN_ERR DRV_NAME ": no free slot for interface\n");
return -ENOMEM;
}
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));
@ -109,10 +108,6 @@ 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);
for (i = 0; i <= 7; i++)
hw.io_ports_array[i] =
(unsigned long)(base + ((0x1f0 + i) << 5));
@ -121,15 +116,26 @@ static int __devinit swarm_ide_probe(struct device *dev)
hw.irq = K_INT_GB_IDE;
hw.chipset = ide_generic;
hwif = ide_find_port_slot(&swarm_port_info);
if (hwif == NULL)
goto err;
ide_init_port_hw(hwif, &hw);
/* Setup MMIO ops. */
default_hwif_mmiops(hwif);
idx[0] = hwif->index;
ide_device_add(idx, NULL);
ide_device_add(idx, &swarm_port_info);
dev_set_drvdata(dev, hwif);
return 0;
err:
release_resource(&swarm_ide_resource);
iounmap(base);
return -ENOMEM;
}
static struct device_driver swarm_ide_driver = {

View File

@ -69,7 +69,8 @@ static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
int s_time, a_time, c_time;
struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
int s_time = t->setup, a_time = t->active, c_time = t->cycle;
u8 s_clc, a_clc, r_clc;
unsigned long flags;
int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
@ -78,13 +79,10 @@ static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
u8 cd_dma_fifo = 0;
int unit = drive->select.b.unit & 1;
s_time = ide_pio_timings[pio].setup_time;
a_time = ide_pio_timings[pio].active_time;
if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8)
s_clc = 0;
if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8)
a_clc = 0;
c_time = ide_pio_timings[pio].cycle_time;
if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) {
r_clc = 1;

View File

@ -21,8 +21,6 @@
#include <linux/init.h>
#include <linux/ide.h>
#include "ide-timing.h"
enum {
AMD_IDE_CONFIG = 0x41,
AMD_CABLE_DETECT = 0x42,

View File

@ -521,6 +521,7 @@ static void program_drive_counts(ide_drive_t *drive, unsigned int index)
static void cmd640_set_mode(ide_drive_t *drive, unsigned int index,
u8 pio_mode, unsigned int cycle_time)
{
struct ide_timing *t;
int setup_time, active_time, recovery_time, clock_time;
u8 setup_count, active_count, recovery_count, recovery_count2, cycle_count;
int bus_speed;
@ -532,8 +533,11 @@ static void cmd640_set_mode(ide_drive_t *drive, unsigned int index,
if (pio_mode > 5)
pio_mode = 5;
setup_time = ide_pio_timings[pio_mode].setup_time;
active_time = ide_pio_timings[pio_mode].active_time;
t = ide_timing_find_mode(XFER_PIO_0 + pio_mode);
setup_time = t->setup;
active_time = t->active;
recovery_time = cycle_time - (setup_time + active_time);
clock_time = 1000 / bus_speed;
cycle_count = DIV_ROUND_UP(cycle_time, clock_time);
@ -607,11 +611,40 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
display_clocks(index);
}
#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
static void cmd640_init_dev(ide_drive_t *drive)
{
unsigned int i = drive->hwif->channel * 2 + drive->select.b.unit;
#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[i] = 4; /* max possible */
active_counts[i] = 16; /* max possible */
recovery_counts[i] = 16; /* max possible */
program_drive_counts(drive, i);
set_prefetch_mode(drive, i, 0);
printk(KERN_INFO DRV_NAME ": drive%d timings/prefetch cleared\n", i);
#else
/*
* Set the drive unmask flags to match the prefetch setting.
*/
check_prefetch(drive, i);
printk(KERN_INFO DRV_NAME ": drive%d timings/prefetch(%s) preserved\n",
i, drive->no_io_32bit ? "off" : "on");
#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
}
static const struct ide_port_ops cmd640_port_ops = {
.init_dev = cmd640_init_dev,
#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
.set_pio_mode = cmd640_set_pio_mode,
#endif
};
#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
static int pci_conf1(void)
{
@ -654,10 +687,8 @@ static const struct ide_port_info cmd640_port_info __initdata = {
IDE_HFLAG_NO_DMA |
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)
@ -683,12 +714,8 @@ static int cmd640x_init_one(unsigned long base, unsigned long ctl)
*/
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, rc;
const char *bus_type, *port2;
unsigned int index;
u8 b, cfr;
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
hw_regs_t hw[2];
@ -774,88 +801,44 @@ static int __init cmd640x_init(void)
put_cmd640_reg(CMDTIM, 0);
put_cmd640_reg(BRST, 0x40);
cmd_hwif1 = ide_find_port();
b = get_cmd640_reg(CNTRL);
/*
* Try to enable the secondary interface, if not already enabled
*/
if (cmd_hwif1 &&
cmd_hwif1->drives[0].noprobe && cmd_hwif1->drives[1].noprobe) {
port2 = "not probed";
if (secondary_port_responding()) {
if ((b & CNTRL_ENA_2ND)) {
second_port_cmd640 = 1;
port2 = "okay";
} else if (cmd640_vlb) {
second_port_cmd640 = 1;
port2 = "alive";
} else
port2 = "not cmd640";
} else {
b = get_cmd640_reg(CNTRL);
put_cmd640_reg(CNTRL, b ^ CNTRL_ENA_2ND); /* toggle the bit */
if (secondary_port_responding()) {
if ((b & CNTRL_ENA_2ND)) {
second_port_cmd640 = 1;
port2 = "okay";
} else if (cmd640_vlb) {
second_port_cmd640 = 1;
port2 = "alive";
} else
port2 = "not cmd640";
second_port_cmd640 = 1;
port2 = "enabled";
} else {
put_cmd640_reg(CNTRL, b ^ CNTRL_ENA_2ND); /* toggle the bit */
if (secondary_port_responding()) {
second_port_cmd640 = 1;
#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
second_port_toggled = 1;
#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
port2 = "enabled";
} else {
put_cmd640_reg(CNTRL, b); /* restore original setting */
port2 = "not responding";
}
put_cmd640_reg(CNTRL, b); /* restore original setting */
port2 = "not responding";
}
}
/*
* Initialize data for secondary cmd640 port, if enabled
*/
if (second_port_cmd640 && cmd_hwif1) {
ide_init_port_hw(cmd_hwif1, &hw[1]);
idx[1] = cmd_hwif1->index;
if (second_port_cmd640) {
cmd_hwif1 = ide_find_port();
if (cmd_hwif1) {
ide_init_port_hw(cmd_hwif1, &hw[1]);
idx[1] = cmd_hwif1->index;
}
}
printk(KERN_INFO "cmd640: %sserialized, secondary interface %s\n",
second_port_cmd640 ? "" : "not ", port2);
/*
* Establish initial timings/prefetch for all drives.
* Do not unnecessarily disturb any prior BIOS setup of these.
*/
for (index = 0; index < (2 + (second_port_cmd640 << 1)); 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(drive, index);
printk("cmd640: drive%d timings/prefetch(%s) preserved\n",
index, drive->no_io_32bit ? "off" : "on");
#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
}
#ifdef CMD640_DUMP_REGS
cmd640_dump_regs();
#endif

View File

@ -116,6 +116,7 @@ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
unsigned int cycle_time;
u8 setup_count, arttim = 0;
@ -124,10 +125,9 @@ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
cycle_time = ide_pio_cycle_time(drive, pio);
program_cycle_times(drive, cycle_time,
ide_pio_timings[pio].active_time);
program_cycle_times(drive, cycle_time, t->active);
setup_count = quantize_timing(ide_pio_timings[pio].setup_time,
setup_count = quantize_timing(t->setup,
1000 / (ide_pci_clk ? ide_pci_clk : 33));
/*

View File

@ -26,8 +26,6 @@
#include <linux/pci.h>
#include <linux/ide.h>
#include "ide-timing.h"
#define MSR_ATAC_BASE 0x51300000
#define ATAC_GLD_MSR_CAP (MSR_ATAC_BASE+0)
#define ATAC_GLD_MSR_CONFIG (MSR_ATAC_BASE+0x01)
@ -75,13 +73,11 @@ static unsigned int cs5535_udma_timings[5] =
*/
static void cs5535_set_speed(ide_drive_t *drive, const u8 speed)
{
u32 reg = 0, dummy;
int unit = drive->select.b.unit;
/* Set the PIO timings */
if ((speed & XFER_MODE) == XFER_PIO) {
if (speed < XFER_SW_DMA_0) {
ide_drive_t *pair = ide_get_paired_drive(drive);
u8 cmd, pioa;

View File

@ -133,6 +133,7 @@ static int calc_clk(int time, int bus_speed)
*/
static void compute_clocks(u8 pio, pio_clocks_t *p_pclk)
{
struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
int clk1, clk2;
int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
@ -141,15 +142,13 @@ static void compute_clocks(u8 pio, pio_clocks_t *p_pclk)
*/
/* let's calc the address setup time clocks */
p_pclk->address_time = (u8)calc_clk(ide_pio_timings[pio].setup_time, bus_speed);
p_pclk->address_time = (u8)calc_clk(t->setup, bus_speed);
/* let's calc the active and recovery time clocks */
clk1 = calc_clk(ide_pio_timings[pio].active_time, bus_speed);
clk1 = calc_clk(t->active, bus_speed);
/* calc recovery timing */
clk2 = ide_pio_timings[pio].cycle_time -
ide_pio_timings[pio].active_time -
ide_pio_timings[pio].setup_time;
clk2 = t->cycle - t->active - t->setup;
clk2 = calc_clk(clk2, bus_speed);

View File

@ -93,7 +93,6 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
i = hwif->index;
ide_init_port_data(hwif, i);
ide_init_port_hw(hwif, &hw);
idx[0] = i;

View File

@ -512,8 +512,14 @@ static void __devinit it821x_quirkproc(ide_drive_t *drive)
}
static struct ide_dma_ops it821x_pass_through_dma_ops = {
.dma_host_set = ide_dma_host_set,
.dma_setup = ide_dma_setup,
.dma_exec_cmd = ide_dma_exec_cmd,
.dma_start = it821x_dma_start,
.dma_end = it821x_dma_end,
.dma_test_irq = ide_dma_test_irq,
.dma_timeout = ide_dma_timeout,
.dma_lost_irq = ide_dma_lost_irq,
};
/**

View File

@ -558,12 +558,9 @@ static int scc_ide_setup_pci_device(struct pci_dev *dev,
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);
hwif = ide_find_port_slot(d);
if (hwif == NULL)
return -ENOMEM;
}
memset(&hw, 0, sizeof(hw));
for (i = 0; i <= 8; i++)
@ -572,7 +569,6 @@ static int scc_ide_setup_pci_device(struct pci_dev *dev,
hw.dev = &dev->dev;
hw.chipset = ide_pci;
ide_init_port_hw(hwif, &hw);
hwif->dev = &dev->dev;
idx[0] = hwif->index;

View File

@ -568,6 +568,7 @@ static const struct ide_dma_ops sgiioc4_dma_ops = {
};
static const struct ide_port_info sgiioc4_port_info __devinitdata = {
.name = DRV_NAME,
.chipset = ide_pci,
.init_dma = ide_dma_sgiioc4,
.port_ops = &sgiioc4_port_ops,
@ -587,13 +588,6 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
hw_regs_t hw;
struct ide_port_info d = sgiioc4_port_info;
hwif = ide_find_port();
if (hwif == NULL) {
printk(KERN_ERR "%s: too many IDE interfaces, no room in table\n",
DRV_NAME);
return -ENOMEM;
}
/* Get the CmdBlk and CtrlBlk Base Registers */
bar0 = pci_resource_start(dev, 0);
virt_base = ioremap(bar0, pci_resource_len(dev, 0));
@ -608,11 +602,11 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
cmd_phys_base = bar0 + IOC4_CMD_OFFSET;
if (!request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE,
hwif->name)) {
DRV_NAME)) {
printk(KERN_ERR
"%s : %s -- ERROR, Addresses "
"0x%p to 0x%p ALREADY in use\n",
__func__, hwif->name, (void *) cmd_phys_base,
__func__, DRV_NAME, (void *) cmd_phys_base,
(void *) cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE);
return -ENOMEM;
}
@ -623,9 +617,12 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
hw.irq = dev->irq;
hw.chipset = ide_pci;
hw.dev = &dev->dev;
ide_init_port_hw(hwif, &hw);
hwif->dev = &dev->dev;
hwif = ide_find_port_slot(&d);
if (hwif == NULL)
goto err;
ide_init_port_hw(hwif, &hw);
/* The IOC4 uses MMIO rather than Port IO. */
default_hwif_mmiops(hwif);
@ -641,6 +638,10 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
return -EIO;
return 0;
err:
release_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE);
iounmap(virt_base);
return -ENOMEM;
}
static unsigned int __devinit

View File

@ -421,8 +421,7 @@ static int sil_sata_reset_poll(ide_drive_t *drive)
if ((sata_stat & 0x03) != 0x03) {
printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n",
hwif->name, sata_stat);
HWGROUP(drive)->polling = 0;
return ide_started;
return -ENXIO;
}
}

View File

@ -52,8 +52,6 @@
#include <linux/init.h>
#include <linux/ide.h>
#include "ide-timing.h"
/* registers layout and init values are chipset family dependant */
#define ATA_16 0x01
@ -616,7 +614,6 @@ MODULE_LICENSE("GPL");
/*
* TODO:
* - CLEANUP
* - Use drivers/ide/ide-timing.h !
* - More checks in the config registers (force values instead of
* relying on the BIOS setting them correctly).
* - Further optimisations ?

View File

@ -47,10 +47,11 @@
*/
static unsigned int get_pio_timings(ide_drive_t *drive, u8 pio)
{
struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
unsigned int cmd_on, cmd_off;
u8 iordy = 0;
cmd_on = (ide_pio_timings[pio].active_time + 29) / 30;
cmd_on = (t->active + 29) / 30;
cmd_off = (ide_pio_cycle_time(drive, pio) - 30 * cmd_on + 29) / 30;
if (cmd_on == 0)

View File

@ -35,8 +35,6 @@
#include <asm/processor.h>
#endif
#include "ide-timing.h"
#define VIA_IDE_ENABLE 0x40
#define VIA_IDE_CONFIG 0x41
#define VIA_FIFO_CONFIG 0x43

View File

@ -1,3 +1,2 @@
obj-$(CONFIG_BLK_DEV_IDE_PMAC) += pmac.o
obj-$(CONFIG_BLK_DEV_MPC8xx_IDE) += mpc8xx.o

View File

@ -1,851 +0,0 @@
/*
* Copyright (C) 2000, 2001 Wolfgang Denk, wd@denx.de
* Modified for direct IDE interface
* by Thomas Lange, thomas@corelatus.com
* Modified for direct IDE interface on 8xx without using the PCMCIA
* controller
* by Steven.Scholz@imc-berlin.de
* Moved out of arch/ppc/kernel/m8xx_setup.c, other minor cleanups
* by Mathew Locke <mattl@mvista.com>
*/
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/user.h>
#include <linux/tty.h>
#include <linux/major.h>
#include <linux/interrupt.h>
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/ide.h>
#include <linux/bootmem.h>
#include <asm/mpc8xx.h>
#include <asm/mmu.h>
#include <asm/processor.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/ide.h>
#include <asm/8xx_immap.h>
#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);
static int check_ide_device (unsigned long base);
static void ide_interrupt_ack (void *dev);
static void m8xx_ide_set_pio_mode(ide_drive_t *drive, const u8 pio);
typedef struct ide_ioport_desc {
unsigned long base_off; /* Offset to PCMCIA memory */
unsigned long reg_off[IDE_NR_PORTS]; /* controller register offsets */
int irq; /* IRQ */
} ide_ioport_desc_t;
ide_ioport_desc_t ioport_dsc[MAX_HWIFS] = {
#ifdef IDE0_BASE_OFFSET
{ IDE0_BASE_OFFSET,
{
IDE0_DATA_REG_OFFSET,
IDE0_ERROR_REG_OFFSET,
IDE0_NSECTOR_REG_OFFSET,
IDE0_SECTOR_REG_OFFSET,
IDE0_LCYL_REG_OFFSET,
IDE0_HCYL_REG_OFFSET,
IDE0_SELECT_REG_OFFSET,
IDE0_STATUS_REG_OFFSET,
IDE0_CONTROL_REG_OFFSET,
IDE0_IRQ_REG_OFFSET,
},
IDE0_INTERRUPT,
},
#ifdef IDE1_BASE_OFFSET
{ IDE1_BASE_OFFSET,
{
IDE1_DATA_REG_OFFSET,
IDE1_ERROR_REG_OFFSET,
IDE1_NSECTOR_REG_OFFSET,
IDE1_SECTOR_REG_OFFSET,
IDE1_LCYL_REG_OFFSET,
IDE1_HCYL_REG_OFFSET,
IDE1_SELECT_REG_OFFSET,
IDE1_STATUS_REG_OFFSET,
IDE1_CONTROL_REG_OFFSET,
IDE1_IRQ_REG_OFFSET,
},
IDE1_INTERRUPT,
},
#endif /* IDE1_BASE_OFFSET */
#endif /* IDE0_BASE_OFFSET */
};
ide_pio_timings_t ide_pio_clocks[6];
int hold_time[6] = {30, 20, 15, 10, 10, 10 }; /* PIO Mode 5 with IORDY (nonstandard) */
/*
* Warning: only 1 (ONE) PCMCIA slot supported here,
* which must be correctly initialized by the firmware (PPCBoot).
*/
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 )
#define M8XX_PCMCIA_CD2(slot) (0x10000000 >> (slot << 4))
#define M8XX_PCMCIA_CD1(slot) (0x08000000 >> (slot << 4))
/*
* The TQM850L hardware has two pins swapped! Grrrrgh!
*/
#ifdef CONFIG_TQM850L
#define __MY_PCMCIA_GCRX_CXRESET PCMCIA_GCRX_CXOE
#define __MY_PCMCIA_GCRX_CXOE PCMCIA_GCRX_CXRESET
#else
#define __MY_PCMCIA_GCRX_CXRESET PCMCIA_GCRX_CXRESET
#define __MY_PCMCIA_GCRX_CXOE PCMCIA_GCRX_CXOE
#endif
#if defined(CONFIG_BLK_DEV_MPC8xx_IDE) && defined(CONFIG_IDE_8xx_PCCARD)
#define PCMCIA_SCHLVL IDE0_INTERRUPT /* Status Change Interrupt Level */
static int pcmcia_schlvl = PCMCIA_SCHLVL;
#endif
/*
* See include/linux/ide.h for definition of hw_regs_t (p, base)
*/
/*
* 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 int __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
{
unsigned long *p = hw->io_ports_array;
int i;
typedef struct {
ulong br;
ulong or;
} pcmcia_win_t;
volatile pcmcia_win_t *win;
volatile pcmconf8xx_t *pcmp;
uint *pgcrx;
u32 pcmcia_phy_base;
u32 pcmcia_phy_end;
static unsigned long pcmcia_base = 0;
unsigned long base;
*p = 0;
pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia));
if (!pcmcia_base) {
/*
* Read out PCMCIA registers. Since the reset values
* are undefined, we sure hope that they have been
* set up by firmware
*/
/* Scan all registers for valid settings */
pcmcia_phy_base = 0xFFFFFFFF;
pcmcia_phy_end = 0;
/* br0 is start of brX and orX regs */
win = (pcmcia_win_t *) \
(&(((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0));
for (i = 0; i < 8; i++) {
if (win->or & 1) { /* This bank is marked as valid */
if (win->br < pcmcia_phy_base) {
pcmcia_phy_base = win->br;
}
if ((win->br + PCMCIA_MEM_SIZE) > pcmcia_phy_end) {
pcmcia_phy_end = win->br + PCMCIA_MEM_SIZE;
}
/* Check which slot that has been defined */
_slot_ = (win->or >> 2) & 1;
} /* Valid bank */
win++;
} /* for */
printk ("PCMCIA slot %c: phys mem %08x...%08x (size %08x)\n",
'A' + _slot_,
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);
#ifdef DEBUG
printk ("PCMCIA virt base: %08lx\n", pcmcia_base);
#endif
/* Compute clock cycles for PIO timings */
for (i=0; i<6; ++i) {
bd_t *binfo = (bd_t *)__res;
hold_time[i] =
PCMCIA_MK_CLKS (hold_time[i],
binfo->bi_busfreq);
ide_pio_clocks[i].setup_time =
PCMCIA_MK_CLKS (ide_pio_timings[i].setup_time,
binfo->bi_busfreq);
ide_pio_clocks[i].active_time =
PCMCIA_MK_CLKS (ide_pio_timings[i].active_time,
binfo->bi_busfreq);
ide_pio_clocks[i].cycle_time =
PCMCIA_MK_CLKS (ide_pio_timings[i].cycle_time,
binfo->bi_busfreq);
#if 0
printk ("PIO mode %d timings: %d/%d/%d => %d/%d/%d\n",
i,
ide_pio_clocks[i].setup_time,
ide_pio_clocks[i].active_time,
ide_pio_clocks[i].hold_time,
ide_pio_clocks[i].cycle_time,
ide_pio_timings[i].setup_time,
ide_pio_timings[i].active_time,
ide_pio_timings[i].hold_time,
ide_pio_timings[i].cycle_time);
#endif
}
}
if (_slot_ == -1) {
printk ("PCMCIA slot has not been defined! Using A as default\n");
_slot_ = 0;
}
#ifdef CONFIG_IDE_8xx_PCCARD
#ifdef DEBUG
printk ("PIPR = 0x%08X slot %c ==> mask = 0x%X\n",
pcmp->pcmc_pipr,
'A' + _slot_,
M8XX_PCMCIA_CD1(_slot_) | M8XX_PCMCIA_CD2(_slot_) );
#endif /* DEBUG */
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 -ENODEV; /* No card in slot */
}
check_ide_device (pcmcia_base);
#endif /* CONFIG_IDE_8xx_PCCARD */
base = pcmcia_base + ioport_dsc[data_port].base_off;
#ifdef DEBUG
printk ("base: %08x + %08x = %08x\n",
pcmcia_base, ioport_dsc[data_port].base_off, base);
#endif
for (i = 0; i < IDE_NR_PORTS; ++i) {
#ifdef DEBUG
printk ("port[%d]: %08x + %08x = %08x\n",
i,
base,
ioport_dsc[data_port].reg_off[i],
i, base + ioport_dsc[data_port].reg_off[i]);
#endif
*p++ = base + ioport_dsc[data_port].reg_off[i];
}
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;
if (_slot_)
pgcrx = &((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pgcrb;
else
pgcrx = &((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pgcra;
reg = *pgcrx;
reg |= mk_int_int_mask (pcmcia_schlvl) << 24;
reg |= mk_int_int_mask (pcmcia_schlvl) << 16;
*pgcrx = reg;
}
#endif /* CONFIG_IDE_8xx_PCCARD */
/* Enable Harddisk Interrupt,
* and make it edge sensitive
*/
/* (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);
#ifdef CONFIG_IDE_8xx_PCCARD
/* Make sure we don't get garbage irq */
((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pscr = 0xFFFF;
/* Enable falling edge irq */
pcmp->pcmc_per = 0x100000 >> (16 * _slot_);
#endif /* CONFIG_IDE_8xx_PCCARD */
hw->chipset = ide_generic;
return 0;
}
#endif /* CONFIG_IDE_8xx_PCCARD || CONFIG_IDE_8xx_DIRECT */
/*
* m8xx_ide_init_ports() for a direct IDE interface _not_ using
* MPC8xx's internal PCMCIA interface
*/
#if defined(CONFIG_IDE_EXT_DIRECT)
static int __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
{
unsigned long *p = hw->io_ports_array;
int i;
u32 ide_phy_base;
u32 ide_phy_end;
static unsigned long ide_base = 0;
unsigned long base;
*p = 0;
if (!ide_base) {
/* TODO:
* - add code to read ORx, BRx
*/
ide_phy_base = CFG_ATA_BASE_ADDR;
ide_phy_end = CFG_ATA_BASE_ADDR + 0x200;
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);
#ifdef DEBUG
printk ("IDE virt base: %08lx\n", ide_base);
#endif
}
base = ide_base + ioport_dsc[data_port].base_off;
#ifdef DEBUG
printk ("base: %08x + %08x = %08x\n",
ide_base, ioport_dsc[data_port].base_off, base);
#endif
for (i = 0; i < IDE_NR_PORTS; ++i) {
#ifdef DEBUG
printk ("port[%d]: %08x + %08x = %08x\n",
i,
base,
ioport_dsc[data_port].reg_off[i],
i, base + ioport_dsc[data_port].reg_off[i]);
#endif
*p++ = base + ioport_dsc[data_port].reg_off[i];
}
/* 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
*/
/* (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);
hw->chipset = ide_generic;
return 0;
}
#endif /* CONFIG_IDE_8xx_DIRECT */
/* -------------------------------------------------------------------- */
/* PCMCIA Timing */
#ifndef PCMCIA_SHT
#define PCMCIA_SHT(t) ((t & 0x0F)<<16) /* Strobe Hold Time */
#define PCMCIA_SST(t) ((t & 0x0F)<<12) /* Strobe Setup Time */
#define PCMCIA_SL(t) ((t==32) ? 0 : ((t & 0x1F)<<7)) /* Strobe Length */
#endif
/* Calculate PIO timings */
static void m8xx_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
#if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT)
volatile pcmconf8xx_t *pcmp;
ulong timing, mask, reg;
pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia));
mask = ~(PCMCIA_SHT(0xFF) | PCMCIA_SST(0xFF) | PCMCIA_SL(0xFF));
timing = PCMCIA_SHT(hold_time[pio] )
| PCMCIA_SST(ide_pio_clocks[pio].setup_time )
| PCMCIA_SL (ide_pio_clocks[pio].active_time)
;
#if 1
printk ("Setting timing bits 0x%08lx in PCMCIA controller\n", timing);
#endif
if ((reg = pcmp->pcmc_por0 & mask) != 0)
pcmp->pcmc_por0 = reg | timing;
if ((reg = pcmp->pcmc_por1 & mask) != 0)
pcmp->pcmc_por1 = reg | timing;
if ((reg = pcmp->pcmc_por2 & mask) != 0)
pcmp->pcmc_por2 = reg | timing;
if ((reg = pcmp->pcmc_por3 & mask) != 0)
pcmp->pcmc_por3 = reg | timing;
if ((reg = pcmp->pcmc_por4 & mask) != 0)
pcmp->pcmc_por4 = reg | timing;
if ((reg = pcmp->pcmc_por5 & mask) != 0)
pcmp->pcmc_por5 = reg | timing;
if ((reg = pcmp->pcmc_por6 & mask) != 0)
pcmp->pcmc_por6 = reg | timing;
if ((reg = pcmp->pcmc_por7 & mask) != 0)
pcmp->pcmc_por7 = reg | timing;
#elif defined(CONFIG_IDE_EXT_DIRECT)
printk("%s[%d] %s: not implemented yet!\n",
__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)
{
#ifdef CONFIG_IDE_8xx_PCCARD
u_int pscr, pipr;
#if (PCMCIA_SOCKETS_NO == 2)
u_int _slot_;
#endif
/* get interrupt sources */
pscr = ((volatile immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr;
pipr = ((volatile immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr;
/*
* report only if both card detect signals are the same
* not too nice done,
* we depend on that CD2 is the bit to the left of CD1...
*/
if(_slot_==-1){
printk("PCMCIA slot has not been defined! Using A as default\n");
_slot_=0;
}
if(((pipr & M8XX_PCMCIA_CD2(_slot_)) >> 1) ^
(pipr & M8XX_PCMCIA_CD1(_slot_)) ) {
printk ("card detect interrupt\n");
}
/* clear the interrupt sources */
((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = pscr;
#else /* ! CONFIG_IDE_8xx_PCCARD */
/*
* Only CONFIG_IDE_8xx_PCCARD is using the interrupt of the
* MPC8xx's PCMCIA controller, so there is nothing to be done here
* for CONFIG_IDE_8xx_DIRECT and CONFIG_IDE_EXT_DIRECT.
* The interrupt is handled somewhere else. -- Steven
*/
#endif /* CONFIG_IDE_8xx_PCCARD */
}
/*
* CIS Tupel codes
*/
#define CISTPL_NULL 0x00
#define CISTPL_DEVICE 0x01
#define CISTPL_LONGLINK_CB 0x02
#define CISTPL_INDIRECT 0x03
#define CISTPL_CONFIG_CB 0x04
#define CISTPL_CFTABLE_ENTRY_CB 0x05
#define CISTPL_LONGLINK_MFC 0x06
#define CISTPL_BAR 0x07
#define CISTPL_PWR_MGMNT 0x08
#define CISTPL_EXTDEVICE 0x09
#define CISTPL_CHECKSUM 0x10
#define CISTPL_LONGLINK_A 0x11
#define CISTPL_LONGLINK_C 0x12
#define CISTPL_LINKTARGET 0x13
#define CISTPL_NO_LINK 0x14
#define CISTPL_VERS_1 0x15
#define CISTPL_ALTSTR 0x16
#define CISTPL_DEVICE_A 0x17
#define CISTPL_JEDEC_C 0x18
#define CISTPL_JEDEC_A 0x19
#define CISTPL_CONFIG 0x1a
#define CISTPL_CFTABLE_ENTRY 0x1b
#define CISTPL_DEVICE_OC 0x1c
#define CISTPL_DEVICE_OA 0x1d
#define CISTPL_DEVICE_GEO 0x1e
#define CISTPL_DEVICE_GEO_A 0x1f
#define CISTPL_MANFID 0x20
#define CISTPL_FUNCID 0x21
#define CISTPL_FUNCE 0x22
#define CISTPL_SWIL 0x23
#define CISTPL_END 0xff
/*
* CIS Function ID codes
*/
#define CISTPL_FUNCID_MULTI 0x00
#define CISTPL_FUNCID_MEMORY 0x01
#define CISTPL_FUNCID_SERIAL 0x02
#define CISTPL_FUNCID_PARALLEL 0x03
#define CISTPL_FUNCID_FIXED 0x04
#define CISTPL_FUNCID_VIDEO 0x05
#define CISTPL_FUNCID_NETWORK 0x06
#define CISTPL_FUNCID_AIMS 0x07
#define CISTPL_FUNCID_SCSI 0x08
/*
* Fixed Disk FUNCE codes
*/
#define CISTPL_IDE_INTERFACE 0x01
#define CISTPL_FUNCE_IDE_IFACE 0x01
#define CISTPL_FUNCE_IDE_MASTER 0x02
#define CISTPL_FUNCE_IDE_SLAVE 0x03
/* First feature byte */
#define CISTPL_IDE_SILICON 0x04
#define CISTPL_IDE_UNIQUE 0x08
#define CISTPL_IDE_DUAL 0x10
/* Second feature byte */
#define CISTPL_IDE_HAS_SLEEP 0x01
#define CISTPL_IDE_HAS_STANDBY 0x02
#define CISTPL_IDE_HAS_IDLE 0x04
#define CISTPL_IDE_LOW_POWER 0x08
#define CISTPL_IDE_REG_INHIBIT 0x10
#define CISTPL_IDE_HAS_INDEX 0x20
#define CISTPL_IDE_IOIS16 0x40
/* -------------------------------------------------------------------- */
#define MAX_TUPEL_SZ 512
#define MAX_FEATURES 4
static int check_ide_device (unsigned long base)
{
volatile u8 *ident = NULL;
volatile u8 *feature_p[MAX_FEATURES];
volatile u8 *p, *start;
int n_features = 0;
u8 func_id = ~0;
u8 code, len;
unsigned short config_base = 0;
int found = 0;
int i;
#ifdef DEBUG
printk ("PCMCIA MEM: %08lX\n", base);
#endif
start = p = (volatile u8 *) base;
while ((p - start) < MAX_TUPEL_SZ) {
code = *p; p += 2;
if (code == 0xFF) { /* End of chain */
break;
}
len = *p; p += 2;
#ifdef DEBUG_PCMCIA
{ volatile u8 *q = p;
printk ("\nTuple code %02x length %d\n\tData:",
code, len);
for (i = 0; i < len; ++i) {
printk (" %02x", *q);
q+= 2;
}
}
#endif /* DEBUG_PCMCIA */
switch (code) {
case CISTPL_VERS_1:
ident = p + 4;
break;
case CISTPL_FUNCID:
func_id = *p;
break;
case CISTPL_FUNCE:
if (n_features < MAX_FEATURES)
feature_p[n_features++] = p;
break;
case CISTPL_CONFIG:
config_base = (*(p+6) << 8) + (*(p+4));
default:
break;
}
p += 2 * len;
}
found = identify (ident);
if (func_id != ((u8)~0)) {
print_funcid (func_id);
if (func_id == CISTPL_FUNCID_FIXED)
found = 1;
else
return (1); /* no disk drive */
}
for (i=0; i<n_features; ++i) {
print_fixed (feature_p[i]);
}
if (!found) {
printk ("unknown card type\n");
return (1);
}
/* set level mode irq and I/O mapped device in config reg*/
*((u8 *)(base + config_base)) = 0x41;
return (0);
}
/* ------------------------------------------------------------------------- */
static void print_funcid (int func)
{
switch (func) {
case CISTPL_FUNCID_MULTI:
printk (" Multi-Function");
break;
case CISTPL_FUNCID_MEMORY:
printk (" Memory");
break;
case CISTPL_FUNCID_SERIAL:
printk (" Serial Port");
break;
case CISTPL_FUNCID_PARALLEL:
printk (" Parallel Port");
break;
case CISTPL_FUNCID_FIXED:
printk (" Fixed Disk");
break;
case CISTPL_FUNCID_VIDEO:
printk (" Video Adapter");
break;
case CISTPL_FUNCID_NETWORK:
printk (" Network Adapter");
break;
case CISTPL_FUNCID_AIMS:
printk (" AIMS Card");
break;
case CISTPL_FUNCID_SCSI:
printk (" SCSI Adapter");
break;
default:
printk (" Unknown");
break;
}
printk (" Card\n");
}
/* ------------------------------------------------------------------------- */
static void print_fixed (volatile u8 *p)
{
if (p == NULL)
return;
switch (*p) {
case CISTPL_FUNCE_IDE_IFACE:
{ u8 iface = *(p+2);
printk ((iface == CISTPL_IDE_INTERFACE) ? " IDE" : " unknown");
printk (" interface ");
break;
}
case CISTPL_FUNCE_IDE_MASTER:
case CISTPL_FUNCE_IDE_SLAVE:
{ u8 f1 = *(p+2);
u8 f2 = *(p+4);
printk ((f1 & CISTPL_IDE_SILICON) ? " [silicon]" : " [rotating]");
if (f1 & CISTPL_IDE_UNIQUE)
printk (" [unique]");
printk ((f1 & CISTPL_IDE_DUAL) ? " [dual]" : " [single]");
if (f2 & CISTPL_IDE_HAS_SLEEP)
printk (" [sleep]");
if (f2 & CISTPL_IDE_HAS_STANDBY)
printk (" [standby]");
if (f2 & CISTPL_IDE_HAS_IDLE)
printk (" [idle]");
if (f2 & CISTPL_IDE_LOW_POWER)
printk (" [low power]");
if (f2 & CISTPL_IDE_REG_INHIBIT)
printk (" [reg inhibit]");
if (f2 & CISTPL_IDE_HAS_INDEX)
printk (" [index]");
if (f2 & CISTPL_IDE_IOIS16)
printk (" [IOis16]");
break;
}
}
printk ("\n");
}
/* ------------------------------------------------------------------------- */
#define MAX_IDENT_CHARS 64
#define MAX_IDENT_FIELDS 4
static u8 *known_cards[] = {
"ARGOSY PnPIDE D5",
NULL
};
static int identify (volatile u8 *p)
{
u8 id_str[MAX_IDENT_CHARS];
u8 data;
u8 *t;
u8 **card;
int i, done;
if (p == NULL)
return (0); /* Don't know */
t = id_str;
done =0;
for (i=0; i<=4 && !done; ++i, p+=2) {
while ((data = *p) != '\0') {
if (data == 0xFF) {
done = 1;
break;
}
*t++ = data;
if (t == &id_str[MAX_IDENT_CHARS-1]) {
done = 1;
break;
}
p += 2;
}
if (!done)
*t++ = ' ';
}
*t = '\0';
while (--t > id_str) {
if (*t == ' ')
*t = '\0';
else
break;
}
printk ("Card ID: %s\n", id_str);
for (card=known_cards; *card; ++card) {
if (strcmp(*card, id_str) == 0) { /* found! */
return (1);
}
}
return (0); /* don't know */
}
static int __init mpc8xx_ide_probe(void)
{
hw_regs_t hw;
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
#ifdef IDE0_BASE_OFFSET
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
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
ide_device_add(idx, NULL);
return 0;
}
module_init(mpc8xx_ide_probe);
MODULE_LICENSE("GPL");

View File

@ -5,7 +5,7 @@
* for doing DMA.
*
* Copyright (C) 1998-2003 Paul Mackerras & Ben. Herrenschmidt
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz
* Copyright (C) 2007-2008 Bartlomiej Zolnierkiewicz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -48,8 +48,6 @@
#include <asm/mediabay.h>
#endif
#include "../ide-timing.h"
#undef IDE_PMAC_DEBUG
#define DMA_WAIT_TIMEOUT 50
@ -495,6 +493,7 @@ static void pmac_outbsync(ide_hwif_t *hwif, u8 value, unsigned long port)
static void
pmac_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
struct ide_timing *tim = ide_timing_find_mode(XFER_PIO_0 + pio);
u32 *timings, t;
unsigned accessTicks, recTicks;
unsigned accessTime, recTime;
@ -526,10 +525,9 @@ pmac_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
}
case controller_kl_ata4:
/* 66Mhz cell */
recTime = cycle_time - ide_pio_timings[pio].active_time
- ide_pio_timings[pio].setup_time;
recTime = cycle_time - tim->active - tim->setup;
recTime = max(recTime, 150U);
accessTime = ide_pio_timings[pio].active_time;
accessTime = tim->active;
accessTime = max(accessTime, 150U);
accessTicks = SYSCLK_TICKS_66(accessTime);
accessTicks = min(accessTicks, 0x1fU);
@ -542,10 +540,9 @@ pmac_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
default: {
/* 33Mhz cell */
int ebit = 0;
recTime = cycle_time - ide_pio_timings[pio].active_time
- ide_pio_timings[pio].setup_time;
recTime = cycle_time - tim->active - tim->setup;
recTime = max(recTime, 150U);
accessTime = ide_pio_timings[pio].active_time;
accessTime = tim->active;
accessTime = max(accessTime, 150U);
accessTicks = SYSCLK_TICKS(accessTime);
accessTicks = min(accessTicks, 0x1fU);
@ -1151,8 +1148,6 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
base = ioremap(macio_resource_start(mdev, 0), 0x400);
regbase = (unsigned long) base;
hwif->dev = &mdev->bus->pdev->dev;
pmif->mdev = mdev;
pmif->node = mdev->ofdev.node;
pmif->regbase = regbase;
@ -1174,7 +1169,8 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
memset(&hw, 0, sizeof(hw));
pmac_ide_init_ports(&hw, pmif->regbase);
hw.irq = irq;
hw.dev = &mdev->ofdev.dev;
hw.dev = &mdev->bus->pdev->dev;
hw.parent = &mdev->ofdev.dev;
rc = pmac_ide_setup_device(pmif, hwif, &hw);
if (rc != 0) {
@ -1274,7 +1270,6 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_free_pmif;
}
hwif->dev = &pdev->dev;
pmif->mdev = NULL;
pmif->node = np;

View File

@ -6,19 +6,15 @@
* May be copied or modified under the terms of the GNU General Public License
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/ide.h>
#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/irq.h>
/**
* ide_setup_pci_baseregs - place a PCI IDE controller native
@ -319,25 +315,22 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
ctl = pci_resource_start(dev, 2*port+1);
base = pci_resource_start(dev, 2*port);
if ((ctl && !base) || (base && !ctl)) {
printk(KERN_ERR "%s: inconsistent baseregs (BIOS) "
"for port %d, skipping\n", d->name, port);
return NULL;
}
}
if (!ctl) {
} else {
/* Use default values */
ctl = port ? 0x374 : 0x3f4;
base = port ? 0x170 : 0x1f0;
}
hwif = ide_find_port_slot(d);
if (hwif == NULL) {
printk(KERN_ERR "%s: too many IDE interfaces, no room in "
"table\n", d->name);
if (!base || !ctl) {
printk(KERN_ERR "%s: bad PCI BARs for port %d, skipping\n",
d->name, port);
return NULL;
}
hwif = ide_find_port_slot(d);
if (hwif == NULL)
return NULL;
memset(&hw, 0, sizeof(hw));
hw.irq = irq;
hw.dev = &dev->dev;
@ -346,8 +339,6 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
ide_init_port_hw(hwif, &hw);
hwif->dev = &dev->dev;
return hwif;
}

View File

@ -258,19 +258,6 @@ idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
return ide_stopped;
}
static ide_startstop_t
idescsi_atapi_abort(ide_drive_t *drive, struct request *rq)
{
debug_log("%s called for %lu\n", __func__,
((struct ide_atapi_pc *) rq->special)->scsi_cmd->serial_number);
rq->errors |= ERROR_MAX;
idescsi_end_request(drive, 0, 0);
return ide_stopped;
}
static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
{
idescsi_scsi_t *scsi = drive_to_idescsi(drive);
@ -524,7 +511,6 @@ static ide_driver_t idescsi_driver = {
.do_request = idescsi_do_request,
.end_request = idescsi_end_request,
.error = idescsi_atapi_error,
.abort = idescsi_atapi_abort,
#ifdef CONFIG_IDE_PROC_FS
.proc = idescsi_proc,
#endif

View File

@ -138,6 +138,12 @@ struct ide_io_ports {
#define WAIT_CMD (10*HZ) /* 10sec - maximum wait for an IRQ to happen */
#define WAIT_MIN_SLEEP (2*HZ/100) /* 20msec - minimum sleep time */
/*
* Op codes for special requests to be handled by ide_special_rq().
* Values should be in the range of 0x20 to 0x3f.
*/
#define REQ_DRIVE_RESET 0x20
/*
* Check for an interrupt and acknowledge the interrupt status
*/
@ -171,7 +177,7 @@ typedef struct hw_regs_s {
int irq; /* our irq number */
ide_ack_intr_t *ack_intr; /* acknowledge interrupt */
hwif_chipset_t chipset;
struct device *dev;
struct device *dev, *parent;
} hw_regs_t;
void ide_init_port_data(struct hwif_s *, unsigned int);
@ -405,8 +411,8 @@ typedef struct ide_drive_s {
struct ide_port_info;
struct ide_port_ops {
/* host specific initialization of devices on a port */
void (*port_init_devs)(struct hwif_s *);
/* host specific initialization of a device */
void (*init_dev)(ide_drive_t *);
/* routine to program host for PIO mode */
void (*set_pio_mode)(ide_drive_t *, const u8);
/* routine to program host for DMA mode */
@ -565,8 +571,6 @@ typedef struct hwgroup_s {
unsigned int sleeping : 1;
/* BOOL: polling active & poll_timeout field valid */
unsigned int polling : 1;
/* BOOL: in a polling reset situation. Must not trigger another reset yet */
unsigned int resetting : 1;
/* current drive */
ide_drive_t *drive;
@ -786,7 +790,6 @@ struct ide_driver_s {
ide_startstop_t (*do_request)(ide_drive_t *, struct request *, sector_t);
int (*end_request)(ide_drive_t *, int, int);
ide_startstop_t (*error)(ide_drive_t *, struct request *rq, u8, u8);
ide_startstop_t (*abort)(ide_drive_t *, struct request *rq);
struct device_driver gen_driver;
int (*probe)(ide_drive_t *);
void (*remove)(ide_drive_t *);
@ -801,18 +804,6 @@ struct ide_driver_s {
int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsigned, unsigned long);
/*
* ide_hwifs[] is the master data structure used to keep track
* of just about everything in ide.c. Whenever possible, routines
* should be using pointers to a drive (ide_drive_t *) or
* pointers to a hwif (ide_hwif_t *), rather than indexing this
* structure directly (the allocation/layout may change!).
*
*/
#ifndef _IDE_C
extern ide_hwif_t ide_hwifs[]; /* master data repository */
#endif
extern int ide_vlb_clk;
extern int ide_pci_clk;
@ -840,10 +831,6 @@ ide_startstop_t __ide_error(ide_drive_t *, struct request *, u8, u8);
ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat);
ide_startstop_t __ide_abort(ide_drive_t *, struct request *);
extern ide_startstop_t ide_abort(ide_drive_t *, const char *);
extern void ide_fix_driveid(struct hd_driveid *);
extern void ide_fixstring(u8 *, const int, const int);
@ -1271,16 +1258,43 @@ static inline int ide_dev_is_sata(struct hd_driveid *id)
u64 ide_get_lba_addr(struct ide_taskfile *, int);
u8 ide_dump_status(ide_drive_t *, const char *, u8);
typedef struct ide_pio_timings_s {
int setup_time; /* Address setup (ns) minimum */
int active_time; /* Active pulse (ns) minimum */
int cycle_time; /* Cycle time (ns) minimum = */
/* active + recovery (+ setup for some chips) */
} ide_pio_timings_t;
struct ide_timing {
u8 mode;
u8 setup; /* t1 */
u16 act8b; /* t2 for 8-bit io */
u16 rec8b; /* t2i for 8-bit io */
u16 cyc8b; /* t0 for 8-bit io */
u16 active; /* t2 or tD */
u16 recover; /* t2i or tK */
u16 cycle; /* t0 */
u16 udma; /* t2CYCTYP/2 */
};
enum {
IDE_TIMING_SETUP = (1 << 0),
IDE_TIMING_ACT8B = (1 << 1),
IDE_TIMING_REC8B = (1 << 2),
IDE_TIMING_CYC8B = (1 << 3),
IDE_TIMING_8BIT = IDE_TIMING_ACT8B | IDE_TIMING_REC8B |
IDE_TIMING_CYC8B,
IDE_TIMING_ACTIVE = (1 << 4),
IDE_TIMING_RECOVER = (1 << 5),
IDE_TIMING_CYCLE = (1 << 6),
IDE_TIMING_UDMA = (1 << 7),
IDE_TIMING_ALL = IDE_TIMING_SETUP | IDE_TIMING_8BIT |
IDE_TIMING_ACTIVE | IDE_TIMING_RECOVER |
IDE_TIMING_CYCLE | IDE_TIMING_UDMA,
};
struct ide_timing *ide_timing_find_mode(u8);
u16 ide_pio_cycle_time(ide_drive_t *, u8);
void ide_timing_merge(struct ide_timing *, struct ide_timing *,
struct ide_timing *, unsigned int);
int ide_timing_compute(ide_drive_t *, u8, struct ide_timing *, int, int);
int ide_scan_pio_blacklist(char *);
unsigned int ide_pio_cycle_time(ide_drive_t *, u8);
u8 ide_get_best_pio_mode(ide_drive_t *, u8, u8);
extern const ide_pio_timings_t ide_pio_timings[6];
int ide_set_pio_mode(ide_drive_t *, u8);
int ide_set_dma_mode(ide_drive_t *, u8);