Module Name:    src
Committed By:   jruoho
Date:           Thu Apr 22 14:50:31 UTC 2010

Modified Files:
        src/sys/dev/acpi: acpi.c acpi_pci.c acpi_pci.h acpivar.h

Log Message:
>From Gregoire Sutre: rework the ACPI PCI support. This makes ACPI to
correctly pick PCI segment groups, PCI bus numbers, PCI root bridges,
PCI-to-PCI bridges, and PCI devices, among other things. In short: it is
more robust than the old code or anything in sys/arch/x86/x86/mpacpi.c.

ok cegger@, jmcneill@


To generate a diff of this commit:
cvs rdiff -u -r1.179 -r1.180 src/sys/dev/acpi/acpi.c
cvs rdiff -u -r1.5 -r1.6 src/sys/dev/acpi/acpi_pci.c
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/acpi/acpi_pci.h
cvs rdiff -u -r1.49 -r1.50 src/sys/dev/acpi/acpivar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/acpi/acpi.c
diff -u src/sys/dev/acpi/acpi.c:1.179 src/sys/dev/acpi/acpi.c:1.180
--- src/sys/dev/acpi/acpi.c:1.179	Tue Apr 20 04:57:04 2010
+++ src/sys/dev/acpi/acpi.c	Thu Apr 22 14:50:30 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: acpi.c,v 1.179 2010/04/20 04:57:04 jruoho Exp $	*/
+/*	$NetBSD: acpi.c,v 1.180 2010/04/22 14:50:30 jruoho Exp $	*/
 
 /*-
  * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc.
@@ -65,7 +65,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.179 2010/04/20 04:57:04 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.180 2010/04/22 14:50:30 jruoho Exp $");
 
 #include "opt_acpi.h"
 #include "opt_pcifixup.h"
@@ -662,6 +662,7 @@
 
 		ad->ad_device = NULL;
 		ad->ad_notify = NULL;
+		ad->ad_pciinfo = NULL;
 
 		ad->ad_type = type;
 		ad->ad_handle = handle;

Index: src/sys/dev/acpi/acpi_pci.c
diff -u src/sys/dev/acpi/acpi_pci.c:1.5 src/sys/dev/acpi/acpi_pci.c:1.6
--- src/sys/dev/acpi/acpi_pci.c:1.5	Sun Apr 18 14:05:26 2010
+++ src/sys/dev/acpi/acpi_pci.c	Thu Apr 22 14:50:31 2010
@@ -1,11 +1,11 @@
-/* $NetBSD: acpi_pci.c,v 1.5 2010/04/18 14:05:26 jruoho Exp $ */
+/* $NetBSD: acpi_pci.c,v 1.6 2010/04/22 14:50:31 jruoho Exp $ */
 
 /*
- * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
- * by Christoph Egger.
+ * by Christoph Egger and Gregoire Sutre.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,147 +33,287 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_pci.c,v 1.5 2010/04/18 14:05:26 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_pci.c,v 1.6 2010/04/22 14:50:31 jruoho Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
 #include <sys/kmem.h>
-#include <sys/queue.h>
 #include <sys/systm.h>
 
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcidevs.h>
+#include <dev/pci/ppbreg.h>
+
 #include <dev/acpi/acpireg.h>
 #include <dev/acpi/acpivar.h>
 #include <dev/acpi/acpi_pci.h>
 
-struct acpi_pcidev;
+#define _COMPONENT	ACPI_BUS_COMPONENT
+ACPI_MODULE_NAME	("acpi_pci")
+
+static ACPI_STATUS	acpi_pcidev_pciroot_bus(ACPI_HANDLE, uint16_t *);
+static ACPI_STATUS	acpi_pcidev_pciroot_bus_callback(ACPI_RESOURCE *,
+			    void *);
+static ACPI_STATUS	acpi_pcidev_scan_rec(struct acpi_devnode *);
 
-static TAILQ_HEAD(, acpi_pcidev) acpi_pcidevlist =
-    TAILQ_HEAD_INITIALIZER(acpi_pcidevlist);
 
-struct acpi_pcidev {
-	struct acpi_devnode *ap_node;
-	uint32_t ap_pciseg;
-	uint32_t ap_pcibus;
-	uint32_t ap_pcidev;
-	uint32_t ap_pcifunc;
-	bool ap_pcihost;
-	TAILQ_ENTRY(acpi_pcidev) ap_list;
-};
-
-
-static const char * const acpi_pcidev_ids[] = {
-	"PNP0A??",	/* ACPI PCI host controllers */
-	NULL
-};
+/*
+ * Regarding PCI Segment Groups, the ACPI spec says (cf. ACPI 4.0, p. 277):
+ *
+ * "The optional _SEG object is located under a PCI host bridge and
+ * evaluates to an integer that describes the PCI Segment Group (see PCI
+ * Firmware Specification v3.0)."
+ *
+ * "PCI Segment Group supports more than 256 buses in a system by allowing
+ * the reuse of the PCI bus numbers.  Within each PCI Segment Group, the bus
+ * numbers for the PCI buses must be unique. PCI buses in different PCI
+ * Segment Group are permitted to have the same bus number."
+ *
+ * "If _SEG does not exist, OSPM assumes that all PCI bus segments are in
+ * PCI Segment Group 0."
+ *
+ * "The lower 16 bits of _SEG returned integer is the PCI Segment Group
+ * number.  Other bits are reserved."
+ */
 
