Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/acpi/acpica AcpiOsDerivePciId: make sure that we onl...
details: https://anonhg.NetBSD.org/src/rev/5eef9d0b79b4
branches: trunk
changeset: 756287:5eef9d0b79b4
user: gsutre <gsutre%NetBSD.org@localhost>
date: Sat Jul 10 21:31:00 2010 +0000
description:
AcpiOsDerivePciId: make sure that we only update the PCI bus number,
and that we do so only if it was succesfully derived.
ok jruoho@, kochi@
diffstat:
sys/dev/acpi/acpica/OsdHardware.c | 139 +++++++++++++++++++++++++------------
1 files changed, 92 insertions(+), 47 deletions(-)
diffs (187 lines):
diff -r 86001369faab -r 5eef9d0b79b4 sys/dev/acpi/acpica/OsdHardware.c
--- a/sys/dev/acpi/acpica/OsdHardware.c Sat Jul 10 19:37:38 2010 +0000
+++ b/sys/dev/acpi/acpica/OsdHardware.c Sat Jul 10 21:31:00 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: OsdHardware.c,v 1.5 2009/09/15 19:41:30 drochner Exp $ */
+/* $NetBSD: OsdHardware.c,v 1.6 2010/07/10 21:31:00 gsutre Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@@ -44,13 +44,14 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: OsdHardware.c,v 1.5 2009/09/15 19:41:30 drochner Exp $");
+__KERNEL_RCSID(0, "$NetBSD: OsdHardware.c,v 1.6 2010/07/10 21:31:00 gsutre Exp $");
#include <sys/param.h>
#include <sys/device.h>
#include <dev/acpi/acpica.h>
#include <dev/acpi/acpivar.h>
+#include <dev/acpi/acpi_pci.h>
#include <machine/acpi_machdep.h>
@@ -276,66 +277,99 @@
return AE_OK;
}
-/* get PCI bus# from root bridge recursively */
-static int
-get_bus_number(
- ACPI_HANDLE rhandle,
- ACPI_HANDLE chandle,
- ACPI_PCI_ID **PciId)
+/*
+ * acpi_os_derive_pciid_rec:
+ *
+ * Helper function for AcpiOsDerivePciId. The parameters are:
+ * - chandle: a handle to the node whose PCI id shall be derived.
+ * - rhandle: a handle the PCI root bridge upstream of chandle.
+ * - pciid: where the derived PCI id is returned.
+ *
+ * This function assumes that rhandle is a proper ancestor of chandle,
+ * and that pciid has already been filled by ACPICA:
+ * - segment# and bus# obtained from _SEG and _BBN on rhandle,
+ * - device# and function# obtained from _ADR on the ACPI device node
+ * whose scope chandle is in).
+ */
+static ACPI_STATUS
+acpi_os_derive_pciid_rec(ACPI_HANDLE chandle, ACPI_HANDLE rhandle, ACPI_PCI_ID *pciid)
{
- ACPI_HANDLE handle;
+ ACPI_HANDLE phandle;
+ ACPI_INTEGER address;
+ ACPI_OBJECT_TYPE objtype;
ACPI_STATUS rv;
- ACPI_OBJECT_TYPE type;
- ACPI_PCI_ID *id;
- ACPI_INTEGER v;
- int bus;
+ uint16_t valb;
- id = *PciId;
-
- rv = AcpiGetParent(chandle, &handle);
- if (ACPI_FAILURE(rv))
- return 0;
+ KASSERT(chandle != rhandle);
/*
- * When handle == rhandle, we have valid PciId->Bus
- * which was obtained from _BBN in evrgnini.c
- * so we don't have to reevaluate _BBN.
+ * Get parent device node. This is should not fail since chandle has
+ * at least one ancestor that is a device node: rhandle.
*/
- if (handle != rhandle) {
- bus = get_bus_number(rhandle, handle, PciId);
+ phandle = chandle;
+ do {
+ rv = AcpiGetParent(phandle, &phandle);
+ if (ACPI_FAILURE(rv))
+ return rv;
+ rv = AcpiGetType(phandle, &objtype);
+ if (ACPI_FAILURE(rv))
+ return rv;
+ }
+ while (objtype != ACPI_TYPE_DEVICE);
- rv = AcpiGetType(handle, &type);
- if (ACPI_FAILURE(rv) || type != ACPI_TYPE_DEVICE)
- return bus;
+ /*
+ * If the parent is rhandle then we have nothing to do since ACPICA
+ * has pre-filled the PCI id to the best it could.
+ */
+ if (phandle == rhandle)
+ return AE_OK;
- rv = acpi_eval_integer(handle, METHOD_NAME__ADR, &v);
-
- if (ACPI_FAILURE(rv))
- return bus;
+ /* Recursive call to get PCI id of the parent */
+ rv = acpi_os_derive_pciid_rec(phandle, rhandle, pciid);
+ if (ACPI_FAILURE(rv))
+ return rv;
- id->Bus = bus;
- id->Device = ACPI_HIWORD((ACPI_INTEGER)v);
- id->Function = ACPI_LOWORD((ACPI_INTEGER)v);
+ /*
+ * If this is not an ACPI device, return the PCI id of its parent.
+ */
+ rv = AcpiGetType(chandle, &objtype);
+ if (ACPI_FAILURE(rv))
+ return rv;
+ if (objtype != ACPI_TYPE_DEVICE)
+ return AE_OK;
- /* read HDR_TYPE register */
- rv = AcpiOsReadPciConfiguration(id, 0x0e, &v, 8);
- if (ACPI_SUCCESS(rv) &&
- /* mask multifunction bit & check bridge type */
- ((v & 0x7f) == 1 || (v & 0x7f) == 2)) {
- /* read SECONDARY_BUS register */
- rv = AcpiOsReadPciConfiguration(id, 0x19, &v, 8);
- if (ACPI_SUCCESS(rv))
- id->Bus = v;
- }
- }
+ /*
+ * This is an ACPI device node. Its parent device node is not a PCI
+ * root bridge. Check that it is a PCI-to-PCI bridge and get its
+ * secondary bus#.
+ */
+ rv = acpi_pcidev_ppb_downbus(pciid->Segment, pciid->Bus, pciid->Device,
+ pciid->Function, &valb);
+ if (ACPI_FAILURE(rv))
+ return rv;
- return id->Bus;
+ /* Get address (contains dev# and fun# for PCI devices). */
+ rv = acpi_eval_integer(chandle, METHOD_NAME__ADR, &address);
+ if (ACPI_FAILURE(rv))
+ return rv;
+
+ pciid->Bus = valb;
+ pciid->Device = ACPI_HIWORD(ACPI_LODWORD(address));
+ pciid->Function = ACPI_LOWORD(ACPI_LODWORD(address));
+ return AE_OK;
}
/*
* AcpiOsDerivePciId:
*
- * Derive correct PCI bus# by traversing bridges
+ * Derive correct PCI bus# by traversing bridges.
+ *
+ * In ACPICA release 20100331 (as well as older versions), the interface
+ * of this function is not correctly documented in the ACPICA programmer
+ * reference. The correct interface parameters to this function are:
+ * - rhandle: a handle the PCI root bridge upstream of handle.
+ * - chandle: a handle to the PCI_Config operation region.
+ * - PciId: where the derived PCI id is returned.
*/
void
AcpiOsDerivePciId(
@@ -343,5 +377,16 @@
ACPI_HANDLE chandle,
ACPI_PCI_ID **PciId)
{
- (*PciId)->Bus = get_bus_number(rhandle, chandle, PciId);
+ ACPI_PCI_ID pciid;
+ ACPI_STATUS rv;
+
+ if (chandle == rhandle)
+ return;
+
+ pciid = **PciId;
+ rv = acpi_os_derive_pciid_rec(chandle, rhandle, &pciid);
+ if (ACPI_FAILURE(rv))
+ return;
+
+ (*PciId)->Bus = pciid.Bus;
}
Home |
Main Index |
Thread Index |
Old Index