summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authordillo <dillo@NetBSD.org>2008-08-01 17:17:35 +0000
committerdillo <dillo@NetBSD.org>2008-08-01 17:17:35 +0000
commitf6bd05d87be082af3ac3a577a88423a7e2993534 (patch)
tree68c2cd2f49ebf9bb1f7d6628ff4a8fab2b475a31 /sys/dev
parent10c7b7cb02fb6401b9f580f20ed7e3d495de744a (diff)
Force ahcisata to attach to NVIDIA MCP65 and MCP67, as they don't
work with viaide. Reviewed by bouyer.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/ahcisata_pci.c66
1 files changed, 48 insertions, 18 deletions
diff --git a/sys/dev/pci/ahcisata_pci.c b/sys/dev/pci/ahcisata_pci.c
index e2a583d384f..ac92d7be4c3 100644
--- a/sys/dev/pci/ahcisata_pci.c
+++ b/sys/dev/pci/ahcisata_pci.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ahcisata_pci.c,v 1.11 2008/03/20 16:15:57 cube Exp $ */
+/* $NetBSD: ahcisata_pci.c,v 1.12 2008/08/01 17:17:35 dillo Exp $ */
/*
* Copyright (c) 2006 Manuel Bouyer.
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ahcisata_pci.c,v 1.11 2008/03/20 16:15:57 cube Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ahcisata_pci.c,v 1.12 2008/08/01 17:17:35 dillo Exp $");
#include <sys/types.h>
#include <sys/malloc.h>
@@ -49,6 +49,15 @@ __KERNEL_RCSID(0, "$NetBSD: ahcisata_pci.c,v 1.11 2008/03/20 16:15:57 cube Exp $
#include <dev/pci/pciidevar.h>
#include <dev/ic/ahcisatavar.h>
+#define AHCI_PCI_QUIRK_FORCE 1 /* force attach */
+
+static const struct pci_quirkdata ahci_pci_quirks[] = {
+ { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_SATA,
+ AHCI_PCI_QUIRK_FORCE },
+ { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_SATA,
+ AHCI_PCI_QUIRK_FORCE },
+};
+
struct ahci_pci_softc {
struct ahci_softc ah_sc;
pci_chipset_tag_t sc_pc;
@@ -58,6 +67,8 @@ struct ahci_pci_softc {
static int ahci_pci_match(device_t, cfdata_t, void *);
static void ahci_pci_attach(device_t, device_t, void *);
+const struct pci_quirkdata *ahci_pci_lookup_quirkdata(pci_vendor_id_t,
+ pci_product_id_t);
static bool ahci_pci_resume(device_t PMF_FN_PROTO);
@@ -72,25 +83,31 @@ ahci_pci_match(device_t parent, cfdata_t match, void *aux)
bus_space_handle_t regh;
bus_size_t size;
int ret = 0;
+ const struct pci_quirkdata *quirks;
+
+ quirks = ahci_pci_lookup_quirkdata(PCI_VENDOR(pa->pa_id),
+ PCI_PRODUCT(pa->pa_id));
+
+ /* if wrong class and not forced by quirks, don't match */
+ if ((PCI_CLASS(pa->pa_class) != PCI_CLASS_MASS_STORAGE ||
+ ((PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_MASS_STORAGE_SATA ||
+ PCI_INTERFACE(pa->pa_class) != PCI_INTERFACE_SATA_AHCI) &&
+ PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_MASS_STORAGE_RAID)) &&
+ (quirks == NULL || (quirks->quirks & AHCI_PCI_QUIRK_FORCE) == 0))
+ return 0;
+
+ if (pci_mapreg_map(pa, AHCI_PCI_ABAR,
+ PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
+ &regt, &regh, NULL, &size) != 0)
+ return 0;
- if (PCI_CLASS(pa->pa_class) == PCI_CLASS_MASS_STORAGE &&
- ((PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_SATA &&
+ if ((PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_SATA &&
PCI_INTERFACE(pa->pa_class) == PCI_INTERFACE_SATA_AHCI) ||
- PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_RAID)) {
- /* check if the chip is in ahci mode */
- if (pci_mapreg_map(pa, AHCI_PCI_ABAR,
- PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
- &regt, &regh, NULL, &size) != 0)
- return 0;
- if (PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_SATA
- && PCI_INTERFACE(pa->pa_class) == PCI_INTERFACE_SATA_AHCI)
- ret = 3;
- else if (bus_space_read_4(regt, regh, AHCI_GHC) & AHCI_GHC_AE)
- ret = 3;
- bus_space_unmap(regt, regh, size);
- return ret;
- }
+ (quirks && quirks->quirks & AHCI_PCI_QUIRK_FORCE) ||
+ (bus_space_read_4(regt, regh, AHCI_GHC) & AHCI_GHC_AE))
+ ret = 3;
+ bus_space_unmap(regt, regh, size);
return ret;
}
@@ -164,3 +181,16 @@ ahci_pci_resume(device_t dv PMF_FN_ARGS)
return true;
}
+
+const struct pci_quirkdata *
+ahci_pci_lookup_quirkdata(pci_vendor_id_t vendor, pci_product_id_t product)
+{
+ int i;
+
+ for (i = 0; i < (sizeof ahci_pci_quirks / sizeof ahci_pci_quirks[0]);
+ i++)
+ if (vendor == ahci_pci_quirks[i].vendor &&
+ product == ahci_pci_quirks[i].product)
+ return (&ahci_pci_quirks[i]);
+ return (NULL);
+}