-static bool
-acpi_pcidev_add(struct acpi_softc *sc, struct acpi_devnode *ad)
+/*
+ * Regarding PCI Base Bus Numbers, the ACPI spec says (cf. ACPI 4.0, p. 277):
+ *
+ * "For multi-root PCI platforms, the _BBN object evaluates to the PCI bus
+ * number that the BIOS assigns.  This is needed to access a PCI_Config
+ * operation region for the specified bus.  The _BBN object is located under
+ * a PCI host bridge and must be unique for every host bridge within a
+ * segment since it is the PCI bus number."
+ *
+ * Moreover, the ACPI FAQ (http://www.acpi.info/acpi_faq.htm) says:
+ *
+ * "For a multiple root bus machine, _BBN is required for each bus.  _BBN
+ * should provide the bus number assigned to this bus by the BIOS at boot
+ * time."
+ */
+
+
+/*
+ * acpi_pcidev_pciroot_bus:
+ *
+ *	Derive the PCI bus number of a PCI root bridge from its resources.
+ *	If successful, return AE_OK and fill *busp.  Otherwise, return an
+ *	exception code and leave *busp unchanged.
+ *
+ * XXX	Use ACPI resource parsing functions (acpi_resource.c) once bus number
+ *	ranges are implemented there.
+ */
+static ACPI_STATUS
+acpi_pcidev_pciroot_bus(ACPI_HANDLE handle, uint16_t *busp)
 {
-	struct acpi_pcidev *ap;
 	ACPI_STATUS rv;
-	ACPI_INTEGER seg, bus, addr;
+	int32_t bus;
+
+	bus = -1;
+	rv = AcpiWalkResources(handle, METHOD_NAME__CRS,
+	    acpi_pcidev_pciroot_bus_callback, &bus);
 
-	/*
-	 * ACPI spec: "The _BBN object is located under a
-	 * PCI host bridge and must be unique for every
-	 * host bridge within a segment since it is the PCI bus number."
-	 */
-	rv = acpi_eval_integer(ad->ad_handle, "_BBN", &bus);
-	if (ACPI_FAILURE(rv))
-		return false;
-	/*
-         * The ACPI address (_ADR) is equal to: (device << 16) | function.
-	 */
-	rv = acpi_eval_integer(ad->ad_handle, "_ADR", &addr);
 	if (ACPI_FAILURE(rv))
-		return false;
+		return rv;
 
-	/*
-	 * ACPI spec: "The optional _SEG object is located under a PCI host
-	 * bridge and evaluates to an integer that describes the
-	 * PCI Segment Group (see PCI Firmware Specification v3.0)."
-	 *
-	 * "PCI Segment Group supports more than 256 buses
-	 * in a system by allowing the reuse of the PCI bus numbers.
-	 * Within each PCI Segment Group, the bus numbers for the PCI
-	 * buses must be unique. PCI buses in different PCI Segment
-	 * Group are permitted to have the same bus number."
-	 */
-	rv = acpi_eval_integer(ad->ad_handle, "_SEG", &seg);
-	if (ACPI_FAILURE(rv)) {
-		/*
-		 * ACPI spec: "If _SEG does not exist, OSPM assumes that all
-		 * PCI bus segments are in PCI Segment Group 0."
-		 */
-		seg = 0;
-	}
+	if (bus < 0 || bus > 0xFFFF)
+		return AE_NOT_EXIST;
 
-	ap = kmem_alloc(sizeof(*ap), KM_SLEEP);
-	if (ap == NULL) {
-		aprint_error("%s: kmem_alloc failed\n", __func__);
-		return false;
-	}
+	*busp = (uint16_t)bus;
+	return rv;
+}
 
