Commit 905adce4 authored by Linus Torvalds's avatar Linus Torvalds

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

* master.kernel.org:/pub/scm/linux/kernel/git/bart/ide-2.6: (23 commits)
  ide-acpi support warning fix
  ACPI support for IDE devices
  IDE Driver for Delkin/Lexar/etc.. cardbus CF adapter
  ide: it8213 IDE driver update (version 2)
  ide: add it8213 IDE driver
  tc86c001: add missing __init tag for tc86c001_ide_init()
  tc86c001: mark init_chipset_tc86c001() with __devinit tag
  tc86c001: init_hwif_tc86c001() can be static
  ide: add Toshiba TC86C001 IDE driver (take 2)
  pdc202xx_new: remove check_in_drive_lists abomination
  pdc202xx_new: remove useless code
  slc90e66: carry over fixes from piix driver
  piix: tuneproc() fixes/cleanups
  piix: fix 82371MX enablebits
  hpt366: HPT36x PCI clock detection fix
  hpt366: init code rewrite
  hpt366: clean up DMA timeout handling for HPT370
  hpt366: merge HPT37x speedproc handlers
  hpt366: cache channel's MCR address
  hpt366: switch to using pci_get_slot
  ...
parents 78149df6 1e8f34f7
...@@ -167,6 +167,13 @@ config BLK_DEV_IDECS ...@@ -167,6 +167,13 @@ config BLK_DEV_IDECS
Support for Compact Flash cards, outboard IDE disks, tape drives, Support for Compact Flash cards, outboard IDE disks, tape drives,
and CD-ROM drives connected through a PCMCIA card. and CD-ROM drives connected through a PCMCIA card.
config BLK_DEV_DELKIN
tristate "Cardbus IDE support (Delkin/ASKA/Workbit)"
depends on CARDBUS && PCI
help
Support for Delkin, ASKA, and Workbit Cardbus CompactFlash
Adapters. This may also work for similar SD and XD adapters.
config BLK_DEV_IDECD config BLK_DEV_IDECD
tristate "Include IDE/ATAPI CDROM support" tristate "Include IDE/ATAPI CDROM support"
---help--- ---help---
...@@ -264,6 +271,13 @@ config BLK_DEV_IDESCSI ...@@ -264,6 +271,13 @@ config BLK_DEV_IDESCSI
If both this SCSI emulation and native ATAPI support are compiled If both this SCSI emulation and native ATAPI support are compiled
into the kernel, the native support will be used. into the kernel, the native support will be used.
config BLK_DEV_IDEACPI
bool "IDE ACPI support"
depends on ACPI
---help---
Implement ACPI support for generic IDE devices. On modern
machines ACPI support is required to properly handle ACPI S3 states.
config IDE_TASK_IOCTL config IDE_TASK_IOCTL
bool "IDE Taskfile Access" bool "IDE Taskfile Access"
help help
...@@ -606,6 +620,11 @@ config BLK_DEV_PIIX ...@@ -606,6 +620,11 @@ config BLK_DEV_PIIX
the kernel to change PIO, DMA and UDMA speeds and to configure the kernel to change PIO, DMA and UDMA speeds and to configure
the chip to optimum performance. the chip to optimum performance.
config BLK_DEV_IT8213
tristate "IT8213 IDE support"
help
This driver adds support for the ITE 8213 IDE controller.
config BLK_DEV_IT821X config BLK_DEV_IT821X
tristate "IT821X IDE support" tristate "IT821X IDE support"
help help
...@@ -742,6 +761,11 @@ config BLK_DEV_VIA82CXXX ...@@ -742,6 +761,11 @@ config BLK_DEV_VIA82CXXX
This allows the kernel to change PIO, DMA and UDMA speeds and to This allows the kernel to change PIO, DMA and UDMA speeds and to
configure the chip to optimum performance. configure the chip to optimum performance.
config BLK_DEV_TC86C001
tristate "Toshiba TC86C001 support"
help
This driver adds support for Toshiba TC86C001 GOKU-S chip.
endif endif
config BLK_DEV_IDE_PMAC config BLK_DEV_IDE_PMAC
......
...@@ -22,6 +22,7 @@ ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o ...@@ -22,6 +22,7 @@ ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o
ide-core-$(CONFIG_BLK_DEV_IDEDMA) += ide-dma.o ide-core-$(CONFIG_BLK_DEV_IDEDMA) += ide-dma.o
ide-core-$(CONFIG_PROC_FS) += ide-proc.o ide-core-$(CONFIG_PROC_FS) += ide-proc.o
ide-core-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o ide-core-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o
ide-core-$(CONFIG_BLK_DEV_IDEACPI) += ide-acpi.o
# built-in only drivers from arm/ # built-in only drivers from arm/
ide-core-$(CONFIG_IDE_ARM) += arm/ide_arm.o ide-core-$(CONFIG_IDE_ARM) += arm/ide_arm.o
......
This diff is collapsed.
...@@ -1384,6 +1384,9 @@ static int hwif_init(ide_hwif_t *hwif) ...@@ -1384,6 +1384,9 @@ static int hwif_init(ide_hwif_t *hwif)
done: done:
init_gendisk(hwif); init_gendisk(hwif);
ide_acpi_init(hwif);
hwif->present = 1; /* success */ hwif->present = 1; /* success */
return 1; return 1;
......
...@@ -187,6 +187,12 @@ int noautodma = 1; ...@@ -187,6 +187,12 @@ int noautodma = 1;
EXPORT_SYMBOL(noautodma); EXPORT_SYMBOL(noautodma);
#ifdef CONFIG_BLK_DEV_IDEACPI
int ide_noacpi = 0;
int ide_noacpitfs = 1;
int ide_noacpionboot = 1;
#endif
/* /*
* This is declared extern in ide.h, for access by other IDE modules: * This is declared extern in ide.h, for access by other IDE modules:
*/ */
...@@ -1214,10 +1220,15 @@ EXPORT_SYMBOL(system_bus_clock); ...@@ -1214,10 +1220,15 @@ EXPORT_SYMBOL(system_bus_clock);
static int generic_ide_suspend(struct device *dev, pm_message_t mesg) static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
{ {
ide_drive_t *drive = dev->driver_data; ide_drive_t *drive = dev->driver_data;
ide_hwif_t *hwif = HWIF(drive);
struct request rq; struct request rq;
struct request_pm_state rqpm; struct request_pm_state rqpm;
ide_task_t args; ide_task_t args;
/* Call ACPI _GTM only once */
if (!(drive->dn % 2))
ide_acpi_get_timing(hwif);
memset(&rq, 0, sizeof(rq)); memset(&rq, 0, sizeof(rq));
memset(&rqpm, 0, sizeof(rqpm)); memset(&rqpm, 0, sizeof(rqpm));
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
...@@ -1235,10 +1246,17 @@ static int generic_ide_suspend(struct device *dev, pm_message_t mesg) ...@@ -1235,10 +1246,17 @@ static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
static int generic_ide_resume(struct device *dev) static int generic_ide_resume(struct device *dev)
{ {
ide_drive_t *drive = dev->driver_data; ide_drive_t *drive = dev->driver_data;
ide_hwif_t *hwif = HWIF(drive);
struct request rq; struct request rq;
struct request_pm_state rqpm; struct request_pm_state rqpm;
ide_task_t args; ide_task_t args;
/* Call ACPI _STM only once */
if (!(drive->dn % 2))
ide_acpi_push_timing(hwif);
ide_acpi_exec_tfs(drive);
memset(&rq, 0, sizeof(rq)); memset(&rq, 0, sizeof(rq));
memset(&rqpm, 0, sizeof(rqpm)); memset(&rqpm, 0, sizeof(rqpm));
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
...@@ -1543,6 +1561,24 @@ static int __init ide_setup(char *s) ...@@ -1543,6 +1561,24 @@ static int __init ide_setup(char *s)
} }
#endif /* CONFIG_BLK_DEV_IDEPCI */ #endif /* CONFIG_BLK_DEV_IDEPCI */
#ifdef CONFIG_BLK_DEV_IDEACPI
if (!strcmp(s, "ide=noacpi")) {
//printk(" : Disable IDE ACPI support.\n");
ide_noacpi = 1;
return 1;
}
if (!strcmp(s, "ide=acpigtf")) {
//printk(" : Enable IDE ACPI _GTF support.\n");
ide_noacpitfs = 0;
return 1;
}
if (!strcmp(s, "ide=acpionboot")) {
//printk(" : Call IDE ACPI methods on boot.\n");
ide_noacpionboot = 0;
return 1;
}
#endif /* CONFIG_BLK_DEV_IDEACPI */
/* /*
* Look for drive options: "hdx=" * Look for drive options: "hdx="
*/ */
......
...@@ -9,9 +9,10 @@ obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o ...@@ -9,9 +9,10 @@ obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o
obj-$(CONFIG_BLK_DEV_CS5535) += cs5535.o obj-$(CONFIG_BLK_DEV_CS5535) += cs5535.o
obj-$(CONFIG_BLK_DEV_SC1200) += sc1200.o obj-$(CONFIG_BLK_DEV_SC1200) += sc1200.o
obj-$(CONFIG_BLK_DEV_CY82C693) += cy82c693.o obj-$(CONFIG_BLK_DEV_CY82C693) += cy82c693.o
obj-$(CONFIG_BLK_DEV_DELKIN) += delkin_cb.o
obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o
obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o
#obj-$(CONFIG_BLK_DEV_HPT37X) += hpt37x.o obj-$(CONFIG_BLK_DEV_IT8213) += it8213.o
obj-$(CONFIG_BLK_DEV_IT821X) += it821x.o obj-$(CONFIG_BLK_DEV_IT821X) += it821x.o
obj-$(CONFIG_BLK_DEV_JMICRON) += jmicron.o obj-$(CONFIG_BLK_DEV_JMICRON) += jmicron.o
obj-$(CONFIG_BLK_DEV_NS87415) += ns87415.o obj-$(CONFIG_BLK_DEV_NS87415) += ns87415.o
...@@ -26,6 +27,7 @@ obj-$(CONFIG_BLK_DEV_SIIMAGE) += siimage.o ...@@ -26,6 +27,7 @@ obj-$(CONFIG_BLK_DEV_SIIMAGE) += siimage.o
obj-$(CONFIG_BLK_DEV_SIS5513) += sis5513.o obj-$(CONFIG_BLK_DEV_SIS5513) += sis5513.o
obj-$(CONFIG_BLK_DEV_SL82C105) += sl82c105.o obj-$(CONFIG_BLK_DEV_SL82C105) += sl82c105.o
obj-$(CONFIG_BLK_DEV_SLC90E66) += slc90e66.o obj-$(CONFIG_BLK_DEV_SLC90E66) += slc90e66.o
obj-$(CONFIG_BLK_DEV_TC86C001) += tc86c001.o
obj-$(CONFIG_BLK_DEV_TRIFLEX) += triflex.o obj-$(CONFIG_BLK_DEV_TRIFLEX) += triflex.o
obj-$(CONFIG_BLK_DEV_TRM290) += trm290.o obj-$(CONFIG_BLK_DEV_TRM290) += trm290.o
obj-$(CONFIG_BLK_DEV_VIA82CXXX) += via82cxxx.o obj-$(CONFIG_BLK_DEV_VIA82CXXX) += via82cxxx.o
......
/*
* linux/drivers/ide/pci/delkin_cb.c
*
* Created 20 Oct 2004 by Mark Lord
*
* Basic support for Delkin/ASKA/Workbit Cardbus CompactFlash adapter
*
* Modeled after the 16-bit PCMCIA driver: ide-cs.c
*
* This is slightly peculiar, in that it is a PCI driver,
* but is NOT an IDE PCI driver -- the IDE layer does not directly
* support hot insertion/removal of PCI interfaces, so this driver
* is unable to use the IDE PCI interfaces. Instead, it uses the
* same interfaces as the ide-cs (PCMCIA) driver uses.
* On the plus side, the driver is also smaller/simpler this way.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*/
#include <linux/autoconf.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <asm/io.h>
/*
* No chip documentation has yet been found,
* so these configuration values were pulled from
* a running Win98 system using "debug".
* This gives around 3MByte/second read performance,
* which is about 2/3 of what the chip is capable of.
*
* There is also a 4KByte mmio region on the card,
* but its purpose has yet to be reverse-engineered.
*/
static const u8 setup[] = {
0x00, 0x05, 0xbe, 0x01, 0x20, 0x8f, 0x00, 0x00,
0xa4, 0x1f, 0xb3, 0x1b, 0x00, 0x00, 0x00, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xa4, 0x83, 0x02, 0x13,
};
static int __devinit
delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
{
unsigned long base;
hw_regs_t hw;
ide_hwif_t *hwif = NULL;
ide_drive_t *drive;
int i, rc;
rc = pci_enable_device(dev);
if (rc) {
printk(KERN_ERR "delkin_cb: pci_enable_device failed (%d)\n", rc);
return rc;
}
rc = pci_request_regions(dev, "delkin_cb");
if (rc) {
printk(KERN_ERR "delkin_cb: pci_request_regions failed (%d)\n", rc);
pci_disable_device(dev);
return rc;
}
base = pci_resource_start(dev, 0);
outb(0x02, base + 0x1e); /* set nIEN to block interrupts */
inb(base + 0x17); /* read status to clear interrupts */
for (i = 0; i < sizeof(setup); ++i) {
if (setup[i])
outb(setup[i], base + i);
}
pci_release_regions(dev); /* IDE layer handles regions itself */
memset(&hw, 0, sizeof(hw));
ide_std_init_ports(&hw, base + 0x10, base + 0x1e);
hw.irq = dev->irq;
hw.chipset = ide_pci; /* this enables IRQ sharing */
rc = ide_register_hw_with_fixup(&hw, &hwif, ide_undecoded_slave);
if (rc < 0) {
printk(KERN_ERR "delkin_cb: ide_register_hw failed (%d)\n", rc);
pci_disable_device(dev);
return -ENODEV;
}
pci_set_drvdata(dev, hwif);
hwif->pci_dev = dev;
drive = &hwif->drives[0];
if (drive->present) {
drive->io_32bit = 1;
drive->unmask = 1;
}
return 0;
}
static void
delkin_cb_remove (struct pci_dev *dev)
{
ide_hwif_t *hwif = pci_get_drvdata(dev);
if (hwif)
ide_unregister(hwif->index);
pci_disable_device(dev);
}
static struct pci_device_id delkin_cb_pci_tbl[] __devinitdata = {
{ 0x1145, 0xf021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ 0, },
};
MODULE_DEVICE_TABLE(pci, delkin_cb_pci_tbl);
static struct pci_driver driver = {
.name = "Delkin-ASKA-Workbit Cardbus IDE",
.id_table = delkin_cb_pci_tbl,
.probe = delkin_cb_probe,
.remove = delkin_cb_remove,
};
static int
delkin_cb_init (void)
{
return pci_module_init(&driver);
}
static void
delkin_cb_exit (void)
{
pci_unregister_driver(&driver);
}
module_init(delkin_cb_init);
module_exit(delkin_cb_exit);
MODULE_AUTHOR("Mark Lord");
MODULE_DESCRIPTION("Basic support for Delkin/ASKA/Workbit Cardbus IDE");
MODULE_LICENSE("GPL");
This diff is collapsed.
/*
* ITE 8213 IDE driver
*
* Copyright (C) 2006 Jack Lee
* Copyright (C) 2006 Alan Cox
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <asm/io.h>
/*
* it8213_ratemask - Compute available modes
* @drive: IDE drive
*
* Compute the available speeds for the devices on the interface. This
* is all modes to ATA133 clipped by drive cable setup.
*/
static u8 it8213_ratemask (ide_drive_t *drive)
{
u8 mode = 4;
if (!eighty_ninty_three(drive))
mode = min_t(u8, mode, 1);
return mode;
}
/**
* it8213_dma_2_pio - return the PIO mode matching DMA
* @xfer_rate: transfer speed
*
* Returns the nearest equivalent PIO timing for the PIO or DMA
* mode requested by the controller.
*/
static u8 it8213_dma_2_pio (u8 xfer_rate) {
switch(xfer_rate) {
case XFER_UDMA_6:
case XFER_UDMA_5:
case XFER_UDMA_4:
case XFER_UDMA_3:
case XFER_UDMA_2:
case XFER_UDMA_1:
case XFER_UDMA_0:
case XFER_MW_DMA_2:
case XFER_PIO_4:
return 4;
case XFER_MW_DMA_1:
case XFER_PIO_3:
return 3;
case XFER_SW_DMA_2:
case XFER_PIO_2:
return 2;
case XFER_MW_DMA_0:
case XFER_SW_DMA_1:
case XFER_SW_DMA_0:
case XFER_PIO_1:
case XFER_PIO_0:
case XFER_PIO_SLOW:
default:
return 0;
}
}
/*
* it8213_tuneproc - tune a drive
* @drive: drive to tune
* @pio: desired PIO mode
*
* Set the interface PIO mode.
*/
static void it8213_tuneproc (ide_drive_t *drive, u8 pio)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
int is_slave = drive->dn & 1;
int master_port = 0x40;
int slave_port = 0x44;
unsigned long flags;
u16 master_data;
u8 slave_data;
static DEFINE_SPINLOCK(tune_lock);
int control = 0;
static const u8 timings[][2]= {
{ 0, 0 },
{ 0, 0 },
{ 1, 0 },
{ 2, 1 },
{ 2, 3 }, };
pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
spin_lock_irqsave(&tune_lock, flags);
pci_read_config_word(dev, master_port, &master_data);
if (pio > 1)
control |= 1; /* Programmable timing on */
if (drive->media != ide_disk)
control |= 4; /* ATAPI */
if (pio > 2)
control |= 2; /* IORDY */
if (is_slave) {
master_data |= 0x4000;
master_data &= ~0x0070;
if (pio > 1)
master_data = master_data | (control << 4);
pci_read_config_byte(dev, slave_port, &slave_data);
slave_data = slave_data & 0xf0;
slave_data = slave_data | (timings[pio][0] << 2) | timings[pio][1];
} else {
master_data &= ~0x3307;
if (pio > 1)
master_data = master_data | control;
master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8);
}
pci_write_config_word(dev, master_port, master_data);
if (is_slave)
pci_write_config_byte(dev, slave_port, slave_data);
spin_unlock_irqrestore(&tune_lock, flags);
}
/**
* it8213_tune_chipset - set controller timings
* @drive: Drive to set up
* @xferspeed: speed we want to achieve
*
* Tune the ITE chipset for the desired mode. If we can't achieve
* the desired mode then tune for a lower one, but ultimately
* make the thing work.
*/
static int it8213_tune_chipset (ide_drive_t *drive, u8 xferspeed)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
u8 maslave = 0x40;
u8 speed = ide_rate_filter(it8213_ratemask(drive), xferspeed);
int a_speed = 3 << (drive->dn * 4);
int u_flag = 1 << drive->dn;
int v_flag = 0x01 << drive->dn;
int w_flag = 0x10 << drive->dn;
int u_speed = 0;
u16 reg4042, reg4a;
u8 reg48, reg54, reg55;
pci_read_config_word(dev, maslave, &reg4042);
pci_read_config_byte(dev, 0x48, &reg48);
pci_read_config_word(dev, 0x4a, &reg4a);
pci_read_config_byte(dev, 0x54, &reg54);
pci_read_config_byte(dev, 0x55, &reg55);
switch(speed) {
case XFER_UDMA_6:
case XFER_UDMA_4:
case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break;
case XFER_UDMA_5:
case XFER_UDMA_3:
case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break;
case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break;
break;
case XFER_MW_DMA_2:
case XFER_MW_DMA_1:
case XFER_SW_DMA_2:
break;
case XFER_PIO_4:
case XFER_PIO_3:
case XFER_PIO_2:
case XFER_PIO_1:
case XFER_PIO_0:
break;
default:
return -1;
}
if (speed >= XFER_UDMA_0) {
if (!(reg48 & u_flag))
pci_write_config_byte(dev, 0x48, reg48 | u_flag);
if (speed >= XFER_UDMA_5) {
pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag);
} else {
pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
}
if ((reg4a & a_speed) != u_speed)
pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed);
if (speed > XFER_UDMA_2) {
if (!(reg54 & v_flag))
pci_write_config_byte(dev, 0x54, reg54 | v_flag);
} else
pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
} else {
if (reg48 & u_flag)
pci_write_config_byte(dev, 0x48, reg48 & ~u_flag);
if (reg4a & a_speed)
pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
if (reg54 & v_flag)
pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
if (reg55 & w_flag)
pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
}
it8213_tuneproc(drive, it8213_dma_2_pio(speed));
return ide_config_drive_speed(drive, speed);
}
/*
* config_chipset_for_dma - configure for DMA
* @drive: drive to configure
*
* Called by the IDE layer when it wants the timings set up.
*/
static int config_chipset_for_dma (ide_drive_t *drive)
{
u8 speed = ide_dma_speed(drive, it8213_ratemask(drive));
if (!speed)
return 0;
it8213_tune_chipset(drive, speed);
return ide_dma_enable(drive);
}
/**
* it8213_configure_drive_for_dma - set up for DMA transfers
* @drive: drive we are going to set up
*
* Set up the drive for DMA, tune the controller and drive as
* required. If the drive isn't suitable for DMA or we hit
* other problems then we will drop down to PIO and set up
* PIO appropriately
*/
static int it8213_config_drive_for_dma (ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
if (ide_use_dma(drive)) {
if (config_chipset_for_dma(drive))
return hwif->ide_dma_on(drive);
}
hwif->speedproc(drive, XFER_PIO_0
+ ide_get_best_pio_mode(drive, 255, 4, NULL));
return hwif->ide_dma_off_quietly(drive);
}
/**
* init_hwif_it8213 - set up hwif structs
* @hwif: interface to set up
*
* We do the basic set up of the interface structure. The IT8212
* requires several custom handlers so we override the default
* ide DMA handlers appropriately
*/
static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
{
u8 reg42h = 0, ata66 = 0;
hwif->speedproc = &it8213_tune_chipset;
hwif->tuneproc = &it8213_tuneproc;
hwif->autodma = 0;
hwif->drives[0].autotune = 1;
hwif->drives[1].autotune = 1;
if (!hwif->dma_base)
return;
hwif->atapi_dma = 1;
hwif->ultra_mask = 0x7f;
hwif->mwdma_mask = 0x06;
hwif->swdma_mask = 0x04;
pci_read_config_byte(hwif->pci_dev, 0x42, &reg42h);
ata66 = (reg42h & 0x02) ? 0 : 1;
hwif->ide_dma_check = &it8213_config_drive_for_dma;
if (!(hwif->udma_four))
hwif->udma_four = ata66;
/*
* The BIOS often doesn't set up DMA on this controller
* so we always do it.
*/
if (!noautodma)
hwif->autodma = 1;
hwif->drives[0].autodma = hwif->autodma;
hwif->drives[1].autodma = hwif->autodma;
}
#define DECLARE_ITE_DEV(name_str) \
{ \
.name = name_str, \
.init_hwif = init_hwif_it8213, \
.channels = 1, \
.autodma = AUTODMA, \
.enablebits = {{0x41,0x80,0x80}}, \
.bootable = ON_BOARD, \
}
static ide_pci_device_t it8213_chipsets[] __devinitdata = {
/* 0 */ DECLARE_ITE_DEV("IT8213"),
};
/**
* it8213_init_one - pci layer discovery entry
* @dev: PCI device
* @id: ident table entry
*
* Called by the PCI code when it finds an ITE8213 controller. As
* this device follows the standard interfaces we can use the
* standard helper functions to do almost all the work for us.
*/
static int __devinit it8213_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
ide_setup_pci_device(dev, &it8213_chipsets[id->driver_data]);
return 0;
}
static struct pci_device_id it8213_pci_tbl[] = {
{ PCI_VENDOR_ID_ITE, 0x8213, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, it8213_pci_tbl);
static struct pci_driver driver = {
.name = "ITE8213_IDE",
.id_table = it8213_pci_tbl,
.probe = it8213_init_one,
};
static int __init it8213_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
module_init(it8213_ide_init);
MODULE_AUTHOR("Jack Lee, Alan Cox");
MODULE_DESCRIPTION("PCI driver module for the ITE 8213");
MODULE_LICENSE("GPL");
...@@ -92,26 +92,6 @@ static u8 pdcnew_ratemask(ide_drive_t *drive) ...@@ -92,26 +92,6 @@ static u8 pdcnew_ratemask(ide_drive_t *drive)
return mode; return mode;
} }
static int check_in_drive_lists(ide_drive_t *drive, const char **list)
{
struct hd_driveid *id = drive->id;
if (pdc_quirk_drives == list) {
while (*list) {
if (strstr(id->model, *list++)) {
return 2;
}
}
} else {
while (*list) {
if (!strcmp(*list++,id->model)) {
return 1;
}
}
}
return 0;
}
/** /**
* get_indexed_reg - Get indexed register * get_indexed_reg - Get indexed register
* @hwif: for the port address * @hwif: for the port address
...@@ -249,13 +229,6 @@ static int pdcnew_tune_chipset(ide_drive_t *drive, u8 speed) ...@@ -249,13 +229,6 @@ static int pdcnew_tune_chipset(ide_drive_t *drive, u8 speed)
return err; return err;
} }
/* 0 1 2 3 4 5 6 7 8
* 960, 480, 390, 300, 240, 180, 120, 90, 60
* 180, 150, 120, 90, 60
* DMA_Speed
* 180, 120, 90, 90, 90, 60, 30
* 11, 5, 4, 3, 2, 1, 0
*/
static void pdcnew_tune_drive(ide_drive_t *drive, u8 pio) static void pdcnew_tune_drive(ide_drive_t *drive, u8 pio)
{ {
pio = ide_get_best_pio_mode(drive, pio, 4, NULL); pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
...@@ -313,12 +286,10 @@ static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive) ...@@ -313,12 +286,10 @@ static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive)
drive->init_speed = 0; drive->init_speed = 0;
if (id && (id->capability & 1) && drive->autodma) { if ((id->capability & 1) && drive->autodma) {
if (ide_use_dma(drive)) { if (ide_use_dma(drive) && config_chipset_for_dma(drive))
if (config_chipset_for_dma(drive))
return hwif->ide_dma_on(drive); return hwif->ide_dma_on(drive);
}
goto fast_ata_pio; goto fast_ata_pio;
...@@ -333,21 +304,12 @@ fast_ata_pio: ...@@ -333,21 +304,12 @@ fast_ata_pio:
static int pdcnew_quirkproc(ide_drive_t *drive) static int pdcnew_quirkproc(ide_drive_t *drive)
{ {
return check_in_drive_lists(drive, pdc_quirk_drives); const char **list, *model = drive->id->model;
}
static int pdcnew_ide_dma_lostirq(ide_drive_t *drive) for (list = pdc_quirk_drives; *list != NULL; list++)
{ if (strstr(model, *list) != NULL)
if (HWIF(drive)->resetproc != NULL) return 2;
HWIF(drive)->resetproc(drive); return 0;
return __ide_dma_lostirq(drive);
}
static int pdcnew_ide_dma_timeout(ide_drive_t *drive)
{
if (HWIF(drive)->resetproc != NULL)
HWIF(drive)->resetproc(drive);
return __ide_dma_timeout(drive);
} }
static void pdcnew_reset(ide_drive_t *drive) static void pdcnew_reset(ide_drive_t *drive)
...@@ -599,8 +561,6 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif) ...@@ -599,8 +561,6 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif)
hwif->err_stops_fifo = 1; hwif->err_stops_fifo = 1;
hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate; hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate;
hwif->ide_dma_lostirq = &pdcnew_ide_dma_lostirq;
hwif->ide_dma_timeout = &pdcnew_ide_dma_timeout;
if (!hwif->udma_four) if (!hwif->udma_four)
hwif->udma_four = pdcnew_cable_detect(hwif) ? 0 : 1; hwif->udma_four = pdcnew_cable_detect(hwif) ? 0 : 1;
......
...@@ -123,26 +123,6 @@ static u8 pdc202xx_ratemask (ide_drive_t *drive) ...@@ -123,26 +123,6 @@ static u8 pdc202xx_ratemask (ide_drive_t *drive)
return mode; return mode;
} }
static int check_in_drive_lists (ide_drive_t *drive, const char **list)
{
struct hd_driveid *id = drive->id;
if (pdc_quirk_drives == list) {
while (*list) {
if (strstr(id->model, *list++)) {
return 2;
}
}
} else {
while (*list) {
if (!strcmp(*list++,id->model)) {
return 1;
}
}
}
return 0;
}
static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed) static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed)
{ {
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
...@@ -377,7 +357,12 @@ fast_ata_pio: ...@@ -377,7 +357,12 @@ fast_ata_pio:
static int pdc202xx_quirkproc (ide_drive_t *drive) static int pdc202xx_quirkproc (ide_drive_t *drive)
{ {
return ((int) check_in_drive_lists(drive, pdc_quirk_drives)); const char **list, *model = drive->id->model;
for (list = pdc_quirk_drives; *list != NULL; list++)
if (strstr(model, *list) != NULL)
return 2;
return 0;
} }
static void pdc202xx_old_ide_dma_start(ide_drive_t *drive) static void pdc202xx_old_ide_dma_start(ide_drive_t *drive)
......
/* /*
* linux/drivers/ide/pci/piix.c Version 0.45 May 12, 2006 * linux/drivers/ide/pci/piix.c Version 0.46 December 3, 2006
* *
* Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
* Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
...@@ -163,7 +163,7 @@ static u8 piix_ratemask (ide_drive_t *drive) ...@@ -163,7 +163,7 @@ static u8 piix_ratemask (ide_drive_t *drive)
* if the drive cannot see an 80pin cable. * if the drive cannot see an 80pin cable.
*/ */
if (!eighty_ninty_three(drive)) if (!eighty_ninty_three(drive))
mode = min(mode, (u8)1); mode = min_t(u8, mode, 1);
return mode; return mode;
} }
...@@ -216,7 +216,7 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio) ...@@ -216,7 +216,7 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio)
{ {
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev; struct pci_dev *dev = hwif->pci_dev;
int is_slave = (&hwif->drives[1] == drive); int is_slave = drive->dn & 1;
int master_port = hwif->channel ? 0x42 : 0x40; int master_port = hwif->channel ? 0x42 : 0x40;
int slave_port = 0x44; int slave_port = 0x44;
unsigned long flags; unsigned long flags;
...@@ -233,7 +233,7 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio) ...@@ -233,7 +233,7 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio)
{ 2, 1 }, { 2, 1 },
{ 2, 3 }, }; { 2, 3 }, };
pio = ide_get_best_pio_mode(drive, pio, 5, NULL); pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
/* /*
* Master vs slave is synchronized above us but the slave register is * Master vs slave is synchronized above us but the slave register is
...@@ -243,25 +243,24 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio) ...@@ -243,25 +243,24 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio)
spin_lock_irqsave(&tune_lock, flags); spin_lock_irqsave(&tune_lock, flags);
pci_read_config_word(dev, master_port, &master_data); pci_read_config_word(dev, master_port, &master_data);
if (pio >= 2) if (pio > 1)
control |= 1; /* Programmable timing on */ control |= 1; /* Programmable timing on */
if (drive->media == ide_disk) if (drive->media == ide_disk)
control |= 4; /* Prefetch, post write */ control |= 4; /* Prefetch, post write */
if (pio >= 3) if (pio > 2)
control |= 2; /* IORDY */ control |= 2; /* IORDY */
if (is_slave) { if (is_slave) {
master_data = master_data | 0x4000; master_data |= 0x4000;
master_data &= ~0x0070;
if (pio > 1) { if (pio > 1) {
/* enable PPE, IE and TIME */ /* enable PPE, IE and TIME */
master_data = master_data | (control << 4); master_data = master_data | (control << 4);
} else {
master_data &= ~0x0070;
} }
pci_read_config_byte(dev, slave_port, &slave_data); pci_read_config_byte(dev, slave_port, &slave_data);
slave_data = slave_data & (hwif->channel ? 0x0f : 0xf0); slave_data = slave_data & (hwif->channel ? 0x0f : 0xf0);
slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) << (hwif->channel ? 4 : 0)); slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) << (hwif->channel ? 4 : 0));
} else { } else {
master_data = master_data & 0xccf8; master_data &= ~0x3307;
if (pio > 1) { if (pio > 1) {
/* enable PPE, IE and TIME */ /* enable PPE, IE and TIME */
master_data = master_data | control; master_data = master_data | control;
...@@ -539,13 +538,19 @@ static ide_pci_device_t piix_pci_info[] __devinitdata = { ...@@ -539,13 +538,19 @@ static ide_pci_device_t piix_pci_info[] __devinitdata = {
/* 0 */ DECLARE_PIIX_DEV("PIIXa"), /* 0 */ DECLARE_PIIX_DEV("PIIXa"),
/* 1 */ DECLARE_PIIX_DEV("PIIXb"), /* 1 */ DECLARE_PIIX_DEV("PIIXb"),
{ /* 2 */ /* 2 */
{ /*
* MPIIX actually has only a single IDE channel mapped to
* the primary or secondary ports depending on the value
* of the bit 14 of the IDETIM register at offset 0x6c
*/
.name = "MPIIX", .name = "MPIIX",
.init_hwif = init_hwif_piix, .init_hwif = init_hwif_piix,
.channels = 2, .channels = 2,
.autodma = NODMA, .autodma = NODMA,
.enablebits = {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}}, .enablebits = {{0x6d,0xc0,0x80}, {0x6d,0xc0,0xc0}},
.bootable = ON_BOARD, .bootable = ON_BOARD,
.flags = IDEPCI_FLAG_ISA_PORTS
}, },
/* 3 */ DECLARE_PIIX_DEV("PIIX3"), /* 3 */ DECLARE_PIIX_DEV("PIIX3"),
......
/* /*
* linux/drivers/ide/pci/slc90e66.c Version 0.12 May 12, 2006 * linux/drivers/ide/pci/slc90e66.c Version 0.13 December 30, 2006
* *
* Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2006 MontaVista Software, Inc. <source@mvista.com> * Copyright (C) 2006 MontaVista Software, Inc. <source@mvista.com>
...@@ -26,7 +26,7 @@ static u8 slc90e66_ratemask (ide_drive_t *drive) ...@@ -26,7 +26,7 @@ static u8 slc90e66_ratemask (ide_drive_t *drive)
u8 mode = 2; u8 mode = 2;
if (!eighty_ninty_three(drive)) if (!eighty_ninty_three(drive))
mode = min(mode, (u8)1); mode = min_t(u8, mode, 1);
return mode; return mode;
} }
...@@ -65,12 +65,13 @@ static void slc90e66_tune_drive (ide_drive_t *drive, u8 pio) ...@@ -65,12 +65,13 @@ static void slc90e66_tune_drive (ide_drive_t *drive, u8 pio)
{ {
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev; struct pci_dev *dev = hwif->pci_dev;
int is_slave = (&hwif->drives[1] == drive); int is_slave = drive->dn & 1;
int master_port = hwif->channel ? 0x42 : 0x40; int master_port = hwif->channel ? 0x42 : 0x40;
int slave_port = 0x44; int slave_port = 0x44;
unsigned long flags; unsigned long flags;
u16 master_data; u16 master_data;
u8 slave_data; u8 slave_data;
int control = 0;
/* ISP RTC */ /* ISP RTC */
static const u8 timings[][2]= { static const u8 timings[][2]= {
{ 0, 0 }, { 0, 0 },
...@@ -79,22 +80,32 @@ static void slc90e66_tune_drive (ide_drive_t *drive, u8 pio) ...@@ -79,22 +80,32 @@ static void slc90e66_tune_drive (ide_drive_t *drive, u8 pio)
{ 2, 1 }, { 2, 1 },
{ 2, 3 }, }; { 2, 3 }, };
pio = ide_get_best_pio_mode(drive, pio, 5, NULL); pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
spin_lock_irqsave(&ide_lock, flags); spin_lock_irqsave(&ide_lock, flags);
pci_read_config_word(dev, master_port, &master_data); pci_read_config_word(dev, master_port, &master_data);
if (is_slave) {
master_data = master_data | 0x4000;
if (pio > 1) if (pio > 1)
control |= 1; /* Programmable timing on */
if (drive->media == ide_disk)
control |= 4; /* Prefetch, post write */
if (pio > 2)
control |= 2; /* IORDY */
if (is_slave) {
master_data |= 0x4000;
master_data &= ~0x0070;
if (pio > 1) {
/* enable PPE, IE and TIME */ /* enable PPE, IE and TIME */
master_data = master_data | 0x0070; master_data = master_data | (control << 4);
}
pci_read_config_byte(dev, slave_port, &slave_data); pci_read_config_byte(dev, slave_port, &slave_data);
slave_data = slave_data & (hwif->channel ? 0x0f : 0xf0); slave_data = slave_data & (hwif->channel ? 0x0f : 0xf0);
slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) << (hwif->channel ? 4 : 0)); slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) << (hwif->channel ? 4 : 0));
} else { } else {
master_data = master_data & 0xccf8; master_data &= ~0x3307;
if (pio > 1) if (pio > 1) {
/* enable PPE, IE and TIME */ /* enable PPE, IE and TIME */
master_data = master_data | 0x0007; master_data = master_data | control;
}
master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8); master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8);
} }
pci_write_config_word(dev, master_port, master_data); pci_write_config_word(dev, master_port, master_data);
...@@ -173,7 +184,7 @@ static int slc90e66_config_drive_xfer_rate (ide_drive_t *drive) ...@@ -173,7 +184,7 @@ static int slc90e66_config_drive_xfer_rate (ide_drive_t *drive)
drive->init_speed = 0; drive->init_speed = 0;
if (id && (id->capability & 1) && drive->autodma) { if ((id->capability & 1) && drive->autodma) {
if (ide_use_dma(drive) && slc90e66_config_drive_for_dma(drive)) if (ide_use_dma(drive) && slc90e66_config_drive_for_dma(drive))
return hwif->ide_dma_on(drive); return hwif->ide_dma_on(drive);
...@@ -213,14 +224,16 @@ static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif) ...@@ -213,14 +224,16 @@ static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif)
hwif->atapi_dma = 1; hwif->atapi_dma = 1;
hwif->ultra_mask = 0x1f; hwif->ultra_mask = 0x1f;
hwif->mwdma_mask = 0x07; hwif->mwdma_mask = 0x06;
hwif->swdma_mask = 0x07; hwif->swdma_mask = 0x04;
if (!(hwif->udma_four)) if (!hwif->udma_four) {
/* bit[0(1)]: 0:80, 1:40 */ /* bit[0(1)]: 0:80, 1:40 */
hwif->udma_four = (reg47 & mask) ? 0 : 1; hwif->udma_four = (reg47 & mask) ? 0 : 1;
}
hwif->ide_dma_check = &slc90e66_config_drive_xfer_rate; hwif->ide_dma_check = &slc90e66_config_drive_xfer_rate;
if (!noautodma) if (!noautodma)
hwif->autodma = 1; hwif->autodma = 1;
hwif->drives[0].autodma = hwif->autodma; hwif->drives[0].autodma = hwif->autodma;
......
/*
* drivers/ide/pci/tc86c001.c Version 1.00 Dec 12, 2006
*
* Copyright (C) 2002 Toshiba Corporation
* Copyright (C) 2005-2006 MontaVista Software, Inc. <source@mvista.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/ide.h>
static inline u8 tc86c001_ratemask(ide_drive_t *drive)
{
return eighty_ninty_three(drive) ? 2 : 1;
}
static int tc86c001_tune_chipset(ide_drive_t *drive, u8 speed)
{
ide_hwif_t *hwif = HWIF(drive);
unsigned long scr_port = hwif->config_data + (drive->dn ? 0x02 : 0x00);
u16 mode, scr = hwif->INW(scr_port);
speed = ide_rate_filter(tc86c001_ratemask(drive), speed);
switch (speed) {
case XFER_UDMA_4: mode = 0x00c0; break;
case XFER_UDMA_3: mode = 0x00b0; break;
case XFER_UDMA_2: mode = 0x00a0; break;
case XFER_UDMA_1: mode = 0x0090; break;
case XFER_UDMA_0: mode = 0x0080; break;
case XFER_MW_DMA_2: mode = 0x0070; break;
case XFER_MW_DMA_1: mode = 0x0060; break;
case XFER_MW_DMA_0: mode = 0x0050; break;
case XFER_PIO_4: mode = 0x0400; break;
case XFER_PIO_3: mode = 0x0300; break;
case XFER_PIO_2: mode = 0x0200; break;
case XFER_PIO_1: mode = 0x0100; break;
case XFER_PIO_0:
default: mode = 0x0000; break;
}
scr &= (speed < XFER_MW_DMA_0) ? 0xf8ff : 0xff0f;
scr |= mode;
hwif->OUTW(scr, scr_port);
return ide_config_drive_speed(drive, speed);
}
static void tc86c001_tune_drive(ide_drive_t *drive, u8 pio)
{
pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
(void) tc86c001_tune_chipset(drive, XFER_PIO_0 + pio);
}
/*
* HACKITY HACK
*
* This is a workaround for the limitation 5 of the TC86C001 IDE controller:
* if a DMA transfer terminates prematurely, the controller leaves the device's
* interrupt request (INTRQ) pending and does not generate a PCI interrupt (or
* set the interrupt bit in the DMA status register), thus no PCI interrupt
* will occur until a DMA transfer has been successfully completed.
*
* We work around this by initiating dummy, zero-length DMA transfer on
* a DMA timeout expiration. I found no better way to do this with the current
* IDE core than to temporarily replace a higher level driver's timer expiry
* handler with our own backing up to that handler in case our recovery fails.
*/
static int tc86c001_timer_expiry(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
ide_expiry_t *expiry = ide_get_hwifdata(hwif);
ide_hwgroup_t *hwgroup = HWGROUP(drive);
u8 dma_stat = hwif->INB(hwif->dma_status);
/* Restore a higher level driver's expiry handler first. */
hwgroup->expiry = expiry;
if ((dma_stat & 5) == 1) { /* DMA active and no interrupt */
unsigned long sc_base = hwif->config_data;
unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04);
u8 dma_cmd = hwif->INB(hwif->dma_command);
printk(KERN_WARNING "%s: DMA interrupt possibly stuck, "
"attempting recovery...\n", drive->name);
/* Stop DMA */
hwif->OUTB(dma_cmd & ~0x01, hwif->dma_command);
/* Setup the dummy DMA transfer */
hwif->OUTW(0, sc_base + 0x0a); /* Sector Count */
hwif->OUTW(0, twcr_port); /* Transfer Word Count 1 or 2 */
/* Start the dummy DMA transfer */
hwif->OUTB(0x00, hwif->dma_command); /* clear R_OR_WCTR for write */
hwif->OUTB(0x01, hwif->dma_command); /* set START_STOPBM */
/*
* If an interrupt was pending, it should come thru shortly.
* If not, a higher level driver's expiry handler should
* eventually cause some kind of recovery from the DMA stall.
*/
return WAIT_MIN_SLEEP;
}
/* Chain to the restored expiry handler if DMA wasn't active. */
if (likely(expiry != NULL))
return expiry(drive);
/* If there was no handler, "emulate" that for ide_timer_expiry()... */
return -1;
}
static void tc86c001_dma_start(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
ide_hwgroup_t *hwgroup = HWGROUP(drive);
unsigned long sc_base = hwif->config_data;
unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04);
unsigned long nsectors = hwgroup->rq->nr_sectors;
/*
* We have to manually load the sector count and size into
* the appropriate system control registers for DMA to work
* with LBA48 and ATAPI devices...
*/
hwif->OUTW(nsectors, sc_base + 0x0a); /* Sector Count */
hwif->OUTW(SECTOR_SIZE / 2, twcr_port); /* Transfer Word Count 1/2 */
/* Install our timeout expiry hook, saving the current handler... */
ide_set_hwifdata(hwif, hwgroup->expiry);
hwgroup->expiry = &tc86c001_timer_expiry;
ide_dma_start(drive);
}
static int tc86c001_busproc(ide_drive_t *drive, int state)
{
ide_hwif_t *hwif = HWIF(drive);
unsigned long sc_base = hwif->config_data;
u16 scr1;
/* System Control 1 Register bit 11 (ATA Hard Reset) read */
scr1 = hwif->INW(sc_base + 0x00);
switch (state) {
case BUSSTATE_ON:
if (!(scr1 & 0x0800))
return 0;
scr1 &= ~0x0800;
hwif->drives[0].failures = hwif->drives[1].failures = 0;
break;
case BUSSTATE_OFF:
if (scr1 & 0x0800)
return 0;
scr1 |= 0x0800;
hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
break;
default:
return -EINVAL;
}
/* System Control 1 Register bit 11 (ATA Hard Reset) write */
hwif->OUTW(scr1, sc_base + 0x00);
return 0;
}
static int config_chipset_for_dma(ide_drive_t *drive)
{
u8 speed = ide_dma_speed(drive, tc86c001_ratemask(drive));
if (!speed)
return 0;
(void) tc86c001_tune_chipset(drive, speed);
return ide_dma_enable(drive);
}
static int tc86c001_config_drive_xfer_rate(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
struct hd_driveid *id = drive->id;
if ((id->capability & 1) && drive->autodma) {
if (ide_use_dma(drive) && config_chipset_for_dma(drive))
return hwif->ide_dma_on(drive);
goto fast_ata_pio;
} else if ((id->capability & 8) || (id->field_valid & 2)) {
fast_ata_pio:
tc86c001_tune_drive(drive, 255);
return hwif->ide_dma_off_quietly(drive);
}
/* IORDY not supported */
return 0;
}
static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
{
unsigned long sc_base = pci_resource_start(hwif->pci_dev, 5);
u16 scr1 = hwif->INW(sc_base + 0x00);;
/* System Control 1 Register bit 15 (Soft Reset) set */
hwif->OUTW(scr1 | 0x8000, sc_base + 0x00);
/* System Control 1 Register bit 14 (FIFO Reset) set */
hwif->OUTW(scr1 | 0x4000, sc_base + 0x00);
/* System Control 1 Register: reset clear */
hwif->OUTW(scr1 & ~0xc000, sc_base + 0x00);
/* Store the system control register base for convenience... */
hwif->config_data = sc_base;
hwif->tuneproc = &tc86c001_tune_drive;
hwif->speedproc = &tc86c001_tune_chipset;
hwif->busproc = &tc86c001_busproc;
hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
if (!hwif->dma_base)
return;
/*
* Sector Count Control Register bits 0 and 1 set:
* software sets Sector Count Register for master and slave device
*/
hwif->OUTW(0x0003, sc_base + 0x0c);
/* Sector Count Register limit */
hwif->rqsize = 0xffff;
hwif->atapi_dma = 1;
hwif->ultra_mask = 0x1f;
hwif->mwdma_mask = 0x07;
hwif->ide_dma_check = &tc86c001_config_drive_xfer_rate;
hwif->dma_start = &tc86c001_dma_start;
if (!hwif->udma_four) {
/*
* System Control 1 Register bit 13 (PDIAGN):
* 0=80-pin cable, 1=40-pin cable
*/
scr1 = hwif->INW(sc_base + 0x00);
hwif->udma_four = (scr1 & 0x2000) ? 0 : 1;
}
if (!noautodma)
hwif->autodma = 1;
hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
}
static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev,
const char *name)
{
int err = pci_request_region(dev, 5, name);
if (err)
printk(KERN_ERR "%s: system control regs already in use", name);
return err;
}
static ide_pci_device_t tc86c001_chipset __devinitdata = {
.name = "TC86C001",
.init_chipset = init_chipset_tc86c001,
.init_hwif = init_hwif_tc86c001,
.channels = 1,
.autodma = AUTODMA,
.bootable = OFF_BOARD
};
static int __devinit tc86c001_init_one(struct pci_dev *dev,
const struct pci_device_id *id)
{
return ide_setup_pci_device(dev, &tc86c001_chipset);
}
static struct pci_device_id tc86c001_pci_tbl[] = {
{ PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ 0, }
};
MODULE_DEVICE_TABLE(pci, tc86c001_pci_tbl);
static struct pci_driver driver = {
.name = "TC86C001",
.id_table = tc86c001_pci_tbl,
.probe = tc86c001_init_one
};
static int __init tc86c001_ide_init(void)
{
return ide_pci_register_driver(&driver);
}
module_init(tc86c001_ide_init);
MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
MODULE_DESCRIPTION("PCI driver module for TC86C001 IDE");
MODULE_LICENSE("GPL");
...@@ -1460,6 +1460,24 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2609, quirk_intel_pcie_pm); ...@@ -1460,6 +1460,24 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2609, quirk_intel_pcie_pm);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260a, quirk_intel_pcie_pm); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260a, quirk_intel_pcie_pm);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm);
/*
* Toshiba TC86C001 IDE controller reports the standard 8-byte BAR0 size
* but the PIO transfers won't work if BAR0 falls at the odd 8 bytes.
* Re-allocate the region if needed...
*/
static void __init quirk_tc86c001_ide(struct pci_dev *dev)
{
struct resource *r = &dev->resource[0];
if (r->start & 0x8) {
r->start = 0;
r->end = 0xf;
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA_2,
PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE,
quirk_tc86c001_ide);
static void __devinit quirk_netmos(struct pci_dev *dev) static void __devinit quirk_netmos(struct pci_dev *dev)
{ {
unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4; unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4;
......
...@@ -18,6 +18,9 @@ ...@@ -18,6 +18,9 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/completion.h> #include <linux/completion.h>
#ifdef CONFIG_BLK_DEV_IDEACPI
#include <acpi/acpi.h>
#endif
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -541,6 +544,11 @@ typedef enum { ...@@ -541,6 +544,11 @@ typedef enum {
struct ide_driver_s; struct ide_driver_s;
struct ide_settings_s; struct ide_settings_s;
#ifdef CONFIG_BLK_DEV_IDEACPI
struct ide_acpi_drive_link;
struct ide_acpi_hwif_link;
#endif
typedef struct ide_drive_s { typedef struct ide_drive_s {
char name[4]; /* drive name, such as "hda" */ char name[4]; /* drive name, such as "hda" */
char driver_req[10]; /* requests specific driver */ char driver_req[10]; /* requests specific driver */
...@@ -637,6 +645,9 @@ typedef struct ide_drive_s { ...@@ -637,6 +645,9 @@ typedef struct ide_drive_s {
int lun; /* logical unit */ int lun; /* logical unit */
int crc_count; /* crc counter to reduce drive speed */ int crc_count; /* crc counter to reduce drive speed */
#ifdef CONFIG_BLK_DEV_IDEACPI
struct ide_acpi_drive_link *acpidata;
#endif
struct list_head list; struct list_head list;
struct device gendev; struct device gendev;
struct completion gendev_rel_comp; /* to deal with device release() */ struct completion gendev_rel_comp; /* to deal with device release() */
...@@ -804,6 +815,10 @@ typedef struct hwif_s { ...@@ -804,6 +815,10 @@ typedef struct hwif_s {
void *hwif_data; /* extra hwif data */ void *hwif_data; /* extra hwif data */
unsigned dma; unsigned dma;
#ifdef CONFIG_BLK_DEV_IDEACPI
struct ide_acpi_hwif_link *acpidata;
#endif
} ____cacheline_internodealigned_in_smp ide_hwif_t; } ____cacheline_internodealigned_in_smp ide_hwif_t;
/* /*
...@@ -1298,6 +1313,18 @@ static inline void ide_dma_verbose(ide_drive_t *drive) { ; } ...@@ -1298,6 +1313,18 @@ static inline void ide_dma_verbose(ide_drive_t *drive) { ; }
static inline void ide_release_dma(ide_hwif_t *drive) {;} static inline void ide_release_dma(ide_hwif_t *drive) {;}
#endif #endif
#ifdef CONFIG_BLK_DEV_IDEACPI
extern int ide_acpi_exec_tfs(ide_drive_t *drive);
extern void ide_acpi_get_timing(ide_hwif_t *hwif);
extern void ide_acpi_push_timing(ide_hwif_t *hwif);
extern void ide_acpi_init(ide_hwif_t *hwif);
#else
static inline int ide_acpi_exec_tfs(ide_drive_t *drive) { return 0; }
static inline void ide_acpi_get_timing(ide_hwif_t *hwif) { ; }
static inline void ide_acpi_push_timing(ide_hwif_t *hwif) { ; }
static inline void ide_acpi_init(ide_hwif_t *hwif) { ; }
#endif
extern int ide_hwif_request_regions(ide_hwif_t *hwif); extern int ide_hwif_request_regions(ide_hwif_t *hwif);
extern void ide_hwif_release_regions(ide_hwif_t* hwif); extern void ide_hwif_release_regions(ide_hwif_t* hwif);
extern void ide_unregister (unsigned int index); extern void ide_unregister (unsigned int index);
......
...@@ -1454,6 +1454,7 @@ ...@@ -1454,6 +1454,7 @@
#define PCI_VENDOR_ID_TOSHIBA_2 0x102f #define PCI_VENDOR_ID_TOSHIBA_2 0x102f
#define PCI_DEVICE_ID_TOSHIBA_TC35815CF 0x0030 #define PCI_DEVICE_ID_TOSHIBA_TC35815CF 0x0030
#define PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE 0x0105
#define PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC 0x0108 #define PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC 0x0108
#define PCI_DEVICE_ID_TOSHIBA_SPIDER_NET 0x01b3 #define PCI_DEVICE_ID_TOSHIBA_SPIDER_NET 0x01b3
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment