summaryrefslogtreecommitdiff
path: root/sys/dev/pci/ahci.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci/ahci.c')
-rw-r--r--sys/dev/pci/ahci.c98
1 files changed, 78 insertions, 20 deletions
diff --git a/sys/dev/pci/ahci.c b/sys/dev/pci/ahci.c
index 4a316acba45..55922dc02bd 100644
--- a/sys/dev/pci/ahci.c
+++ b/sys/dev/pci/ahci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ahci.c,v 1.65 2007/03/05 06:06:13 pascoe Exp $ */
+/* $OpenBSD: ahci.c,v 1.66 2007/03/05 09:12:39 dlg Exp $ */
/*
* Copyright (c) 2006 David Gwynne <dlg@openbsd.org>
@@ -293,13 +293,6 @@ struct ahci_cmd_table {
#define AHCI_MAX_PORTS 32
-static const struct pci_matchid ahci_devices[] = {
- { PCI_VENDOR_JMICRON, PCI_PRODUCT_JMICRON_JMB361 }
-};
-
-int ahci_match(struct device *, void *, void *);
-void ahci_attach(struct device *, struct device *, void *);
-
struct ahci_dmamem {
bus_dmamap_t adm_map;
bus_dma_segment_t adm_seg;
@@ -366,6 +359,26 @@ struct ahci_softc {
};
#define DEVNAME(_s) ((_s)->sc_dev.dv_xname)
+struct ahci_device {
+ pci_vendor_id_t ad_vendor;
+ pci_product_id_t ad_product;
+ int (*ad_match)(struct pci_attach_args *);
+ int (*ad_attach)(struct pci_attach_args *);
+};
+
+const struct ahci_device *ahci_lookup_device(struct pci_attach_args *);
+
+int ahci_jmicron_match(struct pci_attach_args *);
+int ahci_jmicron_attach(struct pci_attach_args *);
+
+static const struct ahci_device ahci_devices[] = {
+ { PCI_VENDOR_JMICRON, PCI_PRODUCT_JMICRON_JMB361,
+ ahci_jmicron_match, ahci_jmicron_attach }
+};
+
+int ahci_match(struct device *, void *, void *);
+void ahci_attach(struct device *, struct device *, void *);
+
struct cfattach ahci_ca = {
sizeof(struct ahci_softc), ahci_match, ahci_attach
};
@@ -433,11 +446,46 @@ struct atascsi_methods ahci_atascsi_methods = {
ahci_ata_cmd
};
+const struct ahci_device *
+ahci_lookup_device(struct pci_attach_args *pa)
+{
+ int i;
+ const struct ahci_device *ad;
+
+ for (i = 0; i < (sizeof(ahci_devices) / sizeof(ahci_devices[0])); i++) {
+ ad = &ahci_devices[i];
+ if (ad->ad_vendor == PCI_VENDOR(pa->pa_id) &&
+ ad->ad_product == PCI_PRODUCT(pa->pa_id))
+ return (ad);
+ }
+
+ return (NULL);
+}
+
int
ahci_match(struct device *parent, void *match, void *aux)
{
- return (pci_matchbyid((struct pci_attach_args *)aux, ahci_devices,
- sizeof(ahci_devices) / sizeof(ahci_devices[0])));
+ struct pci_attach_args *pa = aux;
+ const struct ahci_device *ad;
+
+ ad = ahci_lookup_device(pa);
+ if (ad == NULL)
+ return (0);
+
+ /* the device may need special checks to see if it matches */
+ if (ad->ad_match != NULL)
+ return (ad->ad_match(pa));
+
+ return (2); /* match higher than pciide */
+}
+
+int
+ahci_jmicron_match(struct pci_attach_args *pa)
+{
+ if (pa->pa_function != 0)
+ return (0);
+
+ return (1);
}
void
@@ -445,21 +493,17 @@ ahci_attach(struct device *parent, struct device *self, void *aux)
{
struct ahci_softc *sc = (struct ahci_softc *)self;
struct pci_attach_args *pa = aux;
+ const struct ahci_device *ad;
struct atascsi_attach_args aaa;
u_int32_t reg;
int i;
- /* Switch JMICRON ports to AHCI mode */
- if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_JMICRON) {
- u_int32_t ccr;
-
- ccr = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x40);
- ccr &= ~0x0000ff00;
- ccr |= 0x0000a100;
- pci_conf_write(pa->pa_pc, pa->pa_tag, 0x40, ccr);
+ ad = ahci_lookup_device(pa);
+ if (ad == NULL)
+ panic("ahci attach cant find a device it matched on");
- /* Only function 0 is SATA */
- if (pa->pa_function != 0)
+ if (ad->ad_attach != NULL) {
+ if (ad->ad_attach(pa) != 0)
return;
}
@@ -539,6 +583,20 @@ unmap:
}
int
+ahci_jmicron_attach(struct pci_attach_args *pa)
+{
+ u_int32_t ccr;
+
+ /* Switch JMICRON ports to AHCI mode */
+ ccr = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x40);
+ ccr &= ~0x0000ff00;
+ ccr |= 0x0000a100;
+ pci_conf_write(pa->pa_pc, pa->pa_tag, 0x40, ccr);
+
+ return (0);
+}
+
+int
ahci_map_regs(struct ahci_softc *sc, struct pci_attach_args *pa)
{
pcireg_t maptype;