-	if (acpi_match_hid(ad->ad_devinfo, acpi_pcidev_ids))
-		ap->ap_pcihost = true;
-	else
-		ap->ap_pcihost = false;
+static ACPI_STATUS
+acpi_pcidev_pciroot_bus_callback(ACPI_RESOURCE *res, void *context)
+{
+	int32_t *bus = context;
+	ACPI_RESOURCE_ADDRESS64 addr64;
 
-	ap->ap_node = ad;
-	ap->ap_pciseg = seg;
-	ap->ap_pcibus = bus;
-	ap->ap_pcidev = addr >> 16;
-	ap->ap_pcifunc = addr & 0xffff;
+	if ((res->Type != ACPI_RESOURCE_TYPE_ADDRESS16) &&
+	    (res->Type != ACPI_RESOURCE_TYPE_ADDRESS32) &&
+	    (res->Type != ACPI_RESOURCE_TYPE_ADDRESS64))
+		return AE_OK;	/* continue the walk */
 
-	TAILQ_INSERT_TAIL(&acpi_pcidevlist, ap, ap_list);
+	if (ACPI_FAILURE(AcpiResourceToAddress64(res, &addr64)))
+		return AE_OK;	/* continue the walk */
 
-	return true;
-}
+	if (addr64.ResourceType != ACPI_BUS_NUMBER_RANGE)
+		return AE_OK;	/* continue the walk */
 
-static void
-acpi_pcidev_print(struct acpi_pcidev *ap)
-{
-	aprint_debug(" %s", ap->ap_node->ad_name);
+	if (*bus != -1)
+		return AE_ALREADY_EXISTS;
+
+	*bus = addr64.Minimum;
+	return AE_OK;		/* continue the walk */
 }
 
-int
-acpi_pcidev_scan(struct acpi_softc *sc)
+/*
+ * acpi_pcidev_scan_rec:
+ *
+ *	Scan the ACPI device tree for PCI devices.  A node is detected as a
+ *	PCI device if it has an ancestor that is a PCI root bridge and such
+ *	that all intermediate nodes are PCI-to-PCI bridges.  Depth-first
+ *	recursive implementation.
+ */
+static ACPI_STATUS
+acpi_pcidev_scan_rec(struct acpi_devnode *ad)
 {
-	struct acpi_devnode *ad;
-	struct acpi_pcidev *ap;
-	ACPI_DEVICE_INFO *di;
-	int count = 0;
+	struct acpi_devnode *child;
+	struct acpi_pci_info *ap;
+	ACPI_INTEGER val;
+	ACPI_STATUS rv;
 
-#define ACPI_STA_DEV_VALID      \
-	(ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|ACPI_STA_DEV_OK)
+	if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE ||
+	    !(ad->ad_devinfo->Valid & ACPI_VALID_ADR)) {
+		ad->ad_pciinfo = NULL;
+		goto rec;
+	}
 
