This diff will attempt to match up ACPI PCI devices with their BDF.
This will replace code currently used in acpiprt, but need to test this on
many machines to make sure the bus numbers match.
Code will panic if bus numbers do not match, please report dmesg if you
see a panic, along with pcidump -vv output on booted kernel.
Index: acpi.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/acpi.c,v
retrieving revision 1.168
diff -u -p -u -p -b -r1.168 acpi.c
--- acpi.c 1 Jul 2010 06:29:32 -0000 1.168
+++ acpi.c 1 Jul 2010 06:56:15 -0000
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpi.c,v 1.168 2010/07/01 06:29:32 jordan Exp $ */
+/* $OpenBSD: acpi.c,v 1.167 2010/07/01 01:39:39 jordan Exp $ */
/*
* Copyright (c) 2005 Thorsten Lockert <[email protected]>
* Copyright (c) 2005 Jordan Hargrave <[email protected]>
@@ -18,6 +18,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/buf.h>
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/fcntl.h>
@@ -41,6 +42,10 @@
#include <dev/acpi/dsdt.h>
#include <dev/wscons/wsdisplayvar.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+#include <dev/pci/ppbreg.h>
+
#include <dev/pci/pciidereg.h>
#include <dev/pci/pciidevar.h>
@@ -66,6 +71,8 @@ int acpi_saved_spl;
void acpi_isr_thread(void *);
void acpi_create_thread(void *);
+void acpi_pci_match(struct device *, struct pci_attach_args *);
+
int acpi_match(struct device *, void *, void *);
void acpi_attach(struct device *, struct device *, void *);
int acpi_submatch(struct device *, void *, void *);
@@ -94,12 +101,15 @@ int acpi_foundide(struct aml_node *node,
int acpiide_notify(struct aml_node *, int, void *);
int _acpi_matchhids(const char *, const char *[]);
+int acpi_matchhids(struct acpi_attach_args *aa, const char *hids[],
+ const char *driver);
+
+struct acpi_q *acpi_maptable(struct acpi_softc *, paddr_t, const char *,
+ const char *, const char *, int);
void wdcattach(struct channel_softc *);
int wdcdetach(struct channel_softc *, int);
-struct acpi_q *acpi_maptable(struct acpi_softc *, paddr_t, const char *, const
char *, const char *, int);
-
struct idechnl
{
struct acpi_softc *sc;
@@ -492,6 +502,150 @@ acpi_match(struct device *parent, void *
return (1);
}
+TAILQ_HEAD(, acpi_pci) acpi_pcidevs =
+ TAILQ_HEAD_INITIALIZER(acpi_pcidevs);
+
+int acpi_getpci(struct aml_node *node, void *arg);
+int acpi_getminbus(union acpi_resource *crs, void *arg);
+
+int
+acpi_getminbus(union acpi_resource *crs, void *arg)
+{
+ int *bbn = arg;
+ int typ = AML_CRSTYPE(crs);
+
+ /* Check for embedded bus number */
+ if (typ == LR_WORD && crs->lr_word.type == 2)
+ *bbn = crs->lr_word._min;
+ return 0;
+}
+
+int
+_acpi_matchhids(const char *hid, const char *hids[])
+{
+ int i;
+
+ for (i = 0; hids[i]; i++)
+ if (!strcmp(hid, hids[i]))
+ return (1);
+ return (0);
+}
+
+int
+acpi_matchhids(struct acpi_attach_args *aa, const char *hids[],
+ const char *driver)
+{
+
+ if (aa->aaa_dev == NULL || aa->aaa_node == NULL)
+ return (0);
+ if (_acpi_matchhids(aa->aaa_dev, hids)) {
+ dnprintf(5, "driver %s matches %s\n", driver, hids[i]);
+ return (1);
+ }
+ return (0);
+}
+
+/* Map ACPI device node to PCI */
+int
+acpi_getpci(struct aml_node *node, void *arg)
+{
+ const char *pcihid[] = { ACPI_DEV_PCIB, ACPI_DEV_PCIEB, "HWP0002", 0 };
+ struct acpi_pci *pci, *ppci;
+ struct aml_value res;
+ struct acpi_softc *sc = arg;
+ pci_chipset_tag_t pc = NULL;
+ pcitag_t tag;
+ uint64_t val;
+ uint32_t reg;
+
+ if (!node->value || node->value->type != AML_OBJTYPE_DEVICE)
+ return 0;
+ if (!aml_evalhid(node, &res)) {
+ /* Check if this is a PCI Root node */
+ if (_acpi_matchhids(res.v_string, pcihid)) {
+ aml_freevalue(&res);
+
+ pci = malloc(sizeof(*pci), M_DEVBUF, M_WAITOK|M_ZERO);
+
+ if (!aml_evalinteger(sc, node, "_SEG", 0, NULL, &val))
+ pci->seg = val;
+ if (!aml_evalinteger(sc, node, "_BBN", 0, NULL, &val))
+ pci->bus = val;
+ else if (!aml_evalname(sc, node, "_CRS", 0, NULL,
&res)) {
+ aml_parse_resource(res.length, res.v_buffer,
+ acpi_getminbus, &pci->bus);
+ }
+ pci->sub = pci->bus;
+ node->pci = pci;
+ printf("found PCI root: %s %d\n",
+ aml_nodename(node), pci->bus);
+ }
+ aml_freevalue(&res);
+ return 0;
+ }
+
+ /* If parent is not PCI, or device does not have _ADR, return */
+ if (!node->parent || (ppci = node->parent->pci) == NULL)
+ return 0;
+ if (aml_evalinteger(sc, node, "_ADR", 0, NULL, &val))
+ return 0;
+
+ pci = malloc(sizeof(*pci), M_DEVBUF, M_WAITOK|M_ZERO);
+ pci->bus = ppci->sub;
+ pci->dev = ACPI_ADR_PCIDEV(val);
+ pci->fun = ACPI_ADR_PCIFUN(val);
+ pci->node = node;
+ pci->sub = -1;
+
+ printf("%.2x:%.2x.%x -> %s\n",
+ pci->bus, pci->dev, pci->fun,
+ aml_nodename(node));
+
+ /* Check if PCI device exists */
+ tag = pci_make_tag(pc, pci->bus, pci->dev, pci->fun);
+ reg = pci_conf_read(pc, tag, PCI_ID_REG);
+ if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID) {
+ free(pci, M_DEVBUF);
+ return (1);
+ }
+ node->pci = pci;
+
+ TAILQ_INSERT_TAIL(&acpi_pcidevs, pci, next);
+
+ /* Check if this is a PCI bridge */
+ reg = pci_conf_read(pc, tag, PCI_CLASS_REG);
+ if (PCI_CLASS(reg) == PCI_CLASS_BRIDGE &&
+ PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_PCI) {
+ reg = pci_conf_read(pc, tag, PPB_REG_BUSINFO);
+ pci->sub = PPB_BUSINFO_SECONDARY(reg);
+
+ printf("found PCI bridge: %s %d\n",
+ aml_nodename(node), pci->sub);
+
+ /* Continue scanning */
+ return (0);
+ }
+
+ /* Device does not have children, stop scanning */
+ return (1);
+}
+
+void
+acpi_pci_match(struct device *dev, struct pci_attach_args *pa)
+{
+ struct acpi_pci *pdev;
+
+ TAILQ_FOREACH(pdev, &acpi_pcidevs, next) {
+ if (pdev->bus == pa->pa_bus &&
+ pdev->dev == pa->pa_device &&
+ pdev->fun == pa->pa_function) {
+ dnprintf(10,"%s at acpi0 %s\n",
+ dev->dv_xname, aml_nodename(pdev->node));
+ pdev->device = dev;
+ }
+ }
+}
+
void
acpi_attach(struct device *parent, struct device *self, void *aux)
{
@@ -709,6 +863,9 @@ acpi_attach(struct device *parent, struc
/* initialize runtime environment */
aml_find_node(&aml_root, "_INI", acpi_inidev, sc);
+ /* Get PCI mapping */
+ aml_walknodes(&aml_root, AML_WALK_PRE, acpi_getpci, sc);
+
/* attach pci interrupt routing tables */
aml_find_node(&aml_root, "_PRT", acpi_foundprt, sc);
@@ -2105,10 +2262,12 @@ acpi_prepare_sleep_state(struct acpi_sof
acpi_susp_resume_gpewalk(sc, state, 1);
fail:
+
#if NWSDISPLAY > 0
if (error)
wsdisplay_resume();
#endif /* NWSDISPLAY > 0 */
+
return (error);
}
@@ -2289,31 +2448,6 @@ acpi_foundec(struct aml_node *node, void
aml_freevalue(&res);
return 0;
-}
-
-int
-_acpi_matchhids(const char *hid, const char *hids[])
-{
- int i;
-
- for (i = 0; hids[i]; i++)
- if (!strcmp(hid, hids[i]))
- return (1);
- return (0);
-}
-
-int
-acpi_matchhids(struct acpi_attach_args *aa, const char *hids[],
- const char *driver)
-{
-
- if (aa->aaa_dev == NULL || aa->aaa_node == NULL)
- return (0);
- if (_acpi_matchhids(aa->aaa_dev, hids)) {
- dnprintf(5, "driver %s matches %s\n", driver, hids[i]);
- return (1);
- }
- return (0);
}
int
Index: acpiprt.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/acpiprt.c,v
retrieving revision 1.38
diff -u -p -u -p -b -r1.38 acpiprt.c
--- acpiprt.c 1 Jul 2010 06:29:32 -0000 1.38
+++ acpiprt.c 1 Jul 2010 06:56:15 -0000
@@ -101,11 +101,18 @@ acpiprt_attach(struct device *parent, st
struct acpiprt_softc *sc = (struct acpiprt_softc *)self;
struct acpi_attach_args *aa = aux;
struct aml_value res;
- int i;
+ int i, nbus;
sc->sc_acpi = (struct acpi_softc *)parent;
sc->sc_devnode = aa->aaa_node;
sc->sc_bus = acpiprt_getpcibus(sc, sc->sc_devnode);
+
+ nbus = (sc->sc_devnode->parent && sc->sc_devnode->parent->pci) ?
+ sc->sc_devnode->parent->pci->sub : -1;
+ if (nbus != sc->sc_bus) {
+ printf("bus mismatch: %d, %d\n", sc->sc_bus, nbus);
+ panic("Aiiee..");
+ }
printf(": bus %d (%s)", sc->sc_bus, sc->sc_devnode->parent->name);
Index: amltypes.h
===================================================================
RCS file: /cvs/src/sys/dev/acpi/amltypes.h,v
retrieving revision 1.36
diff -u -p -u -p -b -r1.36 amltypes.h
--- amltypes.h 1 Jul 2010 06:29:32 -0000 1.36
+++ amltypes.h 1 Jul 2010 06:56:15 -0000
@@ -1,4 +1,4 @@
-/* $OpenBSD: amltypes.h,v 1.36 2010/07/01 06:29:32 jordan Exp $ */
+/* $OpenBSD: amltypes.h,v 1.35 2010/06/29 22:08:29 jordan Exp $ */
/*
* Copyright (c) 2005 Jordan Hargrave <[email protected]>
*
@@ -347,6 +347,19 @@ struct aml_value {
#define aml_pkglen(v) ((v)->length)
#define aml_pkgval(v,i) (&(v)->v_package[(i)])
+struct acpi_pci {
+ TAILQ_ENTRY(acpi_pci) next;
+
+ struct aml_node *node;
+ struct device *device;
+
+ int sub;
+ int seg;
+ int bus;
+ int dev;
+ int fun;
+};
+
struct aml_node {
struct aml_node *parent;
struct aml_node *child;
@@ -356,12 +369,9 @@ struct aml_node {
u_int16_t opcode;
u_int8_t *start;
u_int8_t *end;
- // const char *name;
- // const char *mnem;
struct aml_value *value;
-
- int depth;
+ struct acpi_pci *pci;
};
#define aml_bitmask(n) (1L << ((n) & 0x7))
Index: dsdt.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/dsdt.c,v
retrieving revision 1.164
diff -u -p -u -p -b -r1.164 dsdt.c
--- dsdt.c 1 Jul 2010 06:29:32 -0000 1.164
+++ dsdt.c 1 Jul 2010 06:56:15 -0000
@@ -1233,7 +1233,8 @@ aml_walknodes(struct aml_node *node, int
if (node == NULL)
return;
if (mode == AML_WALK_PRE)
- nodecb(node, arg);
+ if (nodecb(node, arg))
+ return;
for (child = node->child; child; child = child->sibling)
aml_walknodes(child, mode, nodecb, arg);
if (mode == AML_WALK_POST)