summaryrefslogtreecommitdiff
path: root/sys/dev/acpi
diff options
context:
space:
mode:
authorkochi <kochi@NetBSD.org>2003-07-02 11:45:08 +0000
committerkochi <kochi@NetBSD.org>2003-07-02 11:45:08 +0000
commit68dae3c110313cbb1ea4ef763745dbf5f0529e7b (patch)
tree0d280ac6b0adf24bb6db34de2f904f200a39c7a1 /sys/dev/acpi
parent8a805886270b35d16c63aaf80f91c4b0ca419f99 (diff)
Implement AcpiOsDerivePciId
Diffstat (limited to 'sys/dev/acpi')
-rw-r--r--sys/dev/acpi/acpica/Osd/OsdHardware.c64
1 files changed, 60 insertions, 4 deletions
diff --git a/sys/dev/acpi/acpica/Osd/OsdHardware.c b/sys/dev/acpi/acpica/Osd/OsdHardware.c
index 7f9f7847785..6c5db815f8c 100644
--- a/sys/dev/acpi/acpica/Osd/OsdHardware.c
+++ b/sys/dev/acpi/acpica/Osd/OsdHardware.c
@@ -1,4 +1,4 @@
-/* $NetBSD: OsdHardware.c,v 1.4 2002/12/23 00:22:05 kanaoka Exp $ */
+/* $NetBSD: OsdHardware.c,v 1.5 2003/07/02 11:45:08 kochi Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@@ -44,7 +44,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: OsdHardware.c,v 1.4 2002/12/23 00:22:05 kanaoka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: OsdHardware.c,v 1.5 2003/07/02 11:45:08 kochi Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -274,10 +274,66 @@ AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register,
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_HANDLE handle;
+ ACPI_STATUS rv;
+ ACPI_OBJECT_TYPE type;
+ ACPI_PCI_ID *id;
+ int v;
+ int bus;
+
+ id = *PciId;
+
+ rv = AcpiGetParent(chandle, &handle);
+ if (ACPI_FAILURE(rv))
+ return (0);
+
+ /*
+ * When handle == rhandle, we have valid PciId->Bus
+ * which was obtained from _BBN in evrgnini.c
+ * so we don't have to reevaluate _BBN.
+ */
+ if (handle != rhandle) {
+ bus = get_bus_number(rhandle, handle, PciId);
+
+ rv = AcpiGetType(handle, &type);
+ if (ACPI_FAILURE(rv) || type != ACPI_TYPE_DEVICE)
+ return (bus);
+
+ rv = acpi_eval_integer(handle, METHOD_NAME__ADR, &v);
+
+ if (ACPI_FAILURE(rv))
+ return (bus);
+
+ id->Bus = bus;
+ id->Device = ACPI_HIWORD((ACPI_INTEGER)v);
+ id->Function = ACPI_LOWORD((ACPI_INTEGER)v);
+
+ /* 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;
+ }
+ }
+
+ return (id->Bus);
+}
+
/*
* AcpiOsDerivePciId:
*
- * Interim function needed for PCI IRQ routing.
+ * Derive correct PCI bus# by traversing bridges
*/
void
AcpiOsDerivePciId(
@@ -285,5 +341,5 @@ AcpiOsDerivePciId(
ACPI_HANDLE chandle,
ACPI_PCI_ID **PciId)
{
- /* XXX TBD */
+ (*PciId)->Bus = get_bus_number(rhandle, chandle, PciId);
}