-	SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
+	if (ad->ad_devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) {
+		ap = kmem_zalloc(sizeof(*ap), KM_SLEEP);
+		if (ap == NULL)
+			return AE_NO_MEMORY;
+
+		rv = acpi_eval_integer(ad->ad_handle, METHOD_NAME__SEG, &val);
+		if (ACPI_SUCCESS(rv))
+			ap->ap_segment = ACPI_LOWORD(val);
+		else
+			ap->ap_segment = 0;
+
+		/* try to get bus number using _CRS first */
+		rv = acpi_pcidev_pciroot_bus(ad->ad_handle, &ap->ap_bus);
+		if (ACPI_FAILURE(rv)) {
+			rv = acpi_eval_integer(ad->ad_handle, METHOD_NAME__BBN, &val);
+			if (ACPI_SUCCESS(rv))
+				ap->ap_bus = ACPI_LOWORD(val);
+			else
+				ap->ap_bus = 0;
+		}
+
+		ap->ap_device = ACPI_HIWORD(ACPI_LODWORD(ad->ad_devinfo->Address));
+		ap->ap_function = ACPI_LOWORD(ACPI_LODWORD(ad->ad_devinfo->Address));
 
-		di = ad->ad_devinfo;
+		ap->ap_bridge = true;
+		ap->ap_downbus = ap->ap_bus;
+
+		ad->ad_pciinfo = ap;
+		goto rec;
+	}
 
-		if (di->Type != ACPI_TYPE_DEVICE)
-			continue;
+	if ((ad->ad_parent != NULL) &&
+	    (ad->ad_parent->ad_pciinfo != NULL) &&
+	    (ad->ad_parent->ad_pciinfo->ap_bridge)) {
+		/*
+		 * Our parent is a PCI root bridge or a PCI-to-PCI bridge.  We
+		 * have the same PCI segment#, and our bus# is its downstream
+		 * bus number.
+		 */
+		ap = kmem_zalloc(sizeof(*ap), KM_SLEEP);
+		if (ap == NULL)
+			return AE_NO_MEMORY;
+
+		ap->ap_segment = ad->ad_parent->ad_pciinfo->ap_segment;
+		ap->ap_bus = ad->ad_parent->ad_pciinfo->ap_downbus;
+		ap->ap_device = ACPI_HIWORD(ACPI_LODWORD(ad->ad_devinfo->Address));
+		ap->ap_function = ACPI_LOWORD(ACPI_LODWORD(ad->ad_devinfo->Address));
 
-		if ((di->Valid & ACPI_VALID_STA) != 0 &&
-		    (di->CurrentStatus & ACPI_STA_DEV_VALID) !=
-		     ACPI_STA_DEV_VALID)
-			continue;
+		/*
+		 * Check whether this device is a PCI-to-PCI bridge and get its
+		 * secondary bus#.
+		 */
+		rv = acpi_pcidev_ppb_downbus(ap->ap_segment, ap->ap_bus,
+		    ap->ap_device, ap->ap_function, &ap->ap_downbus);
+		if (ACPI_SUCCESS(rv))
+			ap->ap_bridge = true;
+		else
+			ap->ap_bridge = false;
 
-		if (acpi_pcidev_add(sc, ad) == true)
-			++count;
+		ad->ad_pciinfo = ap;
+		goto rec;
+	}
+ rec:
+	SIMPLEQ_FOREACH(child, &ad->ad_child_head, ad_child_list) {
+		rv = acpi_pcidev_scan_rec(child);
+		if (ACPI_FAILURE(rv))
+			return rv;
 	}
 
-#undef ACPI_STA_DEV_VALID
+	return AE_OK;
+}
 
-	if (count == 0)
-		return 0;
+/*
+ * acpi_pcidev_ppb_downbus:
+ *
+ *	Retrieve the secondary bus number of the PCI-to-PCI bridge having the
+ *	given PCI id.  If successful, return AE_OK and fill *busp.  Otherwise,
+ *	return an exception code and leave *busp unchanged.
+ *
+ * XXX	Need to deal with PCI segment groups (see also acpica/OsdHardware.c).
+ */
+ACPI_STATUS
+acpi_pcidev_ppb_downbus(uint16_t segment, uint16_t bus, uint16_t device,
+    uint16_t function, uint16_t *downbus)
+{
+	struct acpi_softc *sc = acpi_softc;
+	pci_chipset_tag_t pc;
+	pcitag_t tag;
+	pcireg_t val;
 
+	if (bus > 255 || device > 31 || function > 7)
+		return AE_BAD_PARAMETER;
+
+	if (sc == NULL)
+		pc = NULL;
+	else
+		pc = sc->sc_pc;
+
+	tag = pci_make_tag(pc, bus, device, function);
+
+	/* Check that this device exists. */
+	val = pci_conf_read(pc, tag, PCI_ID_REG);
+	if (PCI_VENDOR(val) == PCI_VENDOR_INVALID ||
+	    PCI_VENDOR(val) == 0)
+		return AE_NOT_EXIST;
+
+	/* Check that this device is a PCI-to-PCI bridge. */
+	val = pci_conf_read(pc, tag, PCI_BHLC_REG);
+	if (PCI_HDRTYPE_TYPE(val) != PCI_HDRTYPE_PPB)
+		return AE_TYPE;
+
+	/* This is a PCI-to-PCI bridge.  Get its secondary bus#. */
+	val = pci_conf_read(pc, tag, PPB_REG_BUSINFO);
+	*downbus = PPB_BUSINFO_SECONDARY(val);
+	return AE_OK;
+}
+
+static void
+acpi_pcidev_print(struct acpi_devnode *ad)
+{
+	aprint_debug(" ");
+	if (ad->ad_devinfo->Flags & ACPI_PCI_ROOT_BRIDGE)
+		aprint_debug("*");
+	aprint_debug("%...@%"PRIx16":%"PRIx16":%"PRIx16":%"PRIx16,
+	    ad->ad_name,
+	    ad->ad_pciinfo->ap_segment,
+	    ad->ad_pciinfo->ap_bus,
+	    ad->ad_pciinfo->ap_device,
+	    ad->ad_pciinfo->ap_function);
+	if (ad->ad_pciinfo->ap_bridge)
+		aprint_debug(">%"PRIx16, ad->ad_pciinfo->ap_downbus);
+}
+
+void
+acpi_pcidev_scan(struct acpi_softc *sc)
+{
+	struct acpi_devnode *ad;
+
+	acpi_pcidev_scan_rec(sc->sc_root);
 	aprint_debug_dev(sc->sc_dev, "pci devices:");
-	TAILQ_FOREACH(ap, &acpi_pcidevlist, ap_list)
-		acpi_pcidev_print(ap);
+	SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
+		if (ad->ad_pciinfo != NULL)
+			acpi_pcidev_print(ad);
+	}
 	aprint_debug("\n");
-
-	return count;
 }
 
 /*
@@ -185,27 +325,24 @@
  *      - AE_OK if one and only one such device was found.
  */
 ACPI_STATUS
-acpi_pcidev_find(u_int segment, u_int bus, u_int device, u_int function,
-    ACPI_HANDLE *handlep)
+acpi_pcidev_find(uint16_t segment, uint16_t bus, uint16_t device,
+    uint16_t function, struct acpi_devnode **devnodep)
 {
-	struct acpi_pcidev *ap;
-	ACPI_HANDLE hdl;
+	struct acpi_softc *sc = acpi_softc;
+	struct acpi_devnode *ad;
 
-	hdl = NULL;
-	TAILQ_FOREACH(ap, &acpi_pcidevlist, ap_list) {
-		if (ap->ap_pciseg != segment)
-			continue;
-		if (ap->ap_pcibus != bus)
-			continue;
-		if (ap->ap_pcidev != device)
-			continue;
-		if (ap->ap_pcifunc != function)
-			continue;
+	if (sc == NULL)
+		return AE_NOT_FOUND;
 
-		hdl = ap->ap_node->ad_handle;
-		break;
+	SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
+		if ((ad->ad_pciinfo != NULL) &&
+		    (ad->ad_pciinfo->ap_segment == segment) &&
+		    (ad->ad_pciinfo->ap_bus == bus) &&
+		    (ad->ad_pciinfo->ap_device == device) &&
+		    (ad->ad_pciinfo->ap_function == function)) {
+			*devnodep = ad;
+			return AE_OK;
+		}
 	}
-
-	*handlep = hdl;
-	return (hdl != NULL) ? AE_OK : AE_NOT_FOUND;
+	return AE_NOT_FOUND;
 }

Index: src/sys/dev/acpi/acpi_pci.h
diff -u src/sys/dev/acpi/acpi_pci.h:1.3 src/sys/dev/acpi/acpi_pci.h:1.4
--- src/sys/dev/acpi/acpi_pci.h:1.3	Fri Mar  5 08:30:48 2010
+++ src/sys/dev/acpi/acpi_pci.h	Thu Apr 22 14:50:31 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_pci.h,v 1.3 2010/03/05 08:30:48 jruoho Exp $ */
+/* $NetBSD: acpi_pci.h,v 1.4 2010/04/22 14:50:31 jruoho Exp $ */
 
 /*
  * Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -31,7 +31,10 @@
 #ifndef _SYS_DEV_ACPI_ACPI_PCI_H
 #define _SYS_DEV_ACPI_ACPI_PCI_H
 
-int		acpi_pcidev_scan(struct acpi_softc *);
-ACPI_STATUS	acpi_pcidev_find(u_int, u_int, u_int, u_int, ACPI_HANDLE *);
+void		acpi_pcidev_scan(struct acpi_softc *);
+ACPI_STATUS	acpi_pcidev_find(uint16_t, uint16_t, uint16_t, uint16_t,
+		    struct acpi_devnode **);
+ACPI_STATUS	acpi_pcidev_ppb_downbus(uint16_t, uint16_t, uint16_t, uint16_t,
+		    uint16_t *);
 
 #endif	/* !_SYS_DEV_ACPI_ACPI_PCI_H */

Index: src/sys/dev/acpi/acpivar.h
diff -u src/sys/dev/acpi/acpivar.h:1.49 src/sys/dev/acpi/acpivar.h:1.50
--- src/sys/dev/acpi/acpivar.h:1.49	Sun Apr 18 14:05:26 2010
+++ src/sys/dev/acpi/acpivar.h	Thu Apr 22 14:50:31 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: acpivar.h,v 1.49 2010/04/18 14:05:26 jruoho Exp $	*/
+/*	$NetBSD: acpivar.h,v 1.50 2010/04/22 14:50:31 jruoho Exp $	*/
 
 /*
  * Copyright 2001 Wasabi Systems, Inc.
@@ -71,12 +71,33 @@
 #define ACPI_DEVICE_WAKEUP		__BIT(1)
 
 /*
+ * PCI information for ACPI device nodes that correspond to PCI devices.
+ */
+struct acpi_pci_info {
+	uint16_t		 ap_segment;	/* PCI segment group */
+	uint16_t		 ap_bus;	/* PCI bus */
+	uint16_t		 ap_device;	/* PCI device */
+	uint16_t		 ap_function;	/* PCI function */
+	bool			 ap_bridge;	/* PCI bridge (PHB or PPB) */
+	uint16_t		 ap_downbus;	/* PCI bridge downstream bus */
+};
+
+/*
  * An ACPI device node.
+ *
+ * Remarks:
+ *
+ *	ad_root		never NULL
+ *	ad_parent	only NULL if the root of the tree ("\").
+ *	ad_device	NULL if no device has attached to the node
+ *	ad_pciinfo	NULL if not a PCI device
+ *	ad_notify	NULL if there is no notify handler
  */
 struct acpi_devnode {
 	device_t		 ad_device;	/* Device */
 	device_t		 ad_root;	/* Backpointer to acpi_softc */
 	struct acpi_devnode	*ad_parent;	/* Backpointer to parent */
+	struct acpi_pci_info	*ad_pciinfo;	/* PCI info */
 	ACPI_NOTIFY_HANDLER	 ad_notify;	/* Device notify */
 	ACPI_DEVICE_INFO	*ad_devinfo;	/* Device info */
 	ACPI_HANDLE		 ad_handle;	/* Device handle */
@@ -85,7 +106,6 @@
 	uint32_t		 ad_type;	/* Device type */
 	int			 ad_wake;	/* Device wakeup */
 
-
 	SIMPLEQ_ENTRY(acpi_devnode)	ad_list;
 	SIMPLEQ_ENTRY(acpi_devnode)	ad_child_list;
 	SIMPLEQ_HEAD(, acpi_devnode)	ad_child_head;

Reply via email to