Commit 067d03e8 authored by Andrew Chew's avatar Andrew Chew Committed by Jeff Garzik

[PATCH] sata_nv: enable generic class support for future NVIDIA SATA

This patch adds a new entry in the pci_device_id table that filters
by class code, in order to cause unlisted NVIDIA SATA controllers to
be probed.  In the probe function, we determine whether the device is
a SATA or IDE controller by checking the device's bars (NVIDIA SATA
controllers will always have 6 bars).  Bar5 I/O mapped vs. memory
mapped is now determined programmatically by looking at the resource
flags of the bar.
Signed-off-by: default avatarAndrew Chew <achew@nvidia.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent 4b24bacd
......@@ -20,6 +20,10 @@
* If you do not delete the provisions above, a recipient may use your
* version of this file under either the OSL or the GPL.
*
* 0.06
* - Added generic SATA support by using a pci_device_id that filters on
* the IDE storage class code.
*
* 0.03
* - Fixed a bug where the hotplug handlers for non-CK804/MCP04 were using
* mmio_base, which is only set for the CK804/MCP04 case.
......@@ -44,7 +48,7 @@
#include <linux/libata.h>
#define DRV_NAME "sata_nv"
#define DRV_VERSION "0.5"
#define DRV_VERSION "0.6"
#define NV_PORTS 2
#define NV_PIO_MASK 0x1f
......@@ -108,6 +112,7 @@ static void nv_check_hotplug_ck804(struct ata_host_set *host_set);
enum nv_host_type
{
GENERIC,
NFORCE2,
NFORCE3,
CK804
......@@ -128,6 +133,9 @@ static struct pci_device_id nv_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
{ PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC },
{ 0, } /* terminate list */
};
......@@ -136,29 +144,31 @@ static struct pci_device_id nv_pci_tbl[] = {
struct nv_host_desc
{
enum nv_host_type host_type;
unsigned long host_flags;
void (*enable_hotplug)(struct ata_probe_ent *probe_ent);
void (*disable_hotplug)(struct ata_host_set *host_set);
void (*check_hotplug)(struct ata_host_set *host_set);
};
static struct nv_host_desc nv_device_tbl[] = {
{
.host_type = GENERIC,
.enable_hotplug = NULL,
.disable_hotplug= NULL,
.check_hotplug = NULL,
},
{
.host_type = NFORCE2,
.host_flags = 0x00000000,
.enable_hotplug = nv_enable_hotplug,
.disable_hotplug= nv_disable_hotplug,
.check_hotplug = nv_check_hotplug,
},
{
.host_type = NFORCE3,
.host_flags = 0x00000000,
.enable_hotplug = nv_enable_hotplug,
.disable_hotplug= nv_disable_hotplug,
.check_hotplug = nv_check_hotplug,
},
{ .host_type = CK804,
.host_flags = NV_HOST_FLAGS_SCR_MMIO,
.enable_hotplug = nv_enable_hotplug_ck804,
.disable_hotplug= nv_disable_hotplug_ck804,
.check_hotplug = nv_check_hotplug_ck804,
......@@ -168,6 +178,7 @@ static struct nv_host_desc nv_device_tbl[] = {
struct nv_host
{
struct nv_host_desc *host_desc;
unsigned long host_flags;
};
static struct pci_driver nv_pci_driver = {
......@@ -284,8 +295,8 @@ static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg)
if (sc_reg > SCR_CONTROL)
return 0xffffffffU;
if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO)
return readl(ap->ioaddr.scr_addr + (sc_reg * 4));
if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO)
return readl((void*)ap->ioaddr.scr_addr + (sc_reg * 4));
else
return inl(ap->ioaddr.scr_addr + (sc_reg * 4));
}
......@@ -298,8 +309,8 @@ static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
if (sc_reg > SCR_CONTROL)
return;
if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO)
writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));
if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO)
writel(val, (void*)ap->ioaddr.scr_addr + (sc_reg * 4));
else
outl(val, ap->ioaddr.scr_addr + (sc_reg * 4));
}
......@@ -322,6 +333,14 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
struct ata_port_info *ppi;
struct ata_probe_ent *probe_ent;
int rc;
u32 bar;
// Make sure this is a SATA controller by counting the number of bars
// (NVIDIA SATA controllers will always have six bars). Otherwise,
// it's an IDE controller and we ignore it.
for (bar=0; bar<6; bar++)
if (pci_resource_start(pdev, bar) == 0)
return -ENODEV;
if (!printed_version++)
printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
......@@ -352,11 +371,15 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (!host)
goto err_out_free_ent;
memset(host, 0, sizeof(struct nv_host));
host->host_desc = &nv_device_tbl[ent->driver_data];
probe_ent->private_data = host;
if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO) {
if (pci_resource_flags(pdev, 5) & IORESOURCE_MEM)
host->host_flags |= NV_HOST_FLAGS_SCR_MMIO;
if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO) {
unsigned long base;
probe_ent->mmio_base = ioremap(pci_resource_start(pdev, 5),
......@@ -395,7 +418,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
return 0;
err_out_iounmap:
if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO)
if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO)
iounmap(probe_ent->mmio_base);
err_out_free_host:
kfree(host);
......
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