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
......
/*
* 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");
/* /*
* linux/drivers/ide/pci/hpt366.c Version 0.36 April 25, 2003 * linux/drivers/ide/pci/hpt366.c Version 1.01 Dec 23, 2006
* *
* Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org>
* Portions Copyright (C) 2001 Sun Microsystems, Inc. * Portions Copyright (C) 2001 Sun Microsystems, Inc.
...@@ -60,13 +60,10 @@ ...@@ -60,13 +60,10 @@
* channel caused the cached register value to get out of sync with the * channel caused the cached register value to get out of sync with the
* actual one, the channels weren't serialized, the turnaround shouldn't * actual one, the channels weren't serialized, the turnaround shouldn't
* be done on 66 MHz PCI bus * be done on 66 MHz PCI bus
* - avoid calibrating PLL twice as the second time results in a wrong PCI * - disable UltraATA/100 for HPT370 by default as the 33 MHz clock being used
* frequency and thus in the wrong timings for the secondary channel * does not allow for this speed anyway
* - disable UltraATA/133 for HPT372 by default (50 MHz DPLL clock do not * - avoid touching disabled channels (e.g. HPT371/N are single channel chips,
* allow for this speed anyway) * their primary channel is kind of virtual, it isn't tied to any pins)
* - add support for HPT302N and HPT371N clocking (the same as for HPT372N)
* - HPT371/N are single channel chips, so avoid touching the primary channel
* which exists only virtually (there's no pins for it)
* - fix/remove bad/unused timing tables and use one set of tables for the whole * - fix/remove bad/unused timing tables and use one set of tables for the whole
* HPT37x chip family; save space by introducing the separate transfer mode * HPT37x chip family; save space by introducing the separate transfer mode
* table in which the mode lookup is done * table in which the mode lookup is done
...@@ -76,11 +73,47 @@ ...@@ -76,11 +73,47 @@
* and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead * and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead
* - pass to init_chipset() handlers a copy of the IDE PCI device structure as * - pass to init_chipset() handlers a copy of the IDE PCI device structure as
* they tamper with its fields * they tamper with its fields
* <source@mvista.com> * - pass to the init_setup handlers a copy of the ide_pci_device_t structure
* * since they may tamper with its fields
* - prefix the driver startup messages with the real chip name
* - claim the extra 240 bytes of I/O space for all chips
* - optimize the rate masking/filtering and the drive list lookup code
* - use pci_get_slot() to get to the function 1 of HPT36x/374
* - cache offset of the channel's misc. control registers (MCRs) being used
* throughout the driver
* - only touch the relevant MCR when detecting the cable type on HPT374's
* function 1
* - rename all the register related variables consistently
* - move all the interrupt twiddling code from the speedproc handlers into
* init_hwif_hpt366(), also grouping all the DMA related code together there
* - merge two HPT37x speedproc handlers, fix the PIO timing register mask and
* separate the UltraDMA and MWDMA masks there to avoid changing PIO timings
* when setting an UltraDMA mode
* - fix hpt3xx_tune_drive() to set the PIO mode requested, not always select
* the best possible one
* - clean up DMA timeout handling for HPT370
* - switch to using the enumeration type to differ between the numerous chip
* variants, matching PCI device/revision ID with the chip type early, at the
* init_setup stage
* - extend the hpt_info structure to hold the DPLL and PCI clock frequencies,
* stop duplicating it for each channel by storing the pointer in the pci_dev
* structure: first, at the init_setup stage, point it to a static "template"
* with only the chip type and its specific base DPLL frequency, the highest
* supported DMA mode, and the chip settings table pointer filled, then, at
* the init_chipset stage, allocate per-chip instance and fill it with the
* rest of the necessary information
* - get rid of the constant thresholds in the HPT37x PCI clock detection code,
* switch to calculating PCI clock frequency based on the chip's base DPLL
* frequency
* - switch to using the DPLL clock and enable UltraATA/133 mode by default on
* anything newer than HPT370/A
* - fold PCI clock detection and DPLL setup code into init_chipset_hpt366(),
* also fixing the interchanged 25/40 MHz PCI clock cases for HPT36x chips;
* unify HPT36x/37x timing setup code and the speedproc handlers by joining
* the register setting lists into the table indexed by the clock selected
* Sergei Shtylyov, <sshtylyov@ru.mvista.com> or <source@mvista.com>
*/ */
#include <linux/types.h> #include <linux/types.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -332,93 +365,159 @@ static u32 sixty_six_base_hpt37x[] = { ...@@ -332,93 +365,159 @@ static u32 sixty_six_base_hpt37x[] = {
}; };
#define HPT366_DEBUG_DRIVE_INFO 0 #define HPT366_DEBUG_DRIVE_INFO 0
#define HPT374_ALLOW_ATA133_6 0 #define HPT374_ALLOW_ATA133_6 1
#define HPT371_ALLOW_ATA133_6 0 #define HPT371_ALLOW_ATA133_6 1
#define HPT302_ALLOW_ATA133_6 0 #define HPT302_ALLOW_ATA133_6 1
#define HPT372_ALLOW_ATA133_6 0 #define HPT372_ALLOW_ATA133_6 1
#define HPT370_ALLOW_ATA100_5 1 #define HPT370_ALLOW_ATA100_5 0
#define HPT366_ALLOW_ATA66_4 1 #define HPT366_ALLOW_ATA66_4 1
#define HPT366_ALLOW_ATA66_3 1 #define HPT366_ALLOW_ATA66_3 1
#define HPT366_MAX_DEVS 8 #define HPT366_MAX_DEVS 8
#define F_LOW_PCI_33 0x23 /* Supported ATA clock frequencies */
#define F_LOW_PCI_40 0x29 enum ata_clock {
#define F_LOW_PCI_50 0x2d ATA_CLOCK_25MHZ,
#define F_LOW_PCI_66 0x42 ATA_CLOCK_33MHZ,
ATA_CLOCK_40MHZ,
ATA_CLOCK_50MHZ,
ATA_CLOCK_66MHZ,
NUM_ATA_CLOCKS
};
/* /*
* Hold all the highpoint quirks and revision information in one * Hold all the HighPoint chip information in one place.
* place.
*/ */
struct hpt_info struct hpt_info {
{ u8 chip_type; /* Chip type */
u8 max_mode; /* Speeds allowed */ u8 max_mode; /* Speeds allowed */
int revision; /* Chipset revision */ u8 dpll_clk; /* DPLL clock in MHz */
int flags; /* Chipset properties */ u8 pci_clk; /* PCI clock in MHz */
#define PLL_MODE 1 u32 **settings; /* Chipset settings table */
#define IS_3xxN 2
#define PCI_66MHZ 4
/* Speed table */
u32 *speed;
}; };
/* /* Supported HighPoint chips */
* This wants fixing so that we do everything not by classrev enum {
* (which breaks on the newest chips) but by creating an HPT36x,
* enumeration of chip variants and using that HPT370,
*/ HPT370A,
HPT374,
HPT372,
HPT372A,
HPT302,
HPT371,
HPT372N,
HPT302N,
HPT371N
};
static u32 *hpt36x_settings[NUM_ATA_CLOCKS] = {
twenty_five_base_hpt36x,
thirty_three_base_hpt36x,
forty_base_hpt36x,
NULL,
NULL
};
static u32 *hpt37x_settings[NUM_ATA_CLOCKS] = {
NULL,
thirty_three_base_hpt37x,
NULL,
fifty_base_hpt37x,
sixty_six_base_hpt37x
};
static struct hpt_info hpt36x __devinitdata = {
.chip_type = HPT36x,
.max_mode = (HPT366_ALLOW_ATA66_4 || HPT366_ALLOW_ATA66_3) ? 2 : 1,
.dpll_clk = 0, /* no DPLL */
.settings = hpt36x_settings
};
static struct hpt_info hpt370 __devinitdata = {
.chip_type = HPT370,
.max_mode = HPT370_ALLOW_ATA100_5 ? 3 : 2,
.dpll_clk = 48,
.settings = hpt37x_settings
};
static struct hpt_info hpt370a __devinitdata = {
.chip_type = HPT370A,
.max_mode = HPT370_ALLOW_ATA100_5 ? 3 : 2,
.dpll_clk = 48,
.settings = hpt37x_settings
};
static struct hpt_info hpt374 __devinitdata = {
.chip_type = HPT374,
.max_mode = HPT374_ALLOW_ATA133_6 ? 4 : 3,
.dpll_clk = 48,
.settings = hpt37x_settings
};
static struct hpt_info hpt372 __devinitdata = {
.chip_type = HPT372,
.max_mode = HPT372_ALLOW_ATA133_6 ? 4 : 3,
.dpll_clk = 55,
.settings = hpt37x_settings
};
static struct hpt_info hpt372a __devinitdata = {
.chip_type = HPT372A,
.max_mode = HPT372_ALLOW_ATA133_6 ? 4 : 3,
.dpll_clk = 66,
.settings = hpt37x_settings
};
static struct hpt_info hpt302 __devinitdata = {
.chip_type = HPT302,
.max_mode = HPT302_ALLOW_ATA133_6 ? 4 : 3,
.dpll_clk = 66,
.settings = hpt37x_settings
};
static struct hpt_info hpt371 __devinitdata = {
.chip_type = HPT371,
.max_mode = HPT371_ALLOW_ATA133_6 ? 4 : 3,
.dpll_clk = 66,
.settings = hpt37x_settings
};
static struct hpt_info hpt372n __devinitdata = {
.chip_type = HPT372N,
.max_mode = HPT372_ALLOW_ATA133_6 ? 4 : 3,
.dpll_clk = 77,
.settings = hpt37x_settings
};
static struct hpt_info hpt302n __devinitdata = {
.chip_type = HPT302N,
.max_mode = HPT302_ALLOW_ATA133_6 ? 4 : 3,
.dpll_clk = 77,
};
static __devinit u32 hpt_revision (struct pci_dev *dev) static struct hpt_info hpt371n __devinitdata = {
.chip_type = HPT371N,
.max_mode = HPT371_ALLOW_ATA133_6 ? 4 : 3,
.dpll_clk = 77,
.settings = hpt37x_settings
};
static int check_in_drive_list(ide_drive_t *drive, const char **list)
{ {
u32 class_rev; struct hd_driveid *id = drive->id;
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
class_rev &= 0xff;
switch(dev->device) {
/* Remap new 372N onto 372 */
case PCI_DEVICE_ID_TTI_HPT372N:
class_rev = PCI_DEVICE_ID_TTI_HPT372; break;
case PCI_DEVICE_ID_TTI_HPT374:
class_rev = PCI_DEVICE_ID_TTI_HPT374; break;
case PCI_DEVICE_ID_TTI_HPT371:
class_rev = PCI_DEVICE_ID_TTI_HPT371; break;
case PCI_DEVICE_ID_TTI_HPT302:
class_rev = PCI_DEVICE_ID_TTI_HPT302; break;
case PCI_DEVICE_ID_TTI_HPT372:
class_rev = PCI_DEVICE_ID_TTI_HPT372; break;
default:
break;
}
return class_rev;
}
static int check_in_drive_lists(ide_drive_t *drive, const char **list); while (*list)
if (!strcmp(*list++,id->model))
return 1;
return 0;
}
static u8 hpt3xx_ratemask (ide_drive_t *drive) static u8 hpt3xx_ratemask(ide_drive_t *drive)
{ {
ide_hwif_t *hwif = drive->hwif; struct hpt_info *info = pci_get_drvdata(HWIF(drive)->pci_dev);
struct hpt_info *info = ide_get_hwifdata(hwif); u8 mode = info->max_mode;
u8 mode = 0;
/* FIXME: TODO - move this to set info->mode once at boot */
if (info->revision >= 8) { /* HPT374 */
mode = (HPT374_ALLOW_ATA133_6) ? 4 : 3;
} else if (info->revision >= 7) { /* HPT371 */
mode = (HPT371_ALLOW_ATA133_6) ? 4 : 3;
} else if (info->revision >= 6) { /* HPT302 */
mode = (HPT302_ALLOW_ATA133_6) ? 4 : 3;
} else if (info->revision >= 5) { /* HPT372 */
mode = (HPT372_ALLOW_ATA133_6) ? 4 : 3;
} else if (info->revision >= 4) { /* HPT370A */
mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2;
} else if (info->revision >= 3) { /* HPT370 */
mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2;
mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : mode;
} else { /* HPT366 and HPT368 */
mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : 2;
}
if (!eighty_ninty_three(drive) && mode) if (!eighty_ninty_three(drive) && mode)
mode = min(mode, (u8)1); mode = min(mode, (u8)1);
return mode; return mode;
...@@ -429,75 +528,61 @@ static u8 hpt3xx_ratemask (ide_drive_t *drive) ...@@ -429,75 +528,61 @@ static u8 hpt3xx_ratemask (ide_drive_t *drive)
* either PIO or UDMA modes 0,4,5 * either PIO or UDMA modes 0,4,5
*/ */
static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed) static u8 hpt3xx_ratefilter(ide_drive_t *drive, u8 speed)
{ {
ide_hwif_t *hwif = drive->hwif; struct hpt_info *info = pci_get_drvdata(HWIF(drive)->pci_dev);
struct hpt_info *info = ide_get_hwifdata(hwif); u8 chip_type = info->chip_type;
u8 mode = hpt3xx_ratemask(drive); u8 mode = hpt3xx_ratemask(drive);
if (drive->media != ide_disk) if (drive->media != ide_disk)
return min(speed, (u8)XFER_PIO_4); return min(speed, (u8)XFER_PIO_4);
switch(mode) { switch (mode) {
case 0x04: case 0x04:
speed = min(speed, (u8)XFER_UDMA_6); speed = min_t(u8, speed, XFER_UDMA_6);
break; break;
case 0x03: case 0x03:
speed = min(speed, (u8)XFER_UDMA_5); speed = min_t(u8, speed, XFER_UDMA_5);
if (info->revision >= 5) if (chip_type >= HPT374)
break; break;
if (check_in_drive_lists(drive, bad_ata100_5)) if (!check_in_drive_list(drive, bad_ata100_5))
speed = min(speed, (u8)XFER_UDMA_4); goto check_bad_ata33;
break; /* fall thru */
case 0x02: case 0x02:
speed = min(speed, (u8)XFER_UDMA_4); speed = min_t(u8, speed, XFER_UDMA_4);
/*
* CHECK ME, Does this need to be set to 5 ?? /*
*/ * CHECK ME, Does this need to be changed to HPT374 ??
if (info->revision >= 3) */
break; if (chip_type >= HPT370)
if ((check_in_drive_lists(drive, bad_ata66_4)) || goto check_bad_ata33;
(!(HPT366_ALLOW_ATA66_4))) if (HPT366_ALLOW_ATA66_4 &&
speed = min(speed, (u8)XFER_UDMA_3); !check_in_drive_list(drive, bad_ata66_4))
if ((check_in_drive_lists(drive, bad_ata66_3)) || goto check_bad_ata33;
(!(HPT366_ALLOW_ATA66_3)))
speed = min(speed, (u8)XFER_UDMA_2); speed = min_t(u8, speed, XFER_UDMA_3);
break; if (HPT366_ALLOW_ATA66_3 &&
!check_in_drive_list(drive, bad_ata66_3))
goto check_bad_ata33;
/* fall thru */
case 0x01: case 0x01:
speed = min(speed, (u8)XFER_UDMA_2); speed = min_t(u8, speed, XFER_UDMA_2);
/*
* CHECK ME, Does this need to be set to 5 ?? check_bad_ata33:
*/ if (chip_type >= HPT370A)
if (info->revision >= 3)
break; break;
if (check_in_drive_lists(drive, bad_ata33)) if (!check_in_drive_list(drive, bad_ata33))
speed = min(speed, (u8)XFER_MW_DMA_2); break;
break; /* fall thru */
case 0x00: case 0x00:
default: default:
speed = min(speed, (u8)XFER_MW_DMA_2); speed = min_t(u8, speed, XFER_MW_DMA_2);
break; break;
} }
return speed; return speed;
} }
static int check_in_drive_lists (ide_drive_t *drive, const char **list) static u32 get_speed_setting(u8 speed, struct hpt_info *info)
{
struct hd_driveid *id = drive->id;
if (quirk_drives == list) {
while (*list)
if (strstr(id->model, *list++))
return 1;
} else {
while (*list)
if (!strcmp(*list++,id->model))
return 1;
}
return 0;
}
static u32 pci_bus_clock_list(u8 speed, u32 *chipset_table)
{ {
int i; int i;
...@@ -510,228 +595,161 @@ static u32 pci_bus_clock_list(u8 speed, u32 *chipset_table) ...@@ -510,228 +595,161 @@ static u32 pci_bus_clock_list(u8 speed, u32 *chipset_table)
for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++) for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++)
if (xfer_speeds[i] == speed) if (xfer_speeds[i] == speed)
break; break;
return chipset_table[i]; /*
* NOTE: info->settings only points to the pointer
* to the list of the actual register values
*/
return (*info->settings)[i];
} }
static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed) static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed)
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev; struct pci_dev *dev = hwif->pci_dev;
struct hpt_info *info = ide_get_hwifdata(hwif); struct hpt_info *info = pci_get_drvdata(dev);
u8 speed = hpt3xx_ratefilter(drive, xferspeed); u8 speed = hpt3xx_ratefilter(drive, xferspeed);
u8 regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; u8 itr_addr = drive->dn ? 0x44 : 0x40;
u8 regfast = (hwif->channel) ? 0x55 : 0x51; u32 itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 :
u8 drive_fast = 0; (speed < XFER_UDMA_0 ? 0xc0070000 : 0xc03800ff);
u32 reg1 = 0, reg2 = 0; u32 new_itr = get_speed_setting(speed, info);
u32 old_itr = 0;
/*
* Disable the "fast interrupt" prediction.
*/
pci_read_config_byte(dev, regfast, &drive_fast);
if (drive_fast & 0x80)
pci_write_config_byte(dev, regfast, drive_fast & ~0x80);
reg2 = pci_bus_clock_list(speed, info->speed);
/* /*
* Disable on-chip PIO FIFO/buffer * Disable on-chip PIO FIFO/buffer (and PIO MST mode as well)
* (to avoid problems handling I/O errors later) * to avoid problems handling I/O errors later
*/ */
pci_read_config_dword(dev, regtime, &reg1); pci_read_config_dword(dev, itr_addr, &old_itr);
if (speed >= XFER_MW_DMA_0) { new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask);
reg2 = (reg2 & ~0xc0000000) | (reg1 & 0xc0000000); new_itr &= ~0xc0000000;
} else {
reg2 = (reg2 & ~0x30070000) | (reg1 & 0x30070000);
}
reg2 &= ~0x80000000;
pci_write_config_dword(dev, regtime, reg2); pci_write_config_dword(dev, itr_addr, new_itr);
return ide_config_drive_speed(drive, speed); return ide_config_drive_speed(drive, speed);
} }
static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed) static int hpt37x_tune_chipset(ide_drive_t *drive, u8 xferspeed)
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev; struct pci_dev *dev = hwif->pci_dev;
struct hpt_info *info = ide_get_hwifdata(hwif); struct hpt_info *info = pci_get_drvdata(dev);
u8 speed = hpt3xx_ratefilter(drive, xferspeed); u8 speed = hpt3xx_ratefilter(drive, xferspeed);
u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51; u8 itr_addr = 0x40 + (drive->dn * 4);
u8 drive_pci = 0x40 + (drive->dn * 4); u32 itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 :
u8 new_fast = 0, drive_fast = 0; (speed < XFER_UDMA_0 ? 0xc03c0000 : 0xc1c001ff);
u32 list_conf = 0, drive_conf = 0; u32 new_itr = get_speed_setting(speed, info);
u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; u32 old_itr = 0;
/* pci_read_config_dword(dev, itr_addr, &old_itr);
* Disable the "fast interrupt" prediction. new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask);
* don't holdoff on interrupts. (== 0x01 despite what the docs say)
*/
pci_read_config_byte(dev, regfast, &drive_fast);
new_fast = drive_fast;
if (new_fast & 0x02)
new_fast &= ~0x02;
#ifdef HPT_DELAY_INTERRUPT
if (new_fast & 0x01)
new_fast &= ~0x01;
#else
if ((new_fast & 0x01) == 0)
new_fast |= 0x01;
#endif
if (new_fast != drive_fast)
pci_write_config_byte(dev, regfast, new_fast);
list_conf = pci_bus_clock_list(speed, info->speed);
pci_read_config_dword(dev, drive_pci, &drive_conf);
list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask);
if (speed < XFER_MW_DMA_0) if (speed < XFER_MW_DMA_0)
list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ new_itr &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */
pci_write_config_dword(dev, drive_pci, list_conf); pci_write_config_dword(dev, itr_addr, new_itr);
return ide_config_drive_speed(drive, speed); return ide_config_drive_speed(drive, speed);
} }
static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed) static int hpt3xx_tune_chipset(ide_drive_t *drive, u8 speed)
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev; struct hpt_info *info = pci_get_drvdata(hwif->pci_dev);
struct hpt_info *info = ide_get_hwifdata(hwif);
u8 speed = hpt3xx_ratefilter(drive, xferspeed);
u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51;
u8 drive_fast = 0, drive_pci = 0x40 + (drive->dn * 4);
u32 list_conf = 0, drive_conf = 0;
u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000;
/*
* Disable the "fast interrupt" prediction.
* don't holdoff on interrupts. (== 0x01 despite what the docs say)
*/
pci_read_config_byte(dev, regfast, &drive_fast);
drive_fast &= ~0x07;
pci_write_config_byte(dev, regfast, drive_fast);
list_conf = pci_bus_clock_list(speed, info->speed);
pci_read_config_dword(dev, drive_pci, &drive_conf);
list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask);
if (speed < XFER_MW_DMA_0)
list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */
pci_write_config_dword(dev, drive_pci, list_conf);
return ide_config_drive_speed(drive, speed);
}
static int hpt3xx_tune_chipset (ide_drive_t *drive, u8 speed) if (info->chip_type >= HPT370)
{ return hpt37x_tune_chipset(drive, speed);
ide_hwif_t *hwif = drive->hwif;
struct hpt_info *info = ide_get_hwifdata(hwif);
if (info->revision >= 8)
return hpt372_tune_chipset(drive, speed); /* not a typo */
else if (info->revision >= 5)
return hpt372_tune_chipset(drive, speed);
else if (info->revision >= 3)
return hpt370_tune_chipset(drive, speed);
else /* hpt368: hpt_minimum_revision(dev, 2) */ else /* hpt368: hpt_minimum_revision(dev, 2) */
return hpt36x_tune_chipset(drive, speed); return hpt36x_tune_chipset(drive, speed);
} }
static void hpt3xx_tune_drive (ide_drive_t *drive, u8 pio) static void hpt3xx_tune_drive(ide_drive_t *drive, u8 pio)
{ {
pio = ide_get_best_pio_mode(drive, 255, pio, NULL); pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
(void) hpt3xx_tune_chipset(drive, (XFER_PIO_0 + pio)); (void) hpt3xx_tune_chipset (drive, XFER_PIO_0 + pio);
} }
/* /*
* This allows the configuration of ide_pci chipset registers * This allows the configuration of ide_pci chipset registers
* for cards that learn about the drive's UDMA, DMA, PIO capabilities * for cards that learn about the drive's UDMA, DMA, PIO capabilities
* after the drive is reported by the OS. Initially for designed for * after the drive is reported by the OS. Initially designed for
* HPT366 UDMA chipset by HighPoint|Triones Technologies, Inc. * HPT366 UDMA chipset by HighPoint|Triones Technologies, Inc.
* *
* check_in_drive_lists(drive, bad_ata66_4)
* check_in_drive_lists(drive, bad_ata66_3)
* check_in_drive_lists(drive, bad_ata33)
*
*/ */
static int config_chipset_for_dma (ide_drive_t *drive) static int config_chipset_for_dma(ide_drive_t *drive)
{ {
u8 speed = ide_dma_speed(drive, hpt3xx_ratemask(drive)); u8 speed = ide_dma_speed(drive, hpt3xx_ratemask(drive));
ide_hwif_t *hwif = drive->hwif;
struct hpt_info *info = ide_get_hwifdata(hwif);
if (!speed) if (!speed)
return 0; return 0;
/* If we don't have any timings we can't do a lot */
if (info->speed == NULL)
return 0;
(void) hpt3xx_tune_chipset(drive, speed); (void) hpt3xx_tune_chipset(drive, speed);
return ide_dma_enable(drive); return ide_dma_enable(drive);
} }
static int hpt3xx_quirkproc (ide_drive_t *drive) static int hpt3xx_quirkproc(ide_drive_t *drive)
{ {
return ((int) check_in_drive_lists(drive, quirk_drives)); struct hd_driveid *id = drive->id;
const char **list = quirk_drives;
while (*list)
if (strstr(id->model, *list++))
return 1;
return 0;
} }
static void hpt3xx_intrproc (ide_drive_t *drive) static void hpt3xx_intrproc(ide_drive_t *drive)
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = HWIF(drive);
if (drive->quirk_list) if (drive->quirk_list)
return; return;
/* drives in the quirk_list may not like intr setups/cleanups */ /* drives in the quirk_list may not like intr setups/cleanups */
hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG); hwif->OUTB(drive->ctl | 2, IDE_CONTROL_REG);
} }
static void hpt3xx_maskproc (ide_drive_t *drive, int mask) static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = HWIF(drive);
struct hpt_info *info = ide_get_hwifdata(hwif); struct pci_dev *dev = hwif->pci_dev;
struct pci_dev *dev = hwif->pci_dev; struct hpt_info *info = pci_get_drvdata(dev);
if (drive->quirk_list) { if (drive->quirk_list) {
if (info->revision >= 3) { if (info->chip_type >= HPT370) {
u8 reg5a = 0; u8 scr1 = 0;
pci_read_config_byte(dev, 0x5a, &reg5a);
if (((reg5a & 0x10) >> 4) != mask) pci_read_config_byte(dev, 0x5a, &scr1);
pci_write_config_byte(dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10)); if (((scr1 & 0x10) >> 4) != mask) {
if (mask)
scr1 |= 0x10;
else
scr1 &= ~0x10;
pci_write_config_byte(dev, 0x5a, scr1);
}
} else { } else {
if (mask) { if (mask)
disable_irq(hwif->irq); disable_irq(hwif->irq);
} else { else
enable_irq(hwif->irq); enable_irq (hwif->irq);
}
} }
} else { } else
if (IDE_CONTROL_REG) hwif->OUTB(mask ? (drive->ctl | 2) : (drive->ctl & ~2),
hwif->OUTB(mask ? (drive->ctl | 2) : IDE_CONTROL_REG);
(drive->ctl & ~2),
IDE_CONTROL_REG);
}
} }
static int hpt366_config_drive_xfer_rate (ide_drive_t *drive) static int hpt366_config_drive_xfer_rate(ide_drive_t *drive)
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = HWIF(drive);
struct hd_driveid *id = drive->id; struct hd_driveid *id = drive->id;
drive->init_speed = 0; drive->init_speed = 0;
if ((id->capability & 1) && drive->autodma) { if ((id->capability & 1) && drive->autodma) {
if (ide_use_dma(drive) && config_chipset_for_dma(drive))
if (ide_use_dma(drive)) { return hwif->ide_dma_on(drive);
if (config_chipset_for_dma(drive))
return hwif->ide_dma_on(drive);
}
goto fast_ata_pio; goto fast_ata_pio;
} else if ((id->capability & 8) || (id->field_valid & 2)) { } else if ((id->capability & 8) || (id->field_valid & 2)) {
fast_ata_pio: fast_ata_pio:
hpt3xx_tune_drive(drive, 5); hpt3xx_tune_drive(drive, 255);
return hwif->ide_dma_off_quietly(drive); return hwif->ide_dma_off_quietly(drive);
} }
/* IORDY not supported */ /* IORDY not supported */
...@@ -739,31 +757,48 @@ static int hpt366_config_drive_xfer_rate (ide_drive_t *drive) ...@@ -739,31 +757,48 @@ static int hpt366_config_drive_xfer_rate (ide_drive_t *drive)
} }
/* /*
* This is specific to the HPT366 UDMA bios chipset * This is specific to the HPT366 UDMA chipset
* by HighPoint|Triones Technologies, Inc. * by HighPoint|Triones Technologies, Inc.
*/ */
static int hpt366_ide_dma_lostirq (ide_drive_t *drive) static int hpt366_ide_dma_lostirq(ide_drive_t *drive)
{ {
struct pci_dev *dev = HWIF(drive)->pci_dev; struct pci_dev *dev = HWIF(drive)->pci_dev;
u8 reg50h = 0, reg52h = 0, reg5ah = 0; u8 mcr1 = 0, mcr3 = 0, scr1 = 0;
pci_read_config_byte(dev, 0x50, &reg50h); pci_read_config_byte(dev, 0x50, &mcr1);
pci_read_config_byte(dev, 0x52, &reg52h); pci_read_config_byte(dev, 0x52, &mcr3);
pci_read_config_byte(dev, 0x5a, &reg5ah); pci_read_config_byte(dev, 0x5a, &scr1);
printk("%s: (%s) reg50h=0x%02x, reg52h=0x%02x, reg5ah=0x%02x\n", printk("%s: (%s) mcr1=0x%02x, mcr3=0x%02x, scr1=0x%02x\n",
drive->name, __FUNCTION__, reg50h, reg52h, reg5ah); drive->name, __FUNCTION__, mcr1, mcr3, scr1);
if (reg5ah & 0x10) if (scr1 & 0x10)
pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); pci_write_config_byte(dev, 0x5a, scr1 & ~0x10);
return __ide_dma_lostirq(drive); return __ide_dma_lostirq(drive);
} }
static void hpt370_clear_engine (ide_drive_t *drive) static void hpt370_clear_engine(ide_drive_t *drive)
{ {
u8 regstate = HWIF(drive)->channel ? 0x54 : 0x50; ide_hwif_t *hwif = HWIF(drive);
pci_write_config_byte(HWIF(drive)->pci_dev, regstate, 0x37);
pci_write_config_byte(hwif->pci_dev, hwif->select_data, 0x37);
udelay(10); udelay(10);
} }
static void hpt370_irq_timeout(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
u16 bfifo = 0;
u8 dma_cmd;
pci_read_config_word(hwif->pci_dev, hwif->select_data + 2, &bfifo);
printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo & 0x1ff);
/* get DMA command mode */
dma_cmd = hwif->INB(hwif->dma_command);
/* stop DMA */
hwif->OUTB(dma_cmd & ~0x1, hwif->dma_command);
hpt370_clear_engine(drive);
}
static void hpt370_ide_dma_start(ide_drive_t *drive) static void hpt370_ide_dma_start(ide_drive_t *drive)
{ {
#ifdef HPT_RESET_STATE_ENGINE #ifdef HPT_RESET_STATE_ENGINE
...@@ -772,64 +807,35 @@ static void hpt370_ide_dma_start(ide_drive_t *drive) ...@@ -772,64 +807,35 @@ static void hpt370_ide_dma_start(ide_drive_t *drive)
ide_dma_start(drive); ide_dma_start(drive);
} }
static int hpt370_ide_dma_end (ide_drive_t *drive) static int hpt370_ide_dma_end(ide_drive_t *drive)
{ {
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
u8 dma_stat = hwif->INB(hwif->dma_status); u8 dma_stat = hwif->INB(hwif->dma_status);
if (dma_stat & 0x01) { if (dma_stat & 0x01) {
/* wait a little */ /* wait a little */
udelay(20); udelay(20);
dma_stat = hwif->INB(hwif->dma_status); dma_stat = hwif->INB(hwif->dma_status);
if (dma_stat & 0x01)
hpt370_irq_timeout(drive);
} }
if ((dma_stat & 0x01) != 0)
/* fallthrough */
(void) HWIF(drive)->ide_dma_timeout(drive);
return __ide_dma_end(drive); return __ide_dma_end(drive);
} }
static void hpt370_lostirq_timeout (ide_drive_t *drive) static int hpt370_ide_dma_timeout(ide_drive_t *drive)
{ {
ide_hwif_t *hwif = HWIF(drive); hpt370_irq_timeout(drive);
u8 bfifo = 0, reginfo = hwif->channel ? 0x56 : 0x52;
u8 dma_stat = 0, dma_cmd = 0;
pci_read_config_byte(HWIF(drive)->pci_dev, reginfo, &bfifo);
printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo);
hpt370_clear_engine(drive);
/* get dma command mode */
dma_cmd = hwif->INB(hwif->dma_command);
/* stop dma */
hwif->OUTB(dma_cmd & ~0x1, hwif->dma_command);
dma_stat = hwif->INB(hwif->dma_status);
/* clear errors */
hwif->OUTB(dma_stat | 0x6, hwif->dma_status);
}
static int hpt370_ide_dma_timeout (ide_drive_t *drive)
{
hpt370_lostirq_timeout(drive);
hpt370_clear_engine(drive);
return __ide_dma_timeout(drive); return __ide_dma_timeout(drive);
} }
static int hpt370_ide_dma_lostirq (ide_drive_t *drive)
{
hpt370_lostirq_timeout(drive);
hpt370_clear_engine(drive);
return __ide_dma_lostirq(drive);
}
/* returns 1 if DMA IRQ issued, 0 otherwise */ /* returns 1 if DMA IRQ issued, 0 otherwise */
static int hpt374_ide_dma_test_irq(ide_drive_t *drive) static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
{ {
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
u16 bfifo = 0; u16 bfifo = 0;
u8 reginfo = hwif->channel ? 0x56 : 0x52; u8 dma_stat;
u8 dma_stat;
pci_read_config_word(hwif->pci_dev, reginfo, &bfifo); pci_read_config_word(hwif->pci_dev, hwif->select_data + 2, &bfifo);
if (bfifo & 0x1FF) { if (bfifo & 0x1FF) {
// printk("%s: %d bytes in FIFO\n", drive->name, bfifo); // printk("%s: %d bytes in FIFO\n", drive->name, bfifo);
return 0; return 0;
...@@ -837,7 +843,7 @@ static int hpt374_ide_dma_test_irq(ide_drive_t *drive) ...@@ -837,7 +843,7 @@ static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
dma_stat = hwif->INB(hwif->dma_status); dma_stat = hwif->INB(hwif->dma_status);
/* return 1 if INTR asserted */ /* return 1 if INTR asserted */
if ((dma_stat & 4) == 4) if (dma_stat & 4)
return 1; return 1;
if (!drive->waiting_for_dma) if (!drive->waiting_for_dma)
...@@ -846,17 +852,17 @@ static int hpt374_ide_dma_test_irq(ide_drive_t *drive) ...@@ -846,17 +852,17 @@ static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
return 0; return 0;
} }
static int hpt374_ide_dma_end (ide_drive_t *drive) static int hpt374_ide_dma_end(ide_drive_t *drive)
{ {
struct pci_dev *dev = HWIF(drive)->pci_dev;
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
u8 msc_stat = 0, mscreg = hwif->channel ? 0x54 : 0x50; struct pci_dev *dev = hwif->pci_dev;
u8 bwsr_stat = 0, bwsr_mask = hwif->channel ? 0x02 : 0x01; u8 mcr = 0, mcr_addr = hwif->select_data;
u8 bwsr = 0, mask = hwif->channel ? 0x02 : 0x01;
pci_read_config_byte(dev, 0x6a, &bwsr_stat);
pci_read_config_byte(dev, mscreg, &msc_stat); pci_read_config_byte(dev, 0x6a, &bwsr);
if ((bwsr_stat & bwsr_mask) == bwsr_mask) pci_read_config_byte(dev, mcr_addr, &mcr);
pci_write_config_byte(dev, mscreg, msc_stat|0x30); if (bwsr & mask)
pci_write_config_byte(dev, mcr_addr, mcr | 0x30);
return __ide_dma_end(drive); return __ide_dma_end(drive);
} }
...@@ -866,40 +872,37 @@ static int hpt374_ide_dma_end (ide_drive_t *drive) ...@@ -866,40 +872,37 @@ static int hpt374_ide_dma_end (ide_drive_t *drive)
* @mode: clocking mode (0x21 for write, 0x23 otherwise) * @mode: clocking mode (0x21 for write, 0x23 otherwise)
* *
* Switch the DPLL clock on the HPT3xxN devices. This is a right mess. * Switch the DPLL clock on the HPT3xxN devices. This is a right mess.
* NOTE: avoid touching the disabled primary channel on HPT371N -- it
* doesn't physically exist anyway...
*/ */
static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode) static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode)
{ {
u8 mcr1, scr2 = hwif->INB(hwif->dma_master + 0x7b); u8 scr2 = hwif->INB(hwif->dma_master + 0x7b);
if ((scr2 & 0x7f) == mode) if ((scr2 & 0x7f) == mode)
return; return;
/* MISC. control register 1 has the channel enable bit... */
mcr1 = hwif->INB(hwif->dma_master + 0x70);
/* Tristate the bus */ /* Tristate the bus */
if (mcr1 & 0x04) hwif->OUTB(0x80, hwif->dma_master + 0x73);
hwif->OUTB(0x80, hwif->dma_master + 0x73);
hwif->OUTB(0x80, hwif->dma_master + 0x77); hwif->OUTB(0x80, hwif->dma_master + 0x77);
/* Switch clock and reset channels */ /* Switch clock and reset channels */
hwif->OUTB(mode, hwif->dma_master + 0x7b); hwif->OUTB(mode, hwif->dma_master + 0x7b);
hwif->OUTB(0xc0, hwif->dma_master + 0x79); hwif->OUTB(0xc0, hwif->dma_master + 0x79);
/* Reset state machines */ /*
if (mcr1 & 0x04) * Reset the state machines.
hwif->OUTB(0x37, hwif->dma_master + 0x70); * NOTE: avoid accidentally enabling the disabled channels.
hwif->OUTB(0x37, hwif->dma_master + 0x74); */
hwif->OUTB(hwif->INB(hwif->dma_master + 0x70) | 0x32,
hwif->dma_master + 0x70);
hwif->OUTB(hwif->INB(hwif->dma_master + 0x74) | 0x32,
hwif->dma_master + 0x74);
/* Complete reset */ /* Complete reset */
hwif->OUTB(0x00, hwif->dma_master + 0x79); hwif->OUTB(0x00, hwif->dma_master + 0x79);
/* Reconnect channels to bus */ /* Reconnect channels to bus */
if (mcr1 & 0x04) hwif->OUTB(0x00, hwif->dma_master + 0x73);
hwif->OUTB(0x00, hwif->dma_master + 0x73);
hwif->OUTB(0x00, hwif->dma_master + 0x77); hwif->OUTB(0x00, hwif->dma_master + 0x77);
} }
...@@ -914,14 +917,12 @@ static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode) ...@@ -914,14 +917,12 @@ static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode)
static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq) static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq)
{ {
ide_hwif_t *hwif = HWIF(drive); hpt3xxn_set_clock(HWIF(drive), rq_data_dir(rq) ? 0x23 : 0x21);
u8 wantclock = rq_data_dir(rq) ? 0x23 : 0x21;
hpt3xxn_set_clock(hwif, wantclock);
} }
/* /*
* Set/get power state for a drive. * Set/get power state for a drive.
* NOTE: affects both drives on each channel.
* *
* When we turn the power back on, we need to re-initialize things. * When we turn the power back on, we need to re-initialize things.
*/ */
...@@ -929,26 +930,18 @@ static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq) ...@@ -929,26 +930,18 @@ static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq)
static int hpt3xx_busproc(ide_drive_t *drive, int state) static int hpt3xx_busproc(ide_drive_t *drive, int state)
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev; struct pci_dev *dev = hwif->pci_dev;
u8 tristate, resetmask, bus_reg = 0; u8 mcr_addr = hwif->select_data + 2;
u16 tri_reg = 0; u8 resetmask = hwif->channel ? 0x80 : 0x40;
u8 bsr2 = 0;
u16 mcr = 0;
hwif->bus_state = state; hwif->bus_state = state;
if (hwif->channel) {
/* secondary channel */
tristate = 0x56;
resetmask = 0x80;
} else {
/* primary channel */
tristate = 0x52;
resetmask = 0x40;
}
/* Grab the status. */ /* Grab the status. */
pci_read_config_word(dev, tristate, &tri_reg); pci_read_config_word(dev, mcr_addr, &mcr);
pci_read_config_byte(dev, 0x59, &bus_reg); pci_read_config_byte(dev, 0x59, &bsr2);
/* /*
* Set the state. We don't set it if we don't need to do so. * Set the state. We don't set it if we don't need to do so.
...@@ -956,22 +949,22 @@ static int hpt3xx_busproc(ide_drive_t *drive, int state) ...@@ -956,22 +949,22 @@ static int hpt3xx_busproc(ide_drive_t *drive, int state)
*/ */
switch (state) { switch (state) {
case BUSSTATE_ON: case BUSSTATE_ON:
if (!(bus_reg & resetmask)) if (!(bsr2 & resetmask))
return 0; return 0;
hwif->drives[0].failures = hwif->drives[1].failures = 0; hwif->drives[0].failures = hwif->drives[1].failures = 0;
pci_write_config_byte(dev, 0x59, bus_reg & ~resetmask); pci_write_config_byte(dev, 0x59, bsr2 & ~resetmask);
pci_write_config_word(dev, tristate, tri_reg & ~TRISTATE_BIT); pci_write_config_word(dev, mcr_addr, mcr & ~TRISTATE_BIT);
return 0; return 0;
case BUSSTATE_OFF: case BUSSTATE_OFF:
if ((bus_reg & resetmask) && !(tri_reg & TRISTATE_BIT)) if ((bsr2 & resetmask) && !(mcr & TRISTATE_BIT))
return 0; return 0;
tri_reg &= ~TRISTATE_BIT; mcr &= ~TRISTATE_BIT;
break; break;
case BUSSTATE_TRISTATE: case BUSSTATE_TRISTATE:
if ((bus_reg & resetmask) && (tri_reg & TRISTATE_BIT)) if ((bsr2 & resetmask) && (mcr & TRISTATE_BIT))
return 0; return 0;
tri_reg |= TRISTATE_BIT; mcr |= TRISTATE_BIT;
break; break;
default: default:
return -EINVAL; return -EINVAL;
...@@ -980,268 +973,320 @@ static int hpt3xx_busproc(ide_drive_t *drive, int state) ...@@ -980,268 +973,320 @@ static int hpt3xx_busproc(ide_drive_t *drive, int state)
hwif->drives[0].failures = hwif->drives[0].max_failures + 1; hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
hwif->drives[1].failures = hwif->drives[1].max_failures + 1; hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
pci_write_config_word(dev, tristate, tri_reg); pci_write_config_word(dev, mcr_addr, mcr);
pci_write_config_byte(dev, 0x59, bus_reg | resetmask); pci_write_config_byte(dev, 0x59, bsr2 | resetmask);
return 0; return 0;
} }
static void __devinit hpt366_clocking(ide_hwif_t *hwif) /**
* hpt37x_calibrate_dpll - calibrate the DPLL
* @dev: PCI device
*
* Perform a calibration cycle on the DPLL.
* Returns 1 if this succeeds
*/
static int __devinit hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f_high)
{ {
u32 reg1 = 0; u32 dpll = (f_high << 16) | f_low | 0x100;
struct hpt_info *info = ide_get_hwifdata(hwif); u8 scr2;
int i;
pci_read_config_dword(hwif->pci_dev, 0x40, &reg1); pci_write_config_dword(dev, 0x5c, dpll);
/* detect bus speed by looking at control reg timing: */ /* Wait for oscillator ready */
switch((reg1 >> 8) & 7) { for(i = 0; i < 0x5000; ++i) {
case 5: udelay(50);
info->speed = forty_base_hpt36x; pci_read_config_byte(dev, 0x5b, &scr2);
break; if (scr2 & 0x80)
case 9:
info->speed = twenty_five_base_hpt36x;
break;
case 7:
default:
info->speed = thirty_three_base_hpt36x;
break; break;
} }
/* See if it stays ready (we'll just bail out if it's not yet) */
for(i = 0; i < 0x1000; ++i) {
pci_read_config_byte(dev, 0x5b, &scr2);
/* DPLL destabilized? */
if(!(scr2 & 0x80))
return 0;
}
/* Turn off tuning, we have the DPLL set */
pci_read_config_dword (dev, 0x5c, &dpll);
pci_write_config_dword(dev, 0x5c, (dpll & ~0x100));
return 1;
} }
static void __devinit hpt37x_clocking(ide_hwif_t *hwif) static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name)
{ {
struct hpt_info *info = ide_get_hwifdata(hwif); struct hpt_info *info = kmalloc(sizeof(struct hpt_info), GFP_KERNEL);
struct pci_dev *dev = hwif->pci_dev; unsigned long io_base = pci_resource_start(dev, 4);
int adjust, i; u8 pci_clk, dpll_clk = 0; /* PCI and DPLL clock in MHz */
u16 freq = 0; enum ata_clock clock;
u32 pll, temp = 0;
u8 reg5bh = 0, mcr1 = 0; if (info == NULL) {
printk(KERN_ERR "%s: out of memory!\n", name);
return -ENOMEM;
}
/* /*
* default to pci clock. make sure MA15/16 are set to output * Copy everything from a static "template" structure
* to prevent drives having problems with 40-pin cables. Needed * to just allocated per-chip hpt_info structure.
* for some drives such as IBM-DTLA which will not enter ready
* state on reset when PDIAG is a input.
*
* ToDo: should we set 0x21 when using PLL mode ?
*/ */
pci_write_config_byte(dev, 0x5b, 0x23); *info = *(struct hpt_info *)pci_get_drvdata(dev);
/* /*
* We'll have to read f_CNT value in order to determine * FIXME: Not portable. Also, why do we enable the ROM in the first place?
* the PCI clock frequency according to the following ratio: * We don't seem to be using it.
*
* f_CNT = Fpci * 192 / Fdpll
*
* First try reading the register in which the HighPoint BIOS
* saves f_CNT value before reprogramming the DPLL from its
* default setting (which differs for the various chips).
* NOTE: This register is only accessible via I/O space.
*
* In case the signature check fails, we'll have to resort to
* reading the f_CNT register itself in hopes that nobody has
* touched the DPLL yet...
*/ */
temp = inl(pci_resource_start(dev, 4) + 0x90); if (dev->resource[PCI_ROM_RESOURCE].start)
if ((temp & 0xFFFFF000) != 0xABCDE000) { pci_write_config_dword(dev, PCI_ROM_ADDRESS,
printk(KERN_WARNING "HPT37X: no clock data saved by BIOS\n"); dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
/* Calculate the average value of f_CNT */ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
for (temp = i = 0; i < 128; i++) { pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
pci_read_config_word(dev, 0x78, &freq); pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
temp += freq & 0x1ff; pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
mdelay(1);
}
freq = temp / 128;
} else
freq = temp & 0x1ff;
/* /*
* HPT3xxN chips use different PCI clock information. * First, try to estimate the PCI clock frequency...
* Currently we always set up the PLL for them.
*/ */
if (info->chip_type >= HPT370) {
u8 scr1 = 0;
u16 f_cnt = 0;
u32 temp = 0;
if (info->flags & IS_3xxN) { /* Interrupt force enable. */
if(freq < 0x55) pci_read_config_byte(dev, 0x5a, &scr1);
pll = F_LOW_PCI_33; if (scr1 & 0x10)
else if(freq < 0x70) pci_write_config_byte(dev, 0x5a, scr1 & ~0x10);
pll = F_LOW_PCI_40;
else if(freq < 0x7F)
pll = F_LOW_PCI_50;
else
pll = F_LOW_PCI_66;
printk(KERN_INFO "HPT3xxN detected, FREQ: %d, PLL: %d\n", freq, pll); /*
} * HighPoint does this for HPT372A.
else * NOTE: This register is only writeable via I/O space.
{ */
if(freq < 0x9C) if (info->chip_type == HPT372A)
pll = F_LOW_PCI_33; outb(0x0e, io_base + 0x9c);
else if(freq < 0xb0)
pll = F_LOW_PCI_40; /*
else if(freq <0xc8) * Default to PCI clock. Make sure MA15/16 are set to output
pll = F_LOW_PCI_50; * to prevent drives having problems with 40-pin cables.
*/
pci_write_config_byte(dev, 0x5b, 0x23);
/*
* We'll have to read f_CNT value in order to determine
* the PCI clock frequency according to the following ratio:
*
* f_CNT = Fpci * 192 / Fdpll
*
* First try reading the register in which the HighPoint BIOS
* saves f_CNT value before reprogramming the DPLL from its
* default setting (which differs for the various chips).
* NOTE: This register is only accessible via I/O space.
*
* In case the signature check fails, we'll have to resort to
* reading the f_CNT register itself in hopes that nobody has
* touched the DPLL yet...
*/
temp = inl(io_base + 0x90);
if ((temp & 0xFFFFF000) != 0xABCDE000) {
int i;
printk(KERN_WARNING "%s: no clock data saved by BIOS\n",
name);
/* Calculate the average value of f_CNT. */
for (temp = i = 0; i < 128; i++) {
pci_read_config_word(dev, 0x78, &f_cnt);
temp += f_cnt & 0x1ff;
mdelay(1);
}
f_cnt = temp / 128;
} else
f_cnt = temp & 0x1ff;
dpll_clk = info->dpll_clk;
pci_clk = (f_cnt * dpll_clk) / 192;
/* Clamp PCI clock to bands. */
if (pci_clk < 40)
pci_clk = 33;
else if(pci_clk < 45)
pci_clk = 40;
else if(pci_clk < 55)
pci_clk = 50;
else else
pll = F_LOW_PCI_66; pci_clk = 66;
if (pll == F_LOW_PCI_33) { printk(KERN_INFO "%s: DPLL base: %d MHz, f_CNT: %d, "
info->speed = thirty_three_base_hpt37x; "assuming %d MHz PCI\n", name, dpll_clk, f_cnt, pci_clk);
printk(KERN_DEBUG "HPT37X: using 33MHz PCI clock\n"); } else {
} else if (pll == F_LOW_PCI_40) { u32 itr1 = 0;
/* Unsupported */
} else if (pll == F_LOW_PCI_50) { pci_read_config_dword(dev, 0x40, &itr1);
info->speed = fifty_base_hpt37x;
printk(KERN_DEBUG "HPT37X: using 50MHz PCI clock\n"); /* Detect PCI clock by looking at cmd_high_time. */
} else { switch((itr1 >> 8) & 0x07) {
info->speed = sixty_six_base_hpt37x; case 0x09:
printk(KERN_DEBUG "HPT37X: using 66MHz PCI clock\n"); pci_clk = 40;
break;
case 0x05:
pci_clk = 25;
break;
case 0x07:
default:
pci_clk = 33;
break;
} }
} }
if (pll == F_LOW_PCI_66) /* Let's assume we'll use PCI clock for the ATA clock... */
info->flags |= PCI_66MHZ; switch (pci_clk) {
case 25:
clock = ATA_CLOCK_25MHZ;
break;
case 33:
default:
clock = ATA_CLOCK_33MHZ;
break;
case 40:
clock = ATA_CLOCK_40MHZ;
break;
case 50:
clock = ATA_CLOCK_50MHZ;
break;
case 66:
clock = ATA_CLOCK_66MHZ;
break;
}
/* /*
* only try the pll if we don't have a table for the clock * Only try the DPLL if we don't have a table for the PCI clock that
* speed that we're running at. NOTE: the internal PLL will * we are running at for HPT370/A, always use it for anything newer...
* result in slow reads when using a 33MHz PCI clock. we also
* don't like to use the PLL because it will cause glitches
* on PRST/SRST when the HPT state engine gets reset.
* *
* ToDo: Use 66MHz PLL when ATA133 devices are present on a * NOTE: Using the internal DPLL results in slow reads on 33 MHz PCI.
* 372 device so we can get ATA133 support * We also don't like using the DPLL because this causes glitches
* on PRST-/SRST- when the state engine gets reset...
*/ */
if (info->speed) if (info->chip_type >= HPT374 || info->settings[clock] == NULL) {
goto init_hpt37X_done; u16 f_low, delta = pci_clk < 50 ? 2 : 4;
int adjust;
/*
* Select 66 MHz DPLL clock only if UltraATA/133 mode is
* supported/enabled, use 50 MHz DPLL clock otherwise...
*/
if (info->max_mode == 0x04) {
dpll_clk = 66;
clock = ATA_CLOCK_66MHZ;
} else if (dpll_clk) { /* HPT36x chips don't have DPLL */
dpll_clk = 50;
clock = ATA_CLOCK_50MHZ;
}
info->flags |= PLL_MODE; if (info->settings[clock] == NULL) {
printk(KERN_ERR "%s: unknown bus timing!\n", name);
/* kfree(info);
* Adjust the PLL based upon the PCI clock, enable it, and return -EIO;
* wait for stabilization...
*/
adjust = 0;
freq = (pll < F_LOW_PCI_50) ? 2 : 4;
while (adjust++ < 6) {
pci_write_config_dword(dev, 0x5c, (freq + pll) << 16 |
pll | 0x100);
/* wait for clock stabilization */
for (i = 0; i < 0x50000; i++) {
pci_read_config_byte(dev, 0x5b, &reg5bh);
if (reg5bh & 0x80) {
/* spin looking for the clock to destabilize */
for (i = 0; i < 0x1000; ++i) {
pci_read_config_byte(dev, 0x5b,
&reg5bh);
if ((reg5bh & 0x80) == 0)
goto pll_recal;
}
pci_read_config_dword(dev, 0x5c, &pll);
pci_write_config_dword(dev, 0x5c,
pll & ~0x100);
pci_write_config_byte(dev, 0x5b, 0x21);
info->speed = fifty_base_hpt37x;
printk("HPT37X: using 50MHz internal PLL\n");
goto init_hpt37X_done;
}
} }
pll_recal:
if (adjust & 1)
pll -= (adjust >> 1);
else
pll += (adjust >> 1);
}
init_hpt37X_done: /* Select the DPLL clock. */
if (!info->speed) pci_write_config_byte(dev, 0x5b, 0x21);
printk(KERN_ERR "HPT37x%s: unknown bus timing [%d %d].\n",
(info->flags & IS_3xxN) ? "N" : "", pll, freq);
/*
* Reset the state engines.
* NOTE: avoid accidentally enabling the primary channel on HPT371N.
*/
pci_read_config_byte(dev, 0x50, &mcr1);
if (mcr1 & 0x04)
pci_write_config_byte(dev, 0x50, 0x37);
pci_write_config_byte(dev, 0x54, 0x37);
udelay(100);
}
static int __devinit init_hpt37x(struct pci_dev *dev) /*
{ * Adjust the DPLL based upon PCI clock, enable it,
u8 reg5ah; * and wait for stabilization...
*/
f_low = (pci_clk * 48) / dpll_clk;
pci_read_config_byte(dev, 0x5a, &reg5ah); for (adjust = 0; adjust < 8; adjust++) {
/* interrupt force enable */ if(hpt37x_calibrate_dpll(dev, f_low, f_low + delta))
pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10)); break;
return 0;
}
static int __devinit init_hpt366(struct pci_dev *dev) /*
{ * See if it'll settle at a fractionally different clock
u32 reg1 = 0; */
u8 drive_fast = 0; if (adjust & 1)
f_low -= adjust >> 1;
else
f_low += adjust >> 1;
}
if (adjust == 8) {
printk(KERN_ERR "%s: DPLL did not stabilize!\n", name);
kfree(info);
return -EIO;
}
/* printk("%s: using %d MHz DPLL clock\n", name, dpll_clk);
* Disable the "fast interrupt" prediction. } else {
*/ /* Mark the fact that we're not using the DPLL. */
pci_read_config_byte(dev, 0x51, &drive_fast); dpll_clk = 0;
if (drive_fast & 0x80)
pci_write_config_byte(dev, 0x51, drive_fast & ~0x80);
pci_read_config_dword(dev, 0x40, &reg1);
return 0;
}
static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name) printk("%s: using %d MHz PCI clock\n", name, pci_clk);
{ }
int ret = 0;
/* /*
* FIXME: Not portable. Also, why do we enable the ROM in the first place? * Advance the table pointer to a slot which points to the list
* We don't seem to be using it. * of the register values settings matching the clock being used.
*/ */
if (dev->resource[PCI_ROM_RESOURCE].start) info->settings += clock;
pci_write_config_dword(dev, PCI_ROM_ADDRESS,
dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); /* Store the clock frequencies. */
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); info->dpll_clk = dpll_clk;
pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); info->pci_clk = pci_clk;
pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
if (hpt_revision(dev) >= 3) /* Point to this chip's own instance of the hpt_info structure. */
ret = init_hpt37x(dev); pci_set_drvdata(dev, info);
else
ret = init_hpt366(dev);
if (ret) if (info->chip_type >= HPT370) {
return ret; u8 mcr1, mcr4;
/*
* Reset the state engines.
* NOTE: Avoid accidentally enabling the disabled channels.
*/
pci_read_config_byte (dev, 0x50, &mcr1);
pci_read_config_byte (dev, 0x54, &mcr4);
pci_write_config_byte(dev, 0x50, (mcr1 | 0x32));
pci_write_config_byte(dev, 0x54, (mcr4 | 0x32));
udelay(100);
}
/*
* On HPT371N, if ATA clock is 66 MHz we must set bit 2 in
* the MISC. register to stretch the UltraDMA Tss timing.
* NOTE: This register is only writeable via I/O space.
*/
if (info->chip_type == HPT371N && clock == ATA_CLOCK_66MHZ)
outb(inb(io_base + 0x9c) | 0x04, io_base + 0x9c);
return dev->irq; return dev->irq;
} }
static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
{ {
struct pci_dev *dev = hwif->pci_dev; struct pci_dev *dev = hwif->pci_dev;
struct hpt_info *info = ide_get_hwifdata(hwif); struct hpt_info *info = pci_get_drvdata(dev);
u8 ata66 = 0, regmask = (hwif->channel) ? 0x01 : 0x02;
int serialize = HPT_SERIALIZE_IO; int serialize = HPT_SERIALIZE_IO;
u8 scr1 = 0, ata66 = (hwif->channel) ? 0x01 : 0x02;
u8 chip_type = info->chip_type;
u8 new_mcr, old_mcr = 0;
/* Cache the channel's MISC. control registers' offset */
hwif->select_data = hwif->channel ? 0x54 : 0x50;
hwif->tuneproc = &hpt3xx_tune_drive; hwif->tuneproc = &hpt3xx_tune_drive;
hwif->speedproc = &hpt3xx_tune_chipset; hwif->speedproc = &hpt3xx_tune_chipset;
hwif->quirkproc = &hpt3xx_quirkproc; hwif->quirkproc = &hpt3xx_quirkproc;
hwif->intrproc = &hpt3xx_intrproc; hwif->intrproc = &hpt3xx_intrproc;
hwif->maskproc = &hpt3xx_maskproc; hwif->maskproc = &hpt3xx_maskproc;
hwif->busproc = &hpt3xx_busproc;
/* /*
* HPT3xxN chips have some complications: * HPT3xxN chips have some complications:
* *
* - on 33 MHz PCI we must clock switch * - on 33 MHz PCI we must clock switch
* - on 66 MHz PCI we must NOT use the PCI clock * - on 66 MHz PCI we must NOT use the PCI clock
*/ */
if ((info->flags & (IS_3xxN | PCI_66MHZ)) == IS_3xxN) { if (chip_type >= HPT372N && info->dpll_clk && info->pci_clk < 66) {
/* /*
* Clock is shared between the channels, * Clock is shared between the channels,
* so we'll have to serialize them... :-( * so we'll have to serialize them... :-(
...@@ -1250,200 +1295,171 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) ...@@ -1250,200 +1295,171 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
hwif->rw_disk = &hpt3xxn_rw_disk; hwif->rw_disk = &hpt3xxn_rw_disk;
} }
/* Serialize access to this device if needed */
if (serialize && hwif->mate)
hwif->serialized = hwif->mate->serialized = 1;
/*
* Disable the "fast interrupt" prediction. Don't hold off
* on interrupts. (== 0x01 despite what the docs say)
*/
pci_read_config_byte(dev, hwif->select_data + 1, &old_mcr);
if (info->chip_type >= HPT374)
new_mcr = old_mcr & ~0x07;
else if (info->chip_type >= HPT370) {
new_mcr = old_mcr;
new_mcr &= ~0x02;
#ifdef HPT_DELAY_INTERRUPT
new_mcr &= ~0x01;
#else
new_mcr |= 0x01;
#endif
} else /* HPT366 and HPT368 */
new_mcr = old_mcr & ~0x80;
if (new_mcr != old_mcr)
pci_write_config_byte(dev, hwif->select_data + 1, new_mcr);
if (!hwif->dma_base) {
hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
return;
}
hwif->ultra_mask = 0x7f;
hwif->mwdma_mask = 0x07;
/* /*
* The HPT37x uses the CBLID pins as outputs for MA15/MA16 * The HPT37x uses the CBLID pins as outputs for MA15/MA16
* address lines to access an external eeprom. To read valid * address lines to access an external EEPROM. To read valid
* cable detect state the pins must be enabled as inputs. * cable detect state the pins must be enabled as inputs.
*/ */
if (info->revision >= 8 && (PCI_FUNC(dev->devfn) & 1)) { if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) {
/* /*
* HPT374 PCI function 1 * HPT374 PCI function 1
* - set bit 15 of reg 0x52 to enable TCBLID as input * - set bit 15 of reg 0x52 to enable TCBLID as input
* - set bit 15 of reg 0x56 to enable FCBLID as input * - set bit 15 of reg 0x56 to enable FCBLID as input
*/ */
u16 mcr3, mcr6; u8 mcr_addr = hwif->select_data + 2;
pci_read_config_word(dev, 0x52, &mcr3); u16 mcr;
pci_read_config_word(dev, 0x56, &mcr6);
pci_write_config_word(dev, 0x52, mcr3 | 0x8000); pci_read_config_word (dev, mcr_addr, &mcr);
pci_write_config_word(dev, 0x56, mcr6 | 0x8000); pci_write_config_word(dev, mcr_addr, (mcr | 0x8000));
/* now read cable id register */ /* now read cable id register */
pci_read_config_byte(dev, 0x5a, &ata66); pci_read_config_byte (dev, 0x5a, &scr1);
pci_write_config_word(dev, 0x52, mcr3); pci_write_config_word(dev, mcr_addr, mcr);
pci_write_config_word(dev, 0x56, mcr6); } else if (chip_type >= HPT370) {
} else if (info->revision >= 3) {
/* /*
* HPT370/372 and 374 pcifn 0 * HPT370/372 and 374 pcifn 0
* - clear bit 0 of 0x5b to enable P/SCBLID as inputs * - clear bit 0 of reg 0x5b to enable P/SCBLID as inputs
*/ */
u8 scr2; u8 scr2 = 0;
pci_read_config_byte(dev, 0x5b, &scr2);
pci_write_config_byte(dev, 0x5b, scr2 & ~1);
/* now read cable id register */
pci_read_config_byte(dev, 0x5a, &ata66);
pci_write_config_byte(dev, 0x5b, scr2);
} else {
pci_read_config_byte(dev, 0x5a, &ata66);
}
#ifdef DEBUG pci_read_config_byte (dev, 0x5b, &scr2);
printk("HPT366: reg5ah=0x%02x ATA-%s Cable Port%d\n", pci_write_config_byte(dev, 0x5b, (scr2 & ~1));
ata66, (ata66 & regmask) ? "33" : "66", /* now read cable id register */
PCI_FUNC(hwif->pci_dev->devfn)); pci_read_config_byte (dev, 0x5a, &scr1);
#endif /* DEBUG */ pci_write_config_byte(dev, 0x5b, scr2);
} else
/* Serialize access to this device */ pci_read_config_byte (dev, 0x5a, &scr1);
if (serialize && hwif->mate)
hwif->serialized = hwif->mate->serialized = 1;
/* if (!hwif->udma_four)
* Set up ioctl for power status. hwif->udma_four = (scr1 & ata66) ? 0 : 1;
* NOTE: power affects both drives on each channel.
*/
hwif->busproc = &hpt3xx_busproc;
if (!hwif->dma_base) { hwif->ide_dma_check = &hpt366_config_drive_xfer_rate;
hwif->drives[0].autotune = 1;
hwif->drives[1].autotune = 1;
return;
}
hwif->ultra_mask = 0x7f; if (chip_type >= HPT374) {
hwif->mwdma_mask = 0x07; hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
hwif->ide_dma_end = &hpt374_ide_dma_end;
if (!(hwif->udma_four)) } else if (chip_type >= HPT370) {
hwif->udma_four = ((ata66 & regmask) ? 0 : 1); hwif->dma_start = &hpt370_ide_dma_start;
hwif->ide_dma_check = &hpt366_config_drive_xfer_rate; hwif->ide_dma_end = &hpt370_ide_dma_end;
hwif->ide_dma_timeout = &hpt370_ide_dma_timeout;
if (info->revision >= 8) { } else
hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq;
hwif->ide_dma_end = &hpt374_ide_dma_end;
} else if (info->revision >= 5) {
hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
hwif->ide_dma_end = &hpt374_ide_dma_end;
} else if (info->revision >= 3) {
hwif->dma_start = &hpt370_ide_dma_start;
hwif->ide_dma_end = &hpt370_ide_dma_end;
hwif->ide_dma_timeout = &hpt370_ide_dma_timeout;
hwif->ide_dma_lostirq = &hpt370_ide_dma_lostirq;
} else if (info->revision >= 2)
hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq;
else
hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq;
if (!noautodma) if (!noautodma)
hwif->autodma = 1; hwif->autodma = 1;
hwif->drives[0].autodma = hwif->autodma; hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
hwif->drives[1].autodma = hwif->autodma;
} }
static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
{ {
struct hpt_info *info = ide_get_hwifdata(hwif); struct pci_dev *dev = hwif->pci_dev;
u8 masterdma = 0, slavedma = 0; u8 masterdma = 0, slavedma = 0;
u8 dma_new = 0, dma_old = 0; u8 dma_new = 0, dma_old = 0;
u8 primary = hwif->channel ? 0x4b : 0x43;
u8 secondary = hwif->channel ? 0x4f : 0x47;
unsigned long flags; unsigned long flags;
if (!dmabase) if (!dmabase)
return; return;
if(info->speed == NULL) { dma_old = hwif->INB(dmabase + 2);
printk(KERN_WARNING "hpt366: no known IDE timings, disabling DMA.\n");
return;
}
dma_old = hwif->INB(dmabase+2);
local_irq_save(flags); local_irq_save(flags);
dma_new = dma_old; dma_new = dma_old;
pci_read_config_byte(hwif->pci_dev, primary, &masterdma); pci_read_config_byte(dev, hwif->channel ? 0x4b : 0x43, &masterdma);
pci_read_config_byte(hwif->pci_dev, secondary, &slavedma); pci_read_config_byte(dev, hwif->channel ? 0x4f : 0x47, &slavedma);
if (masterdma & 0x30) dma_new |= 0x20; if (masterdma & 0x30) dma_new |= 0x20;
if (slavedma & 0x30) dma_new |= 0x40; if ( slavedma & 0x30) dma_new |= 0x40;
if (dma_new != dma_old) if (dma_new != dma_old)
hwif->OUTB(dma_new, dmabase+2); hwif->OUTB(dma_new, dmabase + 2);
local_irq_restore(flags); local_irq_restore(flags);
ide_setup_dma(hwif, dmabase, 8); ide_setup_dma(hwif, dmabase, 8);
} }
/*
* We "borrow" this hook in order to set the data structures
* up early enough before dma or init_hwif calls are made.
*/
static void __devinit init_iops_hpt366(ide_hwif_t *hwif)
{
struct hpt_info *info = kzalloc(sizeof(struct hpt_info), GFP_KERNEL);
struct pci_dev *dev = hwif->pci_dev;
u16 did = dev->device;
u8 rid = 0;
if(info == NULL) {
printk(KERN_WARNING "hpt366: out of memory.\n");
return;
}
ide_set_hwifdata(hwif, info);
/* Avoid doing the same thing twice. */
if (hwif->channel && hwif->mate) {
memcpy(info, ide_get_hwifdata(hwif->mate), sizeof(struct hpt_info));
return;
}
pci_read_config_byte(dev, PCI_CLASS_REVISION, &rid);
if (( did == PCI_DEVICE_ID_TTI_HPT366 && rid == 6) ||
((did == PCI_DEVICE_ID_TTI_HPT372 ||
did == PCI_DEVICE_ID_TTI_HPT302 ||
did == PCI_DEVICE_ID_TTI_HPT371) && rid > 1) ||
did == PCI_DEVICE_ID_TTI_HPT372N)
info->flags |= IS_3xxN;
info->revision = hpt_revision(dev);
if (info->revision >= 3)
hpt37x_clocking(hwif);
else
hpt366_clocking(hwif);
}
static int __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d) static int __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d)
{ {
struct pci_dev *findev = NULL; struct pci_dev *dev2;
if (PCI_FUNC(dev->devfn) & 1) if (PCI_FUNC(dev->devfn) & 1)
return -ENODEV; return -ENODEV;
while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) { pci_set_drvdata(dev, &hpt374);
if ((findev->vendor == dev->vendor) &&
(findev->device == dev->device) && if ((dev2 = pci_get_slot(dev->bus, dev->devfn + 1)) != NULL) {
((findev->devfn - dev->devfn) == 1) && int ret;
(PCI_FUNC(findev->devfn) & 1)) {
if (findev->irq != dev->irq) { pci_set_drvdata(dev2, &hpt374);
/* FIXME: we need a core pci_set_interrupt() */
findev->irq = dev->irq; if (dev2->irq != dev->irq) {
printk(KERN_WARNING "%s: pci-config space interrupt " /* FIXME: we need a core pci_set_interrupt() */
"fixed.\n", d->name); dev2->irq = dev->irq;
} printk(KERN_WARNING "%s: PCI config space interrupt "
return ide_setup_pci_devices(dev, findev, d); "fixed.\n", d->name);
} }
ret = ide_setup_pci_devices(dev, dev2, d);
if (ret < 0)
pci_dev_put(dev2);
return ret;
} }
return ide_setup_pci_device(dev, d); return ide_setup_pci_device(dev, d);
} }
static int __devinit init_setup_hpt37x(struct pci_dev *dev, ide_pci_device_t *d) static int __devinit init_setup_hpt372n(struct pci_dev *dev, ide_pci_device_t *d)
{ {
pci_set_drvdata(dev, &hpt372n);
return ide_setup_pci_device(dev, d); return ide_setup_pci_device(dev, d);
} }
static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d) static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d)
{ {
u8 mcr1 = 0; struct hpt_info *info;
u8 rev = 0, mcr1 = 0;
pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
if (rev > 1) {
d->name = "HPT371N";
info = &hpt371n;
} else
info = &hpt371;
/* /*
* HPT371 chips physically have only one channel, the secondary one, * HPT371 chips physically have only one channel, the secondary one,
...@@ -1453,59 +1469,94 @@ static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d) ...@@ -1453,59 +1469,94 @@ static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d)
*/ */
pci_read_config_byte(dev, 0x50, &mcr1); pci_read_config_byte(dev, 0x50, &mcr1);
if (mcr1 & 0x04) if (mcr1 & 0x04)
pci_write_config_byte(dev, 0x50, (mcr1 & ~0x04)); pci_write_config_byte(dev, 0x50, mcr1 & ~0x04);
pci_set_drvdata(dev, info);
return ide_setup_pci_device(dev, d);
}
static int __devinit init_setup_hpt372a(struct pci_dev *dev, ide_pci_device_t *d)
{
struct hpt_info *info;
u8 rev = 0;
pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
if (rev > 1) {
d->name = "HPT372N";
info = &hpt372n;
} else
info = &hpt372a;
pci_set_drvdata(dev, info);
return ide_setup_pci_device(dev, d);
}
static int __devinit init_setup_hpt302(struct pci_dev *dev, ide_pci_device_t *d)
{
struct hpt_info *info;
u8 rev = 0;
pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
if (rev > 1) {
d->name = "HPT302N";
info = &hpt302n;
} else
info = &hpt302;
pci_set_drvdata(dev, info);
return ide_setup_pci_device(dev, d); return ide_setup_pci_device(dev, d);
} }
static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d) static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
{ {
struct pci_dev *findev = NULL; struct pci_dev *dev2;
u8 pin1 = 0, pin2 = 0; u8 rev = 0;
unsigned int class_rev; static char *chipset_names[] = { "HPT366", "HPT366", "HPT368",
char *chipset_names[] = {"HPT366", "HPT366", "HPT368", "HPT370", "HPT370A", "HPT372",
"HPT370", "HPT370A", "HPT372", "HPT372N" };
"HPT372N" }; static struct hpt_info *info[] = { &hpt36x, &hpt36x, &hpt36x,
&hpt370, &hpt370a, &hpt372,
&hpt372n };
if (PCI_FUNC(dev->devfn) & 1) if (PCI_FUNC(dev->devfn) & 1)
return -ENODEV; return -ENODEV;
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
class_rev &= 0xff;
if(dev->device == PCI_DEVICE_ID_TTI_HPT372N) if (rev > 6)
class_rev = 6; rev = 6;
if(class_rev <= 6) d->name = chipset_names[rev];
d->name = chipset_names[class_rev];
pci_set_drvdata(dev, info[rev]);
switch(class_rev) {
case 6: if (rev > 2)
case 5: goto init_single;
case 4:
case 3:
goto init_single;
default:
break;
}
d->channels = 1; d->channels = 1;
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); if ((dev2 = pci_get_slot(dev->bus, dev->devfn + 1)) != NULL) {
while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) { u8 pin1 = 0, pin2 = 0;
if ((findev->vendor == dev->vendor) && int ret;
(findev->device == dev->device) &&
((findev->devfn - dev->devfn) == 1) && pci_set_drvdata(dev2, info[rev]);
(PCI_FUNC(findev->devfn) & 1)) {
pci_read_config_byte(findev, PCI_INTERRUPT_PIN, &pin2); pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1);
if ((pin1 != pin2) && (dev->irq == findev->irq)) { pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2);
d->bootable = ON_BOARD; if (pin1 != pin2 && dev->irq == dev2->irq) {
printk("%s: onboard version of chipset, " d->bootable = ON_BOARD;
"pin1=%d pin2=%d\n", d->name, printk("%s: onboard version of chipset, pin1=%d pin2=%d\n",
pin1, pin2); d->name, pin1, pin2);
}
return ide_setup_pci_devices(dev, findev, d);
} }
ret = ide_setup_pci_devices(dev, dev2, d);
if (ret < 0)
pci_dev_put(dev2);
return ret;
} }
init_single: init_single:
return ide_setup_pci_device(dev, d); return ide_setup_pci_device(dev, d);
...@@ -1516,64 +1567,68 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { ...@@ -1516,64 +1567,68 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.name = "HPT366", .name = "HPT366",
.init_setup = init_setup_hpt366, .init_setup = init_setup_hpt366,
.init_chipset = init_chipset_hpt366, .init_chipset = init_chipset_hpt366,
.init_iops = init_iops_hpt366,
.init_hwif = init_hwif_hpt366, .init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366, .init_dma = init_dma_hpt366,
.channels = 2, .channels = 2,
.autodma = AUTODMA, .autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
.bootable = OFF_BOARD, .bootable = OFF_BOARD,
.extra = 240 .extra = 240
},{ /* 1 */ },{ /* 1 */
.name = "HPT372A", .name = "HPT372A",
.init_setup = init_setup_hpt37x, .init_setup = init_setup_hpt372a,
.init_chipset = init_chipset_hpt366, .init_chipset = init_chipset_hpt366,
.init_iops = init_iops_hpt366,
.init_hwif = init_hwif_hpt366, .init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366, .init_dma = init_dma_hpt366,
.channels = 2, .channels = 2,
.autodma = AUTODMA, .autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
.bootable = OFF_BOARD, .bootable = OFF_BOARD,
.extra = 240
},{ /* 2 */ },{ /* 2 */
.name = "HPT302", .name = "HPT302",
.init_setup = init_setup_hpt37x, .init_setup = init_setup_hpt302,
.init_chipset = init_chipset_hpt366, .init_chipset = init_chipset_hpt366,
.init_iops = init_iops_hpt366,
.init_hwif = init_hwif_hpt366, .init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366, .init_dma = init_dma_hpt366,
.channels = 2, .channels = 2,
.autodma = AUTODMA, .autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
.bootable = OFF_BOARD, .bootable = OFF_BOARD,
.extra = 240
},{ /* 3 */ },{ /* 3 */
.name = "HPT371", .name = "HPT371",
.init_setup = init_setup_hpt371, .init_setup = init_setup_hpt371,
.init_chipset = init_chipset_hpt366, .init_chipset = init_chipset_hpt366,
.init_iops = init_iops_hpt366,
.init_hwif = init_hwif_hpt366, .init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366, .init_dma = init_dma_hpt366,
.channels = 2, .channels = 2,
.autodma = AUTODMA, .autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
.bootable = OFF_BOARD, .bootable = OFF_BOARD,
.extra = 240
},{ /* 4 */ },{ /* 4 */
.name = "HPT374", .name = "HPT374",
.init_setup = init_setup_hpt374, .init_setup = init_setup_hpt374,
.init_chipset = init_chipset_hpt366, .init_chipset = init_chipset_hpt366,
.init_iops = init_iops_hpt366,
.init_hwif = init_hwif_hpt366, .init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366, .init_dma = init_dma_hpt366,
.channels = 2, /* 4 */ .channels = 2, /* 4 */
.autodma = AUTODMA, .autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
.bootable = OFF_BOARD, .bootable = OFF_BOARD,
.extra = 240
},{ /* 5 */ },{ /* 5 */
.name = "HPT372N", .name = "HPT372N",
.init_setup = init_setup_hpt37x, .init_setup = init_setup_hpt372n,
.init_chipset = init_chipset_hpt366, .init_chipset = init_chipset_hpt366,
.init_iops = init_iops_hpt366,
.init_hwif = init_hwif_hpt366, .init_hwif = init_hwif_hpt366,
.init_dma = init_dma_hpt366, .init_dma = init_dma_hpt366,
.channels = 2, /* 4 */ .channels = 2, /* 4 */
.autodma = AUTODMA, .autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
.bootable = OFF_BOARD, .bootable = OFF_BOARD,
.extra = 240
} }
}; };
......
/*
* 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%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment