提交 905adce4 编写于 作者: L 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
  ...
...@@ -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
......
/*
* ide-acpi.c
* Provides ACPI support for IDE drives.
*
* Copyright (C) 2005 Intel Corp.
* Copyright (C) 2005 Randy Dunlap
* Copyright (C) 2006 SUSE Linux Products GmbH
* Copyright (C) 2006 Hannes Reinecke
*/
#include <linux/ata.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <acpi/acpi.h>
#include <linux/ide.h>
#include <linux/pci.h>
#include <acpi/acpi_bus.h>
#include <acpi/acnames.h>
#include <acpi/acnamesp.h>
#include <acpi/acparser.h>
#include <acpi/acexcep.h>
#include <acpi/acmacros.h>
#include <acpi/actypes.h>
#define REGS_PER_GTF 7
struct taskfile_array {
u8 tfa[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */
};
struct GTM_buffer {
u32 PIO_speed0;
u32 DMA_speed0;
u32 PIO_speed1;
u32 DMA_speed1;
u32 GTM_flags;
};
struct ide_acpi_drive_link {
ide_drive_t *drive;
acpi_handle obj_handle;
u8 idbuff[512];
};
struct ide_acpi_hwif_link {
ide_hwif_t *hwif;
acpi_handle obj_handle;
struct GTM_buffer gtm;
struct ide_acpi_drive_link master;
struct ide_acpi_drive_link slave;
};
#undef DEBUGGING
/* note: adds function name and KERN_DEBUG */
#ifdef DEBUGGING
#define DEBPRINT(fmt, args...) \
printk(KERN_DEBUG "%s: " fmt, __FUNCTION__, ## args)
#else
#define DEBPRINT(fmt, args...) do {} while (0)
#endif /* DEBUGGING */
extern int ide_noacpi;
extern int ide_noacpitfs;
extern int ide_noacpionboot;
/**
* ide_get_dev_handle - finds acpi_handle and PCI device.function
* @dev: device to locate
* @handle: returned acpi_handle for @dev
* @pcidevfn: return PCI device.func for @dev
*
* Returns the ACPI object handle to the corresponding PCI device.
*
* Returns 0 on success, <0 on error.
*/
static int ide_get_dev_handle(struct device *dev, acpi_handle *handle,
acpi_integer *pcidevfn)
{
struct pci_dev *pdev = to_pci_dev(dev);
unsigned int bus, devnum, func;
acpi_integer addr;
acpi_handle dev_handle;
struct acpi_buffer buffer = {.length = ACPI_ALLOCATE_BUFFER,
.pointer = NULL};
acpi_status status;
struct acpi_device_info *dinfo = NULL;
int ret = -ENODEV;
bus = pdev->bus->number;
devnum = PCI_SLOT(pdev->devfn);
func = PCI_FUNC(pdev->devfn);
/* ACPI _ADR encoding for PCI bus: */
addr = (acpi_integer)(devnum << 16 | func);
DEBPRINT("ENTER: pci %02x:%02x.%01x\n", bus, devnum, func);
dev_handle = DEVICE_ACPI_HANDLE(dev);
if (!dev_handle) {
DEBPRINT("no acpi handle for device\n");
goto err;
}
status = acpi_get_object_info(dev_handle, &buffer);
if (ACPI_FAILURE(status)) {
DEBPRINT("get_object_info for device failed\n");
goto err;
}
dinfo = buffer.pointer;
if (dinfo && (dinfo->valid & ACPI_VALID_ADR) &&
dinfo->address == addr) {
*pcidevfn = addr;
*handle = dev_handle;
} else {
DEBPRINT("get_object_info for device has wrong "
" address: %llu, should be %u\n",
dinfo ? (unsigned long long)dinfo->address : -1ULL,
(unsigned int)addr);
goto err;
}
DEBPRINT("for dev=0x%x.%x, addr=0x%llx, *handle=0x%p\n",
devnum, func, (unsigned long long)addr, *handle);
ret = 0;
err:
kfree(dinfo);
return ret;
}
/**
* ide_acpi_hwif_get_handle - Get ACPI object handle for a given hwif
* @hwif: device to locate
*
* Retrieves the object handle for a given hwif.
*
* Returns handle on success, 0 on error.
*/
static acpi_handle ide_acpi_hwif_get_handle(ide_hwif_t *hwif)
{
struct device *dev = hwif->gendev.parent;
acpi_handle dev_handle;
acpi_integer pcidevfn;
acpi_handle chan_handle;
int err;
DEBPRINT("ENTER: device %s\n", hwif->name);
if (!dev) {
DEBPRINT("no PCI device for %s\n", hwif->name);
return NULL;
}
err = ide_get_dev_handle(dev, &dev_handle, &pcidevfn);
if (err < 0) {
DEBPRINT("ide_get_dev_handle failed (%d)\n", err);
return NULL;
}
/* get child objects of dev_handle == channel objects,
* + _their_ children == drive objects */
/* channel is hwif->channel */
chan_handle = acpi_get_child(dev_handle, hwif->channel);
DEBPRINT("chan adr=%d: handle=0x%p\n",
hwif->channel, chan_handle);
return chan_handle;
}
/**
* ide_acpi_drive_get_handle - Get ACPI object handle for a given drive
* @drive: device to locate
*
* Retrieves the object handle of a given drive. According to the ACPI
* spec the drive is a child of the hwif.
*
* Returns handle on success, 0 on error.
*/
static acpi_handle ide_acpi_drive_get_handle(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
int port;
acpi_handle drive_handle;
if (!hwif->acpidata)
return NULL;
if (!hwif->acpidata->obj_handle)
return NULL;
port = hwif->channel ? drive->dn - 2: drive->dn;
DEBPRINT("ENTER: %s at channel#: %d port#: %d\n",
drive->name, hwif->channel, port);
/* TBD: could also check ACPI object VALID bits */
drive_handle = acpi_get_child(hwif->acpidata->obj_handle, port);
DEBPRINT("drive %s handle 0x%p\n", drive->name, drive_handle);
return drive_handle;
}
/**
* do_drive_get_GTF - get the drive bootup default taskfile settings
* @drive: the drive for which the taskfile settings should be retrieved
* @gtf_length: number of bytes of _GTF data returned at @gtf_address
* @gtf_address: buffer containing _GTF taskfile arrays
*
* The _GTF method has no input parameters.
* It returns a variable number of register set values (registers
* hex 1F1..1F7, taskfiles).
* The <variable number> is not known in advance, so have ACPI-CA
* allocate the buffer as needed and return it, then free it later.
*
* The returned @gtf_length and @gtf_address are only valid if the
* function return value is 0.
*/
static int do_drive_get_GTF(ide_drive_t *drive,
unsigned int *gtf_length, unsigned long *gtf_address,
unsigned long *obj_loc)
{
acpi_status status;
struct acpi_buffer output;
union acpi_object *out_obj;
ide_hwif_t *hwif = HWIF(drive);
struct device *dev = hwif->gendev.parent;
int err = -ENODEV;
int port;
*gtf_length = 0;
*gtf_address = 0UL;
*obj_loc = 0UL;
if (ide_noacpi)
return 0;
if (!dev) {
DEBPRINT("no PCI device for %s\n", hwif->name);
goto out;
}
if (!hwif->acpidata) {
DEBPRINT("no ACPI data for %s\n", hwif->name);
goto out;
}
port = hwif->channel ? drive->dn - 2: drive->dn;
if (!drive->acpidata) {
if (port == 0) {
drive->acpidata = &hwif->acpidata->master;
hwif->acpidata->master.drive = drive;
} else {
drive->acpidata = &hwif->acpidata->slave;
hwif->acpidata->slave.drive = drive;
}
}
DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n",
hwif->name, dev->bus_id, port, hwif->channel);
if (!drive->present) {
DEBPRINT("%s drive %d:%d not present\n",
hwif->name, hwif->channel, port);
goto out;
}
/* Get this drive's _ADR info. if not already known. */
if (!drive->acpidata->obj_handle) {
drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive);
if (!drive->acpidata->obj_handle) {
DEBPRINT("No ACPI object found for %s\n",
drive->name);
goto out;
}
}
/* Setting up output buffer */
output.length = ACPI_ALLOCATE_BUFFER;
output.pointer = NULL; /* ACPI-CA sets this; save/free it later */
/* _GTF has no input parameters */
err = -EIO;
status = acpi_evaluate_object(drive->acpidata->obj_handle, "_GTF",
NULL, &output);
if (ACPI_FAILURE(status)) {
printk(KERN_DEBUG
"%s: Run _GTF error: status = 0x%x\n",
__FUNCTION__, status);
goto out;
}
if (!output.length || !output.pointer) {
DEBPRINT("Run _GTF: "
"length or ptr is NULL (0x%llx, 0x%p)\n",
(unsigned long long)output.length,
output.pointer);
goto out;
}
out_obj = output.pointer;
if (out_obj->type != ACPI_TYPE_BUFFER) {
DEBPRINT("Run _GTF: error: "
"expected object type of ACPI_TYPE_BUFFER, "
"got 0x%x\n", out_obj->type);
err = -ENOENT;
kfree(output.pointer);
goto out;
}
if (!out_obj->buffer.length || !out_obj->buffer.pointer ||
out_obj->buffer.length % REGS_PER_GTF) {
printk(KERN_ERR
"%s: unexpected GTF length (%d) or addr (0x%p)\n",
__FUNCTION__, out_obj->buffer.length,
out_obj->buffer.pointer);
err = -ENOENT;
kfree(output.pointer);
goto out;
}
*gtf_length = out_obj->buffer.length;
*gtf_address = (unsigned long)out_obj->buffer.pointer;
*obj_loc = (unsigned long)out_obj;
DEBPRINT("returning gtf_length=%d, gtf_address=0x%lx, obj_loc=0x%lx\n",
*gtf_length, *gtf_address, *obj_loc);
err = 0;
out:
return err;
}
/**
* taskfile_load_raw - send taskfile registers to drive
* @drive: drive to which output is sent
* @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7)
*
* Outputs IDE taskfile to the drive.
*/
static int taskfile_load_raw(ide_drive_t *drive,
const struct taskfile_array *gtf)
{
ide_task_t args;
int err = 0;
DEBPRINT("(0x1f1-1f7): hex: "
"%02x %02x %02x %02x %02x %02x %02x\n",
gtf->tfa[0], gtf->tfa[1], gtf->tfa[2],
gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]);
memset(&args, 0, sizeof(ide_task_t));
args.command_type = IDE_DRIVE_TASK_NO_DATA;
args.data_phase = TASKFILE_IN;
args.handler = &task_no_data_intr;
/* convert gtf to IDE Taskfile */
args.tfRegister[1] = gtf->tfa[0]; /* 0x1f1 */
args.tfRegister[2] = gtf->tfa[1]; /* 0x1f2 */
args.tfRegister[3] = gtf->tfa[2]; /* 0x1f3 */
args.tfRegister[4] = gtf->tfa[3]; /* 0x1f4 */
args.tfRegister[5] = gtf->tfa[4]; /* 0x1f5 */
args.tfRegister[6] = gtf->tfa[5]; /* 0x1f6 */
args.tfRegister[7] = gtf->tfa[6]; /* 0x1f7 */
if (ide_noacpitfs) {
DEBPRINT("_GTF execution disabled\n");
return err;
}
err = ide_raw_taskfile(drive, &args, NULL);
if (err)
printk(KERN_ERR "%s: ide_raw_taskfile failed: %u\n",
__FUNCTION__, err);
return err;
}
/**
* do_drive_set_taskfiles - write the drive taskfile settings from _GTF
* @drive: the drive to which the taskfile command should be sent
* @gtf_length: total number of bytes of _GTF taskfiles
* @gtf_address: location of _GTF taskfile arrays
*
* Write {gtf_address, length gtf_length} in groups of
* REGS_PER_GTF bytes.
*/
static int do_drive_set_taskfiles(ide_drive_t *drive,
unsigned int gtf_length,
unsigned long gtf_address)
{
int rc = -ENODEV, err;
int gtf_count = gtf_length / REGS_PER_GTF;
int ix;
struct taskfile_array *gtf;
if (ide_noacpi)
return 0;
DEBPRINT("ENTER: %s, hard_port#: %d\n", drive->name, drive->dn);
if (!drive->present)
goto out;
if (!gtf_count) /* shouldn't be here */
goto out;
DEBPRINT("total GTF bytes=%u (0x%x), gtf_count=%d, addr=0x%lx\n",
gtf_length, gtf_length, gtf_count, gtf_address);
if (gtf_length % REGS_PER_GTF) {
printk(KERN_ERR "%s: unexpected GTF length (%d)\n",
__FUNCTION__, gtf_length);
goto out;
}
rc = 0;
for (ix = 0; ix < gtf_count; ix++) {
gtf = (struct taskfile_array *)
(gtf_address + ix * REGS_PER_GTF);
/* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */
err = taskfile_load_raw(drive, gtf);
if (err)
rc = err;
}
out:
return rc;
}
/**
* ide_acpi_exec_tfs - get then write drive taskfile settings
* @drive: the drive for which the taskfile settings should be
* written.
*
* According to the ACPI spec this should be called after _STM
* has been evaluated for the interface. Some ACPI vendors interpret
* that as a hard requirement and modify the taskfile according
* to the Identify Drive information passed down with _STM.
* So one should really make sure to call this only after _STM has
* been executed.
*/
int ide_acpi_exec_tfs(ide_drive_t *drive)
{
int ret;
unsigned int gtf_length;
unsigned long gtf_address;
unsigned long obj_loc;
if (ide_noacpi)
return 0;
DEBPRINT("call get_GTF, drive=%s port=%d\n", drive->name, drive->dn);
ret = do_drive_get_GTF(drive, &gtf_length, &gtf_address, &obj_loc);
if (ret < 0) {
DEBPRINT("get_GTF error (%d)\n", ret);
return ret;
}
DEBPRINT("call set_taskfiles, drive=%s\n", drive->name);
ret = do_drive_set_taskfiles(drive, gtf_length, gtf_address);
kfree((void *)obj_loc);
if (ret < 0) {
DEBPRINT("set_taskfiles error (%d)\n", ret);
}
DEBPRINT("ret=%d\n", ret);
return ret;
}
EXPORT_SYMBOL_GPL(ide_acpi_exec_tfs);
/**
* ide_acpi_get_timing - get the channel (controller) timings
* @hwif: target IDE interface (channel)
*
* This function executes the _GTM ACPI method for the target channel.
*
*/
void ide_acpi_get_timing(ide_hwif_t *hwif)
{
acpi_status status;
struct acpi_buffer output;
union acpi_object *out_obj;
if (ide_noacpi)
return;
DEBPRINT("ENTER:\n");
if (!hwif->acpidata) {
DEBPRINT("no ACPI data for %s\n", hwif->name);
return;
}
/* Setting up output buffer for _GTM */
output.length = ACPI_ALLOCATE_BUFFER;
output.pointer = NULL; /* ACPI-CA sets this; save/free it later */
/* _GTM has no input parameters */
status = acpi_evaluate_object(hwif->acpidata->obj_handle, "_GTM",
NULL, &output);
DEBPRINT("_GTM status: %d, outptr: 0x%p, outlen: 0x%llx\n",
status, output.pointer,
(unsigned long long)output.length);
if (ACPI_FAILURE(status)) {
DEBPRINT("Run _GTM error: status = 0x%x\n", status);
return;
}
if (!output.length || !output.pointer) {
DEBPRINT("Run _GTM: length or ptr is NULL (0x%llx, 0x%p)\n",
(unsigned long long)output.length,
output.pointer);
kfree(output.pointer);
return;
}
out_obj = output.pointer;
if (out_obj->type != ACPI_TYPE_BUFFER) {
kfree(output.pointer);
DEBPRINT("Run _GTM: error: "
"expected object type of ACPI_TYPE_BUFFER, "
"got 0x%x\n", out_obj->type);
return;
}
if (!out_obj->buffer.length || !out_obj->buffer.pointer ||
out_obj->buffer.length != sizeof(struct GTM_buffer)) {
kfree(output.pointer);
printk(KERN_ERR
"%s: unexpected _GTM length (0x%x)[should be 0x%zx] or "
"addr (0x%p)\n",
__FUNCTION__, out_obj->buffer.length,
sizeof(struct GTM_buffer), out_obj->buffer.pointer);
return;
}
memcpy(&hwif->acpidata->gtm, out_obj->buffer.pointer,
sizeof(struct GTM_buffer));
DEBPRINT("_GTM info: ptr: 0x%p, len: 0x%x, exp.len: 0x%Zx\n",
out_obj->buffer.pointer, out_obj->buffer.length,
sizeof(struct GTM_buffer));
DEBPRINT("_GTM fields: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
hwif->acpidata->gtm.PIO_speed0,
hwif->acpidata->gtm.DMA_speed0,
hwif->acpidata->gtm.PIO_speed1,
hwif->acpidata->gtm.DMA_speed1,
hwif->acpidata->gtm.GTM_flags);
kfree(output.pointer);
}
EXPORT_SYMBOL_GPL(ide_acpi_get_timing);
/**
* ide_acpi_push_timing - set the channel (controller) timings
* @hwif: target IDE interface (channel)
*
* This function executes the _STM ACPI method for the target channel.
*
* _STM requires Identify Drive data, which has to passed as an argument.
* Unfortunately hd_driveid is a mangled version which we can't readily
* use; hence we'll get the information afresh.
*/
void ide_acpi_push_timing(ide_hwif_t *hwif)
{
acpi_status status;
struct acpi_object_list input;
union acpi_object in_params[3];
struct ide_acpi_drive_link *master = &hwif->acpidata->master;
struct ide_acpi_drive_link *slave = &hwif->acpidata->slave;
if (ide_noacpi)
return;
DEBPRINT("ENTER:\n");
if (!hwif->acpidata) {
DEBPRINT("no ACPI data for %s\n", hwif->name);
return;
}
/* Give the GTM buffer + drive Identify data to the channel via the
* _STM method: */
/* setup input parameters buffer for _STM */
input.count = 3;
input.pointer = in_params;
in_params[0].type = ACPI_TYPE_BUFFER;
in_params[0].buffer.length = sizeof(struct GTM_buffer);
in_params[0].buffer.pointer = (u8 *)&hwif->acpidata->gtm;
in_params[1].type = ACPI_TYPE_BUFFER;
in_params[1].buffer.length = sizeof(struct hd_driveid);
in_params[1].buffer.pointer = (u8 *)&master->idbuff;
in_params[2].type = ACPI_TYPE_BUFFER;
in_params[2].buffer.length = sizeof(struct hd_driveid);
in_params[2].buffer.pointer = (u8 *)&slave->idbuff;
/* Output buffer: _STM has no output */
status = acpi_evaluate_object(hwif->acpidata->obj_handle, "_STM",
&input, NULL);
if (ACPI_FAILURE(status)) {
DEBPRINT("Run _STM error: status = 0x%x\n", status);
}
DEBPRINT("_STM status: %d\n", status);
}
EXPORT_SYMBOL_GPL(ide_acpi_push_timing);
/**
* ide_acpi_init - initialize the ACPI link for an IDE interface
* @hwif: target IDE interface (channel)
*
* The ACPI spec is not quite clear when the drive identify buffer
* should be obtained. Calling IDENTIFY DEVICE during shutdown
* is not the best of ideas as the drive might already being put to
* sleep. And obviously we can't call it during resume.
* So we get the information during startup; but this means that
* any changes during run-time will be lost after resume.
*/
void ide_acpi_init(ide_hwif_t *hwif)
{
int unit;
int err;
struct ide_acpi_drive_link *master;
struct ide_acpi_drive_link *slave;
hwif->acpidata = kzalloc(sizeof(struct ide_acpi_hwif_link), GFP_KERNEL);
if (!hwif->acpidata)
return;
hwif->acpidata->obj_handle = ide_acpi_hwif_get_handle(hwif);
if (!hwif->acpidata->obj_handle) {
DEBPRINT("no ACPI object for %s found\n", hwif->name);
kfree(hwif->acpidata);
hwif->acpidata = NULL;
return;
}
/*
* The ACPI spec mandates that we send information
* for both drives, regardless whether they are connected
* or not.
*/
hwif->acpidata->master.drive = &hwif->drives[0];
hwif->drives[0].acpidata = &hwif->acpidata->master;
master = &hwif->acpidata->master;
hwif->acpidata->slave.drive = &hwif->drives[1];
hwif->drives[1].acpidata = &hwif->acpidata->slave;
slave = &hwif->acpidata->slave;
/*
* Send IDENTIFY for each drive
*/
if (master->drive->present) {
err = taskfile_lib_get_identify(master->drive, master->idbuff);
if (err) {
DEBPRINT("identify device %s failed (%d)\n",
master->drive->name, err);
}
}
if (slave->drive->present) {
err = taskfile_lib_get_identify(slave->drive, slave->idbuff);
if (err) {
DEBPRINT("identify device %s failed (%d)\n",
slave->drive->name, err);
}
}
if (ide_noacpionboot) {
DEBPRINT("ACPI methods disabled on boot\n");
return;
}
/*
* ACPI requires us to call _STM on startup
*/
ide_acpi_get_timing(hwif);
ide_acpi_push_timing(hwif);
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
if (drive->present) {
/* Execute ACPI startup code */
ide_acpi_exec_tfs(drive);
}
}
}
EXPORT_SYMBOL_GPL(ide_acpi_init);
...@@ -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");
此差异已折叠。
/*
* 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 @@ static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive) ...@@ -333,21 +304,12 @@ static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive)
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 @@ static int pdc202xx_config_drive_xfer_rate (ide_drive_t *drive) ...@@ -377,7 +357,12 @@ static int pdc202xx_config_drive_xfer_rate (ide_drive_t *drive)
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;
...@@ -225,7 +225,7 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio) ...@@ -225,7 +225,7 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio)
static DEFINE_SPINLOCK(tune_lock); static DEFINE_SPINLOCK(tune_lock);
int control = 0; int control = 0;
/* ISP RTC */ /* ISP RTC */
static const u8 timings[][2]= { static const u8 timings[][2]= {
{ 0, 0 }, { 0, 0 },
{ 0, 0 }, { 0, 0 },
...@@ -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,36 +65,47 @@ static void slc90e66_tune_drive (ide_drive_t *drive, u8 pio) ...@@ -65,36 +65,47 @@ 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;
/* ISP RTC */ int control = 0;
/* ISP RTC */
static const u8 timings[][2]= { static const u8 timings[][2]= {
{ 0, 0 }, { 0, 0 },
{ 0, 0 }, { 0, 0 },
{ 1, 0 }, { 1, 0 },
{ 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 (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) { if (is_slave) {
master_data = master_data | 0x4000; master_data |= 0x4000;
if (pio > 1) 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);
...@@ -201,7 +212,7 @@ static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif) ...@@ -201,7 +212,7 @@ static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif)
hwif->irq = hwif->channel ? 15 : 14; hwif->irq = hwif->channel ? 15 : 14;
hwif->speedproc = &slc90e66_tune_chipset; hwif->speedproc = &slc90e66_tune_chipset;
hwif->tuneproc = &slc90e66_tune_drive; hwif->tuneproc = &slc90e66_tune_drive;
pci_read_config_byte(hwif->pci_dev, 0x47, &reg47); pci_read_config_byte(hwif->pci_dev, 0x47, &reg47);
...@@ -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% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册