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:
commit
42fdd144a4
58 changed files with 694 additions and 1870 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
94
drivers/ide/ide-pio-blacklist.c
Normal file
94
drivers/ide/ide-pio-blacklist.c
Normal 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;
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -227,7 +227,6 @@ static int __init buddha_init(void)
|
|||
if (hwif) {
|
||||
u8 index = hwif->index;
|
||||
|
||||
ide_init_port_data(hwif, index);
|
||||
ide_init_port_hw(hwif, &hw);
|
||||
|
||||
idx[i] = index;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -185,7 +185,6 @@ static int __init gayle_init(void)
|
|||
if (hwif) {
|
||||
u8 index = hwif->index;
|
||||
|
||||
ide_init_port_data(hwif, index);
|
||||
ide_init_port_hw(hwif, &hw);
|
||||
|
||||
idx[i] = index;
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ?
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
|
||||
obj-$(CONFIG_BLK_DEV_IDE_PMAC) += pmac.o
|
||||
obj-$(CONFIG_BLK_DEV_MPC8xx_IDE) += mpc8xx.o
|
||||
|
|
|
@ -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");
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue