6818129 Solaris support for _OSC AER method (Nehalem IO FMA)
authorKrishna Elango <Krishna.Elango@Sun.COM>
Fri, 24 Apr 2009 13:17:47 -0700
changeset 9455 fadda1ef5322
parent 9454 02e1ddcc9be7
child 9456 9e30d38a8200
6818129 Solaris support for _OSC AER method (Nehalem IO FMA)
usr/src/uts/common/Makefile.files
usr/src/uts/common/io/pcie.c
usr/src/uts/common/sys/pcie_impl.h
usr/src/uts/i86pc/Makefile.files
usr/src/uts/i86pc/pcie/Makefile
usr/src/uts/intel/Makefile.files
usr/src/uts/intel/ia32/ml/modstubs.s
usr/src/uts/intel/io/hotplug/pciehpc/pciehpc_acpi.c
usr/src/uts/intel/io/hotplug/pciehpc/pciehpc_acpi.h
usr/src/uts/intel/io/hotplug/pciehpc/pciehpc_x86.c
usr/src/uts/intel/io/pciex/pcie_acpi.c
usr/src/uts/intel/io/pciex/pcie_pci.c
usr/src/uts/intel/sys/pcie_acpi.h
usr/src/uts/sparc/Makefile.files
usr/src/uts/sparc/Makefile.rules
usr/src/uts/sparc/io/pciex/pcie_plat.c
usr/src/uts/sparc/pcie/Makefile
--- a/usr/src/uts/common/Makefile.files	Fri Apr 24 10:24:29 2009 -0700
+++ b/usr/src/uts/common/Makefile.files	Fri Apr 24 13:17:47 2009 -0700
@@ -1717,7 +1717,7 @@
 INCLUDE_PATH    += $(INC_PATH) $(CCYFLAG)$(UTSBASE)/common
 
 #
-PCIE_OBJS += pcie.o pcie_fault.o
+PCIE_MISC_OBJS += pcie.o pcie_fault.o
 
 #	Chelsio N110 10G NIC driver module
 #
--- a/usr/src/uts/common/io/pcie.c	Fri Apr 24 10:24:29 2009 -0700
+++ b/usr/src/uts/common/io/pcie.c	Fri Apr 24 13:17:47 2009 -0700
@@ -45,36 +45,10 @@
 static void pcie_check_io_mem_range(ddi_acc_handle_t, boolean_t *, boolean_t *);
 #endif /* defined(__i386) || defined(__amd64) */
 
-#ifdef	DEBUG
+#ifdef DEBUG
 uint_t pcie_debug_flags = 0;
-
 static void pcie_print_bus(pcie_bus_t *bus_p);
-
-#define	PCIE_DBG pcie_dbg
-/* Common Debugging shortcuts */
-#define	PCIE_DBG_CFG(dip, bus_p, name, sz, off, org) \
-	PCIE_DBG("%s:%d:(0x%x) %s(0x%x) 0x%x -> 0x%x\n", ddi_node_name(dip), \
-	    ddi_get_instance(dip), bus_p->bus_bdf, name, off, org, \
-	    PCIE_GET(sz, bus_p, off))
-#define	PCIE_DBG_CAP(dip, bus_p, name, sz, off, org) \
-	PCIE_DBG("%s:%d:(0x%x) %s(0x%x) 0x%x -> 0x%x\n", ddi_node_name(dip), \
-	    ddi_get_instance(dip), bus_p->bus_bdf, name, off, org, \
-	    PCIE_CAP_GET(sz, bus_p, off))
-#define	PCIE_DBG_AER(dip, bus_p, name, sz, off, org) \
-	PCIE_DBG("%s:%d:(0x%x) %s(0x%x) 0x%x -> 0x%x\n", ddi_node_name(dip), \
-	    ddi_get_instance(dip), bus_p->bus_bdf, name, off, org, \
-	    PCIE_AER_GET(sz, bus_p, off))
-
-static void pcie_dbg(char *fmt, ...);
-
-#else	/* DEBUG */
-
-#define	PCIE_DBG_CFG 0 &&
-#define	PCIE_DBG 0 &&
-#define	PCIE_DBG_CAP 0 &&
-#define	PCIE_DBG_AER 0 &&
-
-#endif	/* DEBUG */
+#endif /* DEBUG */
 
 /* Variable to control default PCI-Express config settings */
 ushort_t pcie_command_default =
@@ -676,6 +650,8 @@
 
 	bus_p->bus_mps = 0;
 
+	pcie_init_plat(cdip);
+
 	PCIE_DBG("Add %s(dip 0x%p, bdf 0x%x, secbus 0x%x)\n",
 	    ddi_driver_name(cdip), (void *)cdip, bus_p->bus_bdf,
 	    bus_p->bus_bdg_secbus);
@@ -721,6 +697,7 @@
 {
 	pcie_bus_t	*bus_p;
 
+	pcie_fini_plat(cdip);
 	pcie_fini_pfd(cdip);
 
 	bus_p = PCIE_DIP2UPBUS(cdip);
@@ -1510,7 +1487,7 @@
  * o taskq to print at lower pil
  */
 int pcie_dbg_print = 0;
-static void
+void
 pcie_dbg(char *fmt, ...)
 {
 	va_list ap;
--- a/usr/src/uts/common/sys/pcie_impl.h	Fri Apr 24 10:24:29 2009 -0700
+++ b/usr/src/uts/common/sys/pcie_impl.h	Fri Apr 24 13:17:47 2009 -0700
@@ -270,6 +270,8 @@
 	pf_data_t	*bus_pfd;
 
 	int		bus_mps;		/* Maximum Payload Size */
+
+	void		*bus_plat_private;	/* Platform specific */
 } pcie_bus_t;
 
 struct pf_data {
@@ -342,6 +344,34 @@
 	int		highest_common_mps;
 } pcie_max_supported_t;
 
+#ifdef	DEBUG
+extern uint_t pcie_debug_flags;
+#define	PCIE_DBG pcie_dbg
+/* Common Debugging shortcuts */
+#define	PCIE_DBG_CFG(dip, bus_p, name, sz, off, org) \
+	PCIE_DBG("%s:%d:(0x%x) %s(0x%x) 0x%x -> 0x%x\n", ddi_node_name(dip), \
+	    ddi_get_instance(dip), bus_p->bus_bdf, name, off, org, \
+	    PCIE_GET(sz, bus_p, off))
+#define	PCIE_DBG_CAP(dip, bus_p, name, sz, off, org) \
+	PCIE_DBG("%s:%d:(0x%x) %s(0x%x) 0x%x -> 0x%x\n", ddi_node_name(dip), \
+	    ddi_get_instance(dip), bus_p->bus_bdf, name, off, org, \
+	    PCIE_CAP_GET(sz, bus_p, off))
+#define	PCIE_DBG_AER(dip, bus_p, name, sz, off, org) \
+	PCIE_DBG("%s:%d:(0x%x) %s(0x%x) 0x%x -> 0x%x\n", ddi_node_name(dip), \
+	    ddi_get_instance(dip), bus_p->bus_bdf, name, off, org, \
+	    PCIE_AER_GET(sz, bus_p, off))
+
+extern void pcie_dbg(char *fmt, ...);
+
+#else	/* DEBUG */
+
+#define	PCIE_DBG_CFG 0 &&
+#define	PCIE_DBG 0 &&
+#define	PCIE_DBG_CAP 0 &&
+#define	PCIE_DBG_AER 0 &&
+
+#endif	/* DEBUG */
+
 /* PCIe Friendly Functions */
 extern void pcie_init_root_port_mps(dev_info_t *dip);
 extern int pcie_initchild(dev_info_t *dip);
@@ -379,6 +409,8 @@
 extern void pcie_set_aer_ce_mask(uint32_t mask);
 extern void pcie_set_aer_suce_mask(uint32_t mask);
 extern void pcie_set_serr_mask(uint32_t mask);
+extern void pcie_init_plat(dev_info_t *dip);
+extern void pcie_fini_plat(dev_info_t *dip);
 
 /* PCIe error handling functions */
 extern int pf_scan_fabric(dev_info_t *rpdip, ddi_fm_error_t *derr,
--- a/usr/src/uts/i86pc/Makefile.files	Fri Apr 24 10:24:29 2009 -0700
+++ b/usr/src/uts/i86pc/Makefile.files	Fri Apr 24 13:17:47 2009 -0700
@@ -173,7 +173,7 @@
 			   gfxp_devmap.o gfxp_vgatext.o gfxp_vm.o vgasubr.o
 IOAT_OBJS += ioat.o ioat_rs.o ioat_ioctl.o ioat_chan.o
 ISANEXUS_OBJS += isa.o dma_engine.o i8237A.o
-PCI_E_MISC_OBJS += pcie.o pcie_fault.o
+PCIE_MISC_OBJS += pcie_acpi.o
 PCI_E_NEXUS_OBJS += npe.o npe_misc.o
 PCI_E_NEXUS_OBJS += pci_common.o pci_kstats.o pci_tools.o
 PCINEXUS_OBJS += pci.o pci_common.o pci_kstats.o pci_tools.o
--- a/usr/src/uts/i86pc/pcie/Makefile	Fri Apr 24 10:24:29 2009 -0700
+++ b/usr/src/uts/i86pc/pcie/Makefile	Fri Apr 24 13:17:47 2009 -0700
@@ -21,10 +21,9 @@
 #
 # uts/i86pc/pcie/Makefile
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-#ident	"%Z%%M%	%I%	%E% SMI"
 #
 #	This makefile drives the production of the kernel/misc/pcie module
 #	for PCI-E Error handling support in PCI-E nexus drivers.
@@ -41,8 +40,8 @@
 #	Define the module and object file sets.
 #
 MODULE		= pcie
-OBJECTS		= $(PCI_E_MISC_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(PCI_E_MISC_OBJS:%.o=$(LINTS_DIR)/%.ln)
+OBJECTS		= $(PCIE_MISC_OBJS:%=$(OBJS_DIR)/%)
+LINTS		= $(PCIE_MISC_OBJS:%.o=$(LINTS_DIR)/%.ln)
 ROOTMODULE	= $(ROOT_PSM_MISC_DIR)/$(MODULE)
 
 #
@@ -50,6 +49,8 @@
 #
 include $(UTSBASE)/i86pc/Makefile.i86pc
 
+LDFLAGS         += -dy -Nmisc/acpica
+
 #
 #	Define targets
 #
--- a/usr/src/uts/intel/Makefile.files	Fri Apr 24 10:24:29 2009 -0700
+++ b/usr/src/uts/intel/Makefile.files	Fri Apr 24 13:17:47 2009 -0700
@@ -153,7 +153,7 @@
 PCICFG_OBJS += pcicfg.o
 PCI_E_PCINEXUS_OBJS += pcie_pci.o
 PCI_PCINEXUS_OBJS += pci_pci.o
-PCIEHPCNEXUS_OBJS += pciehpc_x86.o pciehpc_acpi.o
+PCIEHPCNEXUS_OBJS += pciehpc_acpi.o
 PCN_OBJS += mii.o
 PIT_BEEP_OBJS += pit_beep.o
 POWER_OBJS += power.o
--- a/usr/src/uts/intel/ia32/ml/modstubs.s	Fri Apr 24 10:24:29 2009 -0700
+++ b/usr/src/uts/intel/ia32/ml/modstubs.s	Fri Apr 24 13:17:47 2009 -0700
@@ -1049,7 +1049,6 @@
 	MODULE(pciehpc,misc);
 	STUB(pciehpc, pciehpc_init, 0);
 	STUB(pciehpc, pciehpc_uninit, 0);
-	STUB(pciehpc, pciehpc_acpi_eval_osc, 0);
 	WSTUB(pciehpc, pciehpc_intr, nomod_zero);
 	END_MODULE(pciehpc);
 #endif
--- a/usr/src/uts/intel/io/hotplug/pciehpc/pciehpc_acpi.c	Fri Apr 24 10:24:29 2009 -0700
+++ b/usr/src/uts/intel/io/hotplug/pciehpc/pciehpc_acpi.c	Fri Apr 24 13:17:47 2009 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- *  Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ *  Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  *  Use is subject to license terms.
  */
 
@@ -38,6 +38,7 @@
 #include <sys/pci.h>
 #include <sys/ddi.h>
 #include <sys/sunddi.h>
+#include <sys/pcie_acpi.h>
 #include "pciehpc_acpi.h"
 
 /* local static functions */
@@ -51,6 +52,7 @@
 	void *data, uint_t flags);
 static int pciehpc_acpi_slot_disconnect(caddr_t ops_arg, hpc_slot_t slot_hdl,
 	void *data, uint_t flags);
+static void pciehpc_acpi_setup_ops(pciehpc_t *ctrl_p);
 
 static ACPI_STATUS pciehpc_acpi_install_event_handler(pciehpc_t *ctrl_p);
 static void pciehpc_acpi_uninstall_event_handler(pciehpc_t *ctrl_p);
@@ -60,127 +62,39 @@
 	void *context);
 static ACPI_STATUS pciehpc_acpi_ej0_present(ACPI_HANDLE pcibus_obj);
 static ACPI_STATUS pciehpc_acpi_get_dev_state(ACPI_HANDLE obj, int *statusp);
-ACPI_STATUS pciehpc_acpi_eval_osc(ACPI_HANDLE osc_hdl, uint32_t *hp_mode);
-static ACPI_STATUS pciehpc_acpi_find_osc(ACPI_HANDLE busobj,
-	ACPI_HANDLE *osc_hdlp);
 
-#ifdef DEBUG
-static void pciehpc_dump_acpi_obj(ACPI_HANDLE pcibus_obj);
-static ACPI_STATUS pciehpc_walk_obj_namespace(ACPI_HANDLE hdl, uint32_t nl,
-	void *context, void **ret);
-static ACPI_STATUS pciehpc_print_acpi_name(ACPI_HANDLE hdl, uint32_t nl,
-	void *context, void **ret);
-static void print_acpi_pathname(ACPI_HANDLE hdl);
-#endif
-
-/* UUID for for PCI/PCI-X/PCI-Exp hierarchy as defined in PCI fw ver 3.0 */
-static uint8_t pcie_uuid[16] =
-	{0x5b, 0x4d, 0xdb, 0x33, 0xf7, 0x1f, 0x1c, 0x40,
-	0x96, 0x57, 0x74, 0x41, 0xc0, 0x3d, 0xd7, 0x66};
 /*
- * Function to check if ACPI hot plug is enabled on this bridge device.
- * Since there is no absolute way to figure out if ACPI BIOS has hot plug
- * control, the following approach is necessary:
- *
- *	1) If _OSC method is present then it is straight forward.
- *	2) Otherwise, we need platform specific way to determine
- *	   whether ACPI BIOS has hot plug control or not.
- *	   (e.g: using .conf file property)
- *
- * NOTE: As per the PCI FW 3.0 spec, in the absence of _OSC method OS
- * should not try to do native hot plug control.
- *
- * Returns 0 if the current mode is not ACPI hot plug.
+ * Update ops vector with platform specific (ACPI, CK8-04,...) functions.
  */
-int
-pciehpc_acpi_hotplug_enabled(dev_info_t *dip)
+void
+pciehpc_update_ops(pciehpc_t *ctrl_p)
 {
-	int *hotplug_mode;
-	uint_t count;
-	ACPI_HANDLE pcibus_obj;
-	int status = AE_ERROR;
-	ACPI_HANDLE osc_hdl;
-	int use_native_hotplug = 0;
-	uint32_t hp_mode;
-
-	/*
-	 * (1)  Find the ACPI device node for this bus node.
-	 */
-	status = acpica_get_handle(dip, &pcibus_obj);
-	if (status != AE_OK) {
-		/*
-		 * No ACPI device for this bus node. Assume there is
-		 * no ACPI hot plug support on this bus.
-		 */
-		PCIEHPC_DEBUG((CE_CONT, "No ACPI device found (dip %p)\n",
-		    (void *)dip));
-		PCIEHPC_DEBUG((CE_CONT, "Assuming native Hot-Plug mode\n"));
-		return (0);
-	}
-
+	boolean_t hp_native_mode = B_FALSE;
+	uint32_t osc_flags = OSC_CONTROL_PCIE_NAT_HP;
 
 	/*
-	 * NOTE: Without _OSC method there is no reliable way to know if the
-	 * platform implements ACPI hot plug or native hot plug. But, if it is
-	 * present then it may be possible to use either mode (i.e ACPI or
-	 * native-hotplug) if the platform supports both.
+	 * Call _OSC method to determine if hotplug mode is native or ACPI.
+	 * If _OSC method succeeds hp_native_mode below will be set according to
+	 * if native hotplug control was granted or not by BIOS.
+	 *
+	 * If _OSC method fails for any reason or if native hotplug control was
+	 * not granted assume it's ACPI mode and update platform specific
+	 * (ACPI, CK8-04,...) impl. ops
 	 */
 
-	/*
-	 * (2)	Check if _OSC method is present.
-	 */
-	if (pciehpc_acpi_find_osc(pcibus_obj, &osc_hdl) != AE_OK) {
-		/* no _OSC method present; we need to guess here! */
-		PCIEHPC_DEBUG((CE_NOTE, "no _OSC method present\n"));
-		/*
-		 * If "use-native-hotplug-mode" property set then it means
-		 * the platform supports only native hot-plug mode.
-		 */
-		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
-		    DDI_PROP_DONTPASS, "use-native-hotplug-mode",
-		    &hotplug_mode, &count) == DDI_PROP_SUCCESS) {
-			if (hotplug_mode[0] == 1)
-				use_native_hotplug = 1;
-			ddi_prop_free(hotplug_mode);
-		}
-		if (use_native_hotplug) {
-			PCIEHPC_DEBUG((CE_NOTE,
-			    "Assuming native Hot-Plug mode\n"));
-			return (0); /* assume native hot plug mode */
-		} else {
-			PCIEHPC_DEBUG((CE_NOTE,
-			    "Assuming legacy ACPI Hot-Plug mode\n"));
-			return (1); /* assume ACPI hot plug mode */
-		}
+	if (pcie_acpi_osc(ctrl_p->dip, &osc_flags) == DDI_SUCCESS) {
+		hp_native_mode = (osc_flags & OSC_CONTROL_PCIE_NAT_HP) ?
+		    B_TRUE : B_FALSE;
 	}
 
-	/*
-	 * (3)	_OSC method exists; evaluate _OSC to use native hot-plug mode.
-	 *
-	 * Note: The default policy is to use native hot-plug mode if the
-	 * platform supports it.
-	 */
-	if (pciehpc_acpi_eval_osc(osc_hdl, &hp_mode) != AE_OK) {
-		/* failed to evaluate _OSC method; assume ACPI hot plug */
-		PCIEHPC_DEBUG((CE_NOTE, "Failed to evaluate _OSC; "
-		    "Assuming legacy ACPI Hot-Plug mode\n"));
-		return (1);
+	if (!hp_native_mode) {
+		/* update ops vector for ACPI mode */
+		pciehpc_acpi_setup_ops(ctrl_p);
+		ctrl_p->hp_mode = PCIEHPC_ACPI_HP_MODE;
 	}
-
-#ifdef DEBUG
-	if (pciehpc_debug > 1)
-		pciehpc_dump_acpi_obj(pcibus_obj);
-#endif
-	if (hp_mode == NATIVE_HP_MODE) {
-		PCIEHPC_DEBUG((CE_NOTE, "Native Hot-Plug mode enabled\n"));
-		return (0); /* it is in native hp mode! */
-	}
-
-	PCIEHPC_DEBUG((CE_NOTE, "ACPI Hot-Plug mode enabled\n"));
-	return (1); /* use ACPI mode */
 }
 
-void
+static void
 pciehpc_acpi_setup_ops(pciehpc_t *ctrl_p)
 {
 	ctrl_p->ops.init_hpc_hw = pciehpc_acpi_hpc_init;
@@ -752,196 +666,3 @@
 
 	return (ret);
 }
-
-/*
- * Evaluate _OSC method to use native hot-plug mode if platform supports it.
- * If platform doesn't support native hot-plug then hp_mode will be set
- * to ACPI_HP_MODE.
- */
-ACPI_STATUS
-pciehpc_acpi_eval_osc(ACPI_HANDLE osc_hdl, uint32_t *hp_mode)
-{
-	ACPI_STATUS		status;
-	ACPI_OBJECT_LIST	arglist;
-	ACPI_OBJECT		args[4];
-	UINT32			caps_buffer[3];
-	ACPI_BUFFER		rb;
-	UINT32			*rbuf;
-
-	/* construct argument list */
-	arglist.Count = 4;
-	arglist.Pointer = args;
-
-	/* arg0 - UUID */
-	args[0].Type = ACPI_TYPE_BUFFER;
-	args[0].Buffer.Length = 16; /* size of UUID string */
-	args[0].Buffer.Pointer = pcie_uuid;
-
-	/* arg1 - Revision ID */
-	args[1].Type = ACPI_TYPE_INTEGER;
-	args[1].Integer.Value = PCIE_OSC_REVISION_ID;
-
-	/* arg2 - Count */
-	args[2].Type = ACPI_TYPE_INTEGER;
-	args[2].Integer.Value = 3; /* no. of DWORDS in caps_buffer */
-
-	/* arg3 - Capabilities Buffer */
-	args[3].Type = ACPI_TYPE_BUFFER;
-	args[3].Buffer.Length = 12;
-	args[3].Buffer.Pointer = (void *)caps_buffer;
-
-	/* Initialize Capabilities Buffer */
-
-	/* DWORD1: no query flag set */
-	caps_buffer[0] = 0;
-	/* DWORD2: Support Field */
-	caps_buffer[1] = OSC_SUPPORT_FIELD_INIT;
-	/* DWORD3: Control Field */
-	caps_buffer[2] = OSC_CONTROL_FIELD_INIT;
-
-	rb.Length = ACPI_ALLOCATE_BUFFER;
-	rb.Pointer = NULL;
-
-	status = AcpiEvaluateObjectTyped(osc_hdl, NULL, &arglist, &rb,
-	    ACPI_TYPE_BUFFER);
-	if (status != AE_OK) {
-		PCIEHPC_DEBUG((CE_CONT,
-		    "Failed to execute _OSC method (status %d)\n", status));
-		return (status);
-	}
-
-	rbuf = (UINT32 *)((ACPI_OBJECT *)rb.Pointer)->Buffer.Pointer;
-
-	/* check the STATUS word in the capability buffer */
-	if (rbuf[0] & OSC_STATUS_ERRORS) {
-		PCIEHPC_DEBUG((CE_CONT, "_OSC method failed (STATUS %d)\n",
-		    rbuf[0]));
-		AcpiOsFree(rb.Pointer);
-		return (AE_ERROR);
-	}
-
-	PCIEHPC_DEBUG((CE_CONT, "_OSC method evaluation completed: "
-	    "STATUS 0x%x SUPPORT 0x%x CONTROL 0x%x\n",
-	    rbuf[0], rbuf[1], rbuf[2]));
-
-	/* check if the Native Hot-Plug Control is granted */
-	if (rbuf[2] & OSC_CONTROL_PCIE_NAT_HP)
-		*hp_mode = NATIVE_HP_MODE;
-	else
-		*hp_mode = ACPI_HP_MODE;
-
-	AcpiOsFree(rb.Pointer);
-
-	return (AE_OK);
-}
-
-#ifdef DEBUG
-static void
-pciehpc_dump_acpi_obj(ACPI_HANDLE pcibus_obj)
-{
-	int status;
-	ACPI_BUFFER retbuf;
-
-	if (pcibus_obj == NULL)
-		return;
-
-	/* print the full path name */
-	retbuf.Pointer = NULL;
-	retbuf.Length = ACPI_ALLOCATE_BUFFER;
-	status = AcpiGetName(pcibus_obj, ACPI_FULL_PATHNAME, &retbuf);
-	if (status != AE_OK)
-		return;
-	cmn_err(CE_CONT, "PCIE BUS PATHNAME: %s\n", (char *)retbuf.Pointer);
-	AcpiOsFree(retbuf.Pointer);
-
-	/* dump all the methods for this bus node */
-	cmn_err(CE_CONT, "  METHODS: \n");
-	status = AcpiWalkNamespace(ACPI_TYPE_METHOD, pcibus_obj, 1,
-	    pciehpc_print_acpi_name, "  ", NULL);
-	/* dump all the child devices */
-	status = AcpiWalkNamespace(ACPI_TYPE_DEVICE, pcibus_obj, 1,
-	    pciehpc_walk_obj_namespace, NULL, NULL);
-}
-
-/*ARGSUSED*/
-static ACPI_STATUS
-pciehpc_walk_obj_namespace(ACPI_HANDLE hdl, uint32_t nl, void *context,
-	void **ret)
-{
-	int status;
-	ACPI_BUFFER retbuf;
-	char buf[32];
-
-	/* print the full path name */
-	retbuf.Pointer = NULL;
-	retbuf.Length = ACPI_ALLOCATE_BUFFER;
-	status = AcpiGetName(hdl, ACPI_FULL_PATHNAME, &retbuf);
-	if (status != AE_OK)
-		return (status);
-	buf[0] = 0;
-	while (nl--)
-		(void) strcat(buf, "  ");
-	cmn_err(CE_CONT, "%sDEVICE: %s\n", buf, (char *)retbuf.Pointer);
-	AcpiOsFree(retbuf.Pointer);
-
-	/* dump all the methods for this device */
-	cmn_err(CE_CONT, "%s  METHODS: \n", buf);
-	status = AcpiWalkNamespace(ACPI_TYPE_METHOD, hdl, 1,
-	    pciehpc_print_acpi_name, (void *)buf, NULL);
-	return (status);
-}
-
-/*ARGSUSED*/
-static ACPI_STATUS
-pciehpc_print_acpi_name(ACPI_HANDLE hdl, uint32_t nl, void *context, void **ret)
-{
-	int status;
-	ACPI_BUFFER retbuf;
-	char name[16];
-
-	retbuf.Pointer = name;
-	retbuf.Length = 16;
-	status = AcpiGetName(hdl, ACPI_SINGLE_NAME, &retbuf);
-	if (status == AE_OK)
-		cmn_err(CE_CONT, "%s    %s \n", (char *)context, name);
-	return (AE_OK);
-}
-
-static void
-print_acpi_pathname(ACPI_HANDLE hdl)
-{
-	int status;
-	ACPI_BUFFER retbuf;
-
-	retbuf.Pointer = NULL;
-	retbuf.Length = ACPI_ALLOCATE_BUFFER;
-	status = AcpiGetName(hdl, ACPI_FULL_PATHNAME, &retbuf);
-	if (status == AE_OK) {
-		cmn_err(CE_CONT, "%s \n", (char *)retbuf.Pointer);
-		AcpiOsFree(retbuf.Pointer);
-	}
-}
-#endif
-
-static ACPI_STATUS
-pciehpc_acpi_find_osc(ACPI_HANDLE busobj, ACPI_HANDLE *osc_hdlp)
-{
-	ACPI_HANDLE parentobj = busobj;
-	ACPI_STATUS status = AE_NOT_FOUND;
-
-	*osc_hdlp = NULL;
-
-	/*
-	 * Walk up the ACPI device tree looking for _OSC method.
-	 */
-	do {
-		busobj = parentobj;
-		if ((status = AcpiGetHandle(busobj, "_OSC", osc_hdlp)) == AE_OK)
-			break;
-	} while (AcpiGetParent(busobj, &parentobj) == AE_OK);
-
-	if (*osc_hdlp == NULL)
-		status = AE_NOT_FOUND;
-
-	return (status);
-}
--- a/usr/src/uts/intel/io/hotplug/pciehpc/pciehpc_acpi.h	Fri Apr 24 10:24:29 2009 -0700
+++ b/usr/src/uts/intel/io/hotplug/pciehpc/pciehpc_acpi.h	Fri Apr 24 13:17:47 2009 -0700
@@ -20,15 +20,13 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #ifndef	_PCIEHPC_ACPI_H
 #define	_PCIEHPC_ACPI_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #ifdef	__cplusplus
 extern "C" {
 #endif
@@ -64,48 +62,6 @@
 #define	PCIEHPC_ACPI_DSM_PRESENT	0x0080
 #define	PCIEHPC_ACPI_STR_PRESENT	0x0100
 
-/* revision id of _OSC for PCI/PCI-X/PCI-Exp hierarchy */
-#define	PCIE_OSC_REVISION_ID	1	/* defined in PCI fw ver 3.0 */
-
-/*
- * _OSC method Capabilities buffer bit definitions (from PCI FW 3.0)
- */
-/* first DWORD: status from _OSC invocation (except bit 0) */
-#define	OSC_STATUS_QUERY_ENABLE	0x1	/* Query Support Flag */
-#define	OSC_STATUS_FAILED	0x2	/* _OSC failure */
-#define	OSC_STATUS_INV_UUID	0x4	/* invalid UUID */
-#define	OSC_STATUS_INV_REVID	0x8	/* invalid revision ID */
-#define	OSC_STATUS_CAPS_MASKED	0x10	/* capabilities masked */
-
-#define	OSC_STATUS_ERRORS \
-	(OSC_STATUS_FAILED | OSC_STATUS_INV_UUID | OSC_STATUS_INV_REVID)
-
-/* second DWORD: Support Field (set by OS) */
-#define	OSC_SUPPORT_EXT_PCI_CFG	0x1	/* Extended PCI Config Ops supported */
-#define	OSC_SUPPORT_ACT_PM	0x2	/* Active State PM supported */
-#define	OSC_SUPPORT_CLK_PM_CAP	0x4	/* Clock PM Capability supported */
-#define	OSC_SUPPORT_PCI_SEGS	0x8	/* PCI Segment Groups supported */
-#define	OSC_SUPPORT_MSI		0x10	/* MSI supported */
-
-/* third DWORD: Control Field (set by OS/BIOS) */
-#define	OSC_CONTROL_PCIE_NAT_HP	0x1	/* PCI Exp Native Hot Plug control */
-#define	OSC_CONTROL_SHPC_NAT_HP	0x2	/* SHPC Native Hot Plug control */
-#define	OSC_CONTROL_PCIE_NAT_PM	0x4	/* PCI Exp Native Power Mgmt. control */
-#define	OSC_CONTROL_PCIE_ADV_ERR 0x8	/* PCIE Advanced Err. rep. control */
-#define	OSC_CONTROL_PCIE_CAPS	0x10	/* PCIE Caps Structure control */
-
-#define	OSC_CONTROL_FIELD_INIT \
-	(OSC_CONTROL_PCIE_NAT_PM | OSC_CONTROL_PCIE_NAT_HP | \
-	OSC_CONTROL_PCIE_CAPS | OSC_CONTROL_PCIE_ADV_ERR)
-
-#define	OSC_SUPPORT_FIELD_INIT \
-	(OSC_SUPPORT_EXT_PCI_CFG | \
-	OSC_SUPPORT_ACT_PM | OSC_SUPPORT_CLK_PM_CAP | \
-	OSC_SUPPORT_MSI | OSC_SUPPORT_PCI_SEGS)
-
-#define	ACPI_HP_MODE	1
-#define	NATIVE_HP_MODE	2
-
 /* Device status bit as returned by _STA method (see 6.3.7 of ACPI 3.0) */
 #define	DEV_STS_PRESENT		0x1	/* device is present */
 #define	DEV_STS_ENABLED		0x2	/* device is enabled */
--- a/usr/src/uts/intel/io/hotplug/pciehpc/pciehpc_x86.c	Fri Apr 24 10:24:29 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- *  Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
- *  Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <sys/types.h>
-#include <sys/note.h>
-#include <sys/kmem.h>
-#include <sys/debug.h>
-#include <sys/vtrace.h>
-#include <sys/autoconf.h>
-#include <sys/varargs.h>
-#include <sys/ddi_impldefs.h>
-#include <sys/pci.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/time.h>
-#include <sys/callb.h>
-#include <sys/hotplug/pci/pciehpc_impl.h>
-
-extern int pciehpc_acpi_hotplug_enabled(dev_info_t *dip);
-extern void pciehpc_acpi_setup_ops(pciehpc_t *ctrl_p);
-
-/*
- * Update ops vector with platform specific (ACPI, CK8-04,...) functions.
- */
-void
-pciehpc_update_ops(pciehpc_t *ctrl_p)
-{
-	/* update platform specific (ACPI, CK8-04,...) impl. ops */
-	if (pciehpc_acpi_hotplug_enabled(ctrl_p->dip)) {
-		/* update ops vector for ACPI mode */
-		pciehpc_acpi_setup_ops(ctrl_p);
-		ctrl_p->hp_mode = PCIEHPC_ACPI_HP_MODE;
-	}
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/intel/io/pciex/pcie_acpi.c	Fri Apr 24 13:17:47 2009 -0700
@@ -0,0 +1,314 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+#include <sys/sysmacros.h>
+#include <sys/types.h>
+#include <sys/kmem.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/sunndi.h>
+#include <sys/promif.h>
+#include <sys/pcie.h>
+#include <sys/pci_cap.h>
+#include <sys/pcie_impl.h>
+#include <sys/pcie_acpi.h>
+#include <sys/acpi/acpi.h>
+#include <sys/acpica.h>
+
+ACPI_STATUS pcie_acpi_eval_osc(dev_info_t *dip, ACPI_HANDLE osc_hdl,
+	uint32_t *osc_flags);
+static ACPI_STATUS pcie_acpi_find_osc(ACPI_HANDLE busobj,
+	ACPI_HANDLE *osc_hdlp);
+
+#ifdef DEBUG
+static void pcie_dump_acpi_obj(ACPI_HANDLE pcibus_obj);
+static ACPI_STATUS pcie_walk_obj_namespace(ACPI_HANDLE hdl, uint32_t nl,
+	void *context, void **ret);
+static ACPI_STATUS pcie_print_acpi_name(ACPI_HANDLE hdl, uint32_t nl,
+	void *context, void **ret);
+#endif /* DEBUG */
+
+void
+pcie_init_plat(dev_info_t *dip)
+{
+	pcie_bus_t	*bus_p = PCIE_DIP2BUS(dip);
+	bus_p->bus_plat_private =
+	    (pcie_x86_priv_t *)kmem_zalloc(sizeof (pcie_x86_priv_t), KM_SLEEP);
+}
+
+void
+pcie_fini_plat(dev_info_t *dip)
+{
+	pcie_bus_t	*bus_p = PCIE_DIP2BUS(dip);
+
+	kmem_free(bus_p->bus_plat_private, sizeof (pcie_x86_priv_t));
+}
+
+int
+pcie_acpi_osc(dev_info_t *dip, uint32_t *osc_flags)
+{
+	ACPI_HANDLE pcibus_obj;
+	int status = AE_ERROR;
+	ACPI_HANDLE osc_hdl;
+	pcie_bus_t *bus_p = PCIE_DIP2BUS(dip);
+	pcie_x86_priv_t *osc_p = (pcie_x86_priv_t *)bus_p->bus_plat_private;
+
+	/* Mark this so we know _OSC has been called for this device */
+	osc_p->bus_osc = B_TRUE;
+
+	/*
+	 * (1)  Find the ACPI device node for this bus node.
+	 */
+	status = acpica_get_handle(dip, &pcibus_obj);
+	if (status != AE_OK) {
+		PCIE_DBG("No ACPI device found (dip %p)\n", (void *)dip);
+		return (DDI_FAILURE);
+	}
+
+	/*
+	 * (2)	Check if _OSC method is present.
+	 */
+	if (pcie_acpi_find_osc(pcibus_obj, &osc_hdl) != AE_OK) {
+		/* no _OSC method present */
+		PCIE_DBG("no _OSC method present for dip %p\n",
+		    (void *)dip);
+		return (DDI_FAILURE);
+	}
+
+	/*
+	 * (3)	_OSC method exists; evaluate _OSC.
+	 */
+	if (pcie_acpi_eval_osc(dip, osc_hdl, osc_flags) != AE_OK) {
+		PCIE_DBG("Failed to evaluate _OSC method for dip 0x%p\n",
+		    (void *)dip);
+		return (DDI_FAILURE);
+	}
+
+	osc_p->bus_osc_hp = (*osc_flags & OSC_CONTROL_PCIE_NAT_HP) ?
+	    B_TRUE : B_FALSE;
+	osc_p->bus_osc_aer = (*osc_flags & OSC_CONTROL_PCIE_ADV_ERR) ?
+	    B_TRUE : B_FALSE;
+
+#ifdef DEBUG
+	if (pcie_debug_flags > 1)
+		pcie_dump_acpi_obj(pcibus_obj);
+#endif /* DEBUG */
+
+	return (DDI_SUCCESS);
+}
+
+static ACPI_STATUS
+pcie_acpi_find_osc(ACPI_HANDLE busobj, ACPI_HANDLE *osc_hdlp)
+{
+	ACPI_HANDLE parentobj = busobj;
+	ACPI_STATUS status = AE_NOT_FOUND;
+
+	*osc_hdlp = NULL;
+
+	/*
+	 * Walk up the ACPI device tree looking for _OSC method.
+	 */
+	do {
+		busobj = parentobj;
+		if ((status = AcpiGetHandle(busobj, "_OSC", osc_hdlp)) == AE_OK)
+			break;
+	} while (AcpiGetParent(busobj, &parentobj) == AE_OK);
+
+	if (*osc_hdlp == NULL)
+		status = AE_NOT_FOUND;
+
+	return (status);
+}
+
+/* UUID for for PCI/PCI-X/PCI-Exp hierarchy as defined in PCI fw ver 3.0 */
+static uint8_t pcie_uuid[16] =
+	{0x5b, 0x4d, 0xdb, 0x33, 0xf7, 0x1f, 0x1c, 0x40,
+	0x96, 0x57, 0x74, 0x41, 0xc0, 0x3d, 0xd7, 0x66};
+
+/*
+ * Evaluate _OSC method.
+ */
+ACPI_STATUS
+pcie_acpi_eval_osc(dev_info_t *dip, ACPI_HANDLE osc_hdl, uint32_t *osc_flags)
+{
+	ACPI_STATUS		status;
+	ACPI_OBJECT_LIST	arglist;
+	ACPI_OBJECT		args[4];
+	UINT32			caps_buffer[3];
+	ACPI_BUFFER		rb;
+	UINT32			*rbuf;
+	UINT32			tmp_ctrl;
+
+	/* construct argument list */
+	arglist.Count = 4;
+	arglist.Pointer = args;
+
+	/* arg0 - UUID */
+	args[0].Type = ACPI_TYPE_BUFFER;
+	args[0].Buffer.Length = 16; /* size of UUID string */
+	args[0].Buffer.Pointer = pcie_uuid;
+
+	/* arg1 - Revision ID */
+	args[1].Type = ACPI_TYPE_INTEGER;
+	args[1].Integer.Value = PCIE_OSC_REVISION_ID;
+
+	/* arg2 - Count */
+	args[2].Type = ACPI_TYPE_INTEGER;
+	args[2].Integer.Value = 3; /* no. of DWORDS in caps_buffer */
+
+	/* arg3 - Capabilities Buffer */
+	args[3].Type = ACPI_TYPE_BUFFER;
+	args[3].Buffer.Length = 12;
+	args[3].Buffer.Pointer = (void *)caps_buffer;
+
+	/* Initialize Capabilities Buffer */
+
+	/* DWORD1: no query flag set */
+	caps_buffer[0] = 0;
+	/* DWORD2: Support Field */
+	caps_buffer[1] = OSC_SUPPORT_FIELD_INIT;
+	/* DWORD3: Control Field */
+	caps_buffer[2] = OSC_CONTROL_FIELD_INIT;
+
+	/* If hotplug is supported add the corresponding control fields */
+	if (*osc_flags & OSC_CONTROL_PCIE_NAT_HP)
+		caps_buffer[2] |= (OSC_CONTROL_PCIE_NAT_HP |
+		    OSC_CONTROL_PCIE_NAT_PM);
+
+	tmp_ctrl = caps_buffer[2];
+	rb.Length = ACPI_ALLOCATE_BUFFER;
+	rb.Pointer = NULL;
+
+	status = AcpiEvaluateObjectTyped(osc_hdl, NULL, &arglist, &rb,
+	    ACPI_TYPE_BUFFER);
+	if (status != AE_OK) {
+		PCIE_DBG("Failed to execute _OSC method (status %d)\n",
+		    status);
+		return (status);
+	}
+
+	/* LINTED pointer alignment */
+	rbuf = (UINT32 *)((ACPI_OBJECT *)rb.Pointer)->Buffer.Pointer;
+
+	/* check the STATUS word in the capability buffer */
+	if (rbuf[0] & OSC_STATUS_ERRORS) {
+		PCIE_DBG("_OSC method failed (STATUS %d)\n", rbuf[0]);
+		AcpiOsFree(rb.Pointer);
+		return (AE_ERROR);
+	}
+
+	*osc_flags = rbuf[2];
+
+	PCIE_DBG("_OSC method evaluation completed for 0x%p: "
+	    "STATUS 0x%x SUPPORT 0x%x CONTROL req 0x%x, CONTROL ret 0x%x\n",
+	    (void *)dip, rbuf[0], rbuf[1], tmp_ctrl, rbuf[2]);
+
+	AcpiOsFree(rb.Pointer);
+
+	return (AE_OK);
+}
+
+/*
+ * Checks if _OSC method has been called for this device.
+ */
+boolean_t
+pcie_is_osc(dev_info_t *dip)
+{
+	pcie_bus_t *bus_p = PCIE_DIP2BUS(dip);
+	pcie_x86_priv_t *osc_p = (pcie_x86_priv_t *)bus_p->bus_plat_private;
+	return (osc_p->bus_osc);
+}
+
+#ifdef DEBUG
+static void
+pcie_dump_acpi_obj(ACPI_HANDLE pcibus_obj)
+{
+	int status;
+	ACPI_BUFFER retbuf;
+
+	if (pcibus_obj == NULL)
+		return;
+
+	/* print the full path name */
+	retbuf.Pointer = NULL;
+	retbuf.Length = ACPI_ALLOCATE_BUFFER;
+	status = AcpiGetName(pcibus_obj, ACPI_FULL_PATHNAME, &retbuf);
+	if (status != AE_OK)
+		return;
+	PCIE_DBG("PCIE BUS PATHNAME: %s\n", (char *)retbuf.Pointer);
+	AcpiOsFree(retbuf.Pointer);
+
+	/* dump all the methods for this bus node */
+	PCIE_DBG("  METHODS: \n");
+	status = AcpiWalkNamespace(ACPI_TYPE_METHOD, pcibus_obj, 1,
+	    pcie_print_acpi_name, "  ", NULL);
+	/* dump all the child devices */
+	status = AcpiWalkNamespace(ACPI_TYPE_DEVICE, pcibus_obj, 1,
+	    pcie_walk_obj_namespace, NULL, NULL);
+}
+
+/*ARGSUSED*/
+static ACPI_STATUS
+pcie_walk_obj_namespace(ACPI_HANDLE hdl, uint32_t nl, void *context,
+	void **ret)
+{
+	int status;
+	ACPI_BUFFER retbuf;
+	char buf[32];
+
+	/* print the full path name */
+	retbuf.Pointer = NULL;
+	retbuf.Length = ACPI_ALLOCATE_BUFFER;
+	status = AcpiGetName(hdl, ACPI_FULL_PATHNAME, &retbuf);
+	if (status != AE_OK)
+		return (status);
+	buf[0] = 0;
+	while (nl--)
+		(void) strcat(buf, "  ");
+	PCIE_DBG("%sDEVICE: %s\n", buf, (char *)retbuf.Pointer);
+	AcpiOsFree(retbuf.Pointer);
+
+	/* dump all the methods for this device */
+	PCIE_DBG("%s  METHODS: \n", buf);
+	status = AcpiWalkNamespace(ACPI_TYPE_METHOD, hdl, 1,
+	    pcie_print_acpi_name, (void *)buf, NULL);
+	return (status);
+}
+
+/*ARGSUSED*/
+static ACPI_STATUS
+pcie_print_acpi_name(ACPI_HANDLE hdl, uint32_t nl, void *context, void **ret)
+{
+	int status;
+	ACPI_BUFFER retbuf;
+	char name[16];
+
+	retbuf.Pointer = name;
+	retbuf.Length = 16;
+	status = AcpiGetName(hdl, ACPI_SINGLE_NAME, &retbuf);
+	if (status == AE_OK)
+		PCIE_DBG("%s    %s \n", (char *)context, name);
+	return (AE_OK);
+}
+#endif /* DEBUG */
--- a/usr/src/uts/intel/io/pciex/pcie_pci.c	Fri Apr 24 10:24:29 2009 -0700
+++ b/usr/src/uts/intel/io/pciex/pcie_pci.c	Fri Apr 24 13:17:47 2009 -0700
@@ -44,6 +44,7 @@
 #include <sys/pcie.h>
 #include <sys/pci_cap.h>
 #include <sys/pcie_impl.h>
+#include <sys/pcie_acpi.h>
 #include <sys/hotplug/pci/pcihp.h>
 #include <sys/hotplug/pci/pciehpc.h>
 #include <sys/hotplug/hpctrl.h>
@@ -305,8 +306,8 @@
 	int			instance, intr_types, fmcap;
 	char			device_type[8];
 	pepb_devstate_t		*pepb;
-	ddi_acc_handle_t	config_handle;
 	pcie_bus_t		*bus_p = PCIE_DIP2UPBUS(devi);
+	ddi_acc_handle_t	config_handle = bus_p->bus_cfg_hdl;
 
 	switch (cmd) {
 	case DDI_RESUME:
@@ -370,54 +371,6 @@
 	    DDI_PROP_DONTPASS, "pci-hotplug-type", INBAND_HPC_NONE);
 
 	/*
-	 * Initialize interrupt handlers.
-	 */
-	if (ddi_intr_get_supported_types(devi, &intr_types) != DDI_SUCCESS)
-		goto next_step;
-
-	PEPB_DEBUG((CE_NOTE, "%s#%d: intr_types = 0x%x\n",
-	    ddi_driver_name(devi), ddi_get_instance(devi), intr_types));
-
-	if (pepb_msi_intr_supported(devi, intr_types) == DDI_SUCCESS) {
-		if (pepb_intr_init(pepb, DDI_INTR_TYPE_MSI) == DDI_SUCCESS)
-			goto next_step;
-		else
-			PEPB_DEBUG((CE_WARN,
-			    "%s#%d: Unable to attach MSI handler",
-			    ddi_driver_name(devi), ddi_get_instance(devi)));
-	}
-
-	/*
-	 * If we are here that means MSIs were not enabled. For errors fall back
-	 * to the SERR+Machinecheck approach on Intel chipsets.
-	 */
-	if (PCIE_IS_RP(bus_p))
-		pepb->pepb_no_aer_msi = B_TRUE;
-
-	/*
-	 * Only register hotplug interrupts for now.
-	 * Check if device supports PCIe hotplug or not?
-	 * If yes, register fixed interrupts if ILINE is valid.
-	 * Fix error handling for INTx.
-	 */
-	if (pepb->inband_hpc == INBAND_HPC_PCIE) {
-		uint8_t iline;
-
-		(void) pci_config_setup(devi, &config_handle);
-		iline = pci_config_get8(config_handle, PCI_CONF_ILINE);
-		pci_config_teardown(&config_handle);
-
-		if (iline == 0 || iline > 15)
-			goto next_step;
-
-		if (pepb_intr_init(pepb, DDI_INTR_TYPE_FIXED) != DDI_SUCCESS)
-			PEPB_DEBUG((CE_WARN,
-			    "%s#%d: Unable to attach INTx handler",
-			    ddi_driver_name(devi), ddi_get_instance(devi)));
-	}
-
-next_step:
-	/*
 	 * Initialize hotplug support on this bus. At minimum
 	 * (for non hotplug bus) this would create ":devctl" minor
 	 * node to support DEVCTL_DEVICE_* and DEVCTL_BUS_* ioctls
@@ -439,6 +392,71 @@
 		}
 	}
 
+	/*
+	 * Call _OSC method for 2 reasons:
+	 * 1. Hotplug: To determine if it is native or ACPI mode.
+	 *
+	 * 2. Error handling: Inform firmware that OS can support AER error
+	 * handling. Currently we don't care for what the BIOS response was
+	 * and instead setup interrupts for error handling as if it were
+	 * supported.
+	 *
+	 * For hotpluggable slots the _OSC method has already been called as
+	 * part of the hotplug initialization above.
+	 * For non-hotpluggable slots we need to call the _OSC method only for
+	 * Root Ports (for AER support).
+	 */
+	if (!pcie_is_osc(devi) && PCIE_IS_RP(bus_p) && PCIE_HAS_AER(bus_p)) {
+		uint32_t osc_flags = OSC_CONTROL_PCIE_ADV_ERR;
+		(void) pcie_acpi_osc(devi, &osc_flags);
+	}
+
+	/*
+	 * Initialize interrupt handlers.
+	 */
+	if (ddi_intr_get_supported_types(devi, &intr_types) != DDI_SUCCESS)
+		goto next_step;
+
+	PEPB_DEBUG((CE_NOTE, "%s#%d: intr_types = 0x%x\n",
+	    ddi_driver_name(devi), ddi_get_instance(devi), intr_types));
+
+	if (pepb_msi_intr_supported(devi, intr_types) == DDI_SUCCESS) {
+		if (pepb_intr_init(pepb, DDI_INTR_TYPE_MSI) == DDI_SUCCESS)
+			goto next_step;
+		else
+			PEPB_DEBUG((CE_WARN,
+			    "%s#%d: Unable to attach MSI handler",
+			    ddi_driver_name(devi), ddi_get_instance(devi)));
+	}
+
+	/*
+	 * If we are here that means MSIs were not enabled. For errors fall back
+	 * to the SERR+Machinecheck approach on certain Intel chipsets.
+	 */
+	if (PCIE_IS_RP(bus_p))
+		pepb->pepb_no_aer_msi = B_TRUE;
+
+	/*
+	 * Only register hotplug interrupts for now.
+	 * Check if device supports PCIe hotplug or not?
+	 * If yes, register fixed interrupts if ILINE is valid.
+	 * Fix error handling for INTx.
+	 */
+	if (pepb->inband_hpc == INBAND_HPC_PCIE) {
+		uint8_t iline;
+
+		iline = pci_config_get8(config_handle, PCI_CONF_ILINE);
+
+		if (iline == 0 || iline > 15)
+			goto next_step;
+
+		if (pepb_intr_init(pepb, DDI_INTR_TYPE_FIXED) != DDI_SUCCESS)
+			PEPB_DEBUG((CE_WARN,
+			    "%s#%d: Unable to attach INTx handler",
+			    ddi_driver_name(devi), ddi_get_instance(devi)));
+	}
+
+next_step:
 	/* Must apply workaround only after all initialization is done */
 	pepb_intel_serr_workaround(devi, pepb->pepb_no_aer_msi);
 	pepb_intel_rber_workaround(devi);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/intel/sys/pcie_acpi.h	Fri Apr 24 13:17:47 2009 -0700
@@ -0,0 +1,85 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_SYS_PCIE_ACPI_H
+#define	_SYS_PCIE_ACPI_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/* revision id of _OSC for PCI/PCI-X/PCI-Exp hierarchy */
+#define	PCIE_OSC_REVISION_ID	1	/* defined in PCI fw ver 3.0 */
+
+/*
+ * _OSC method Capabilities buffer bit definitions (from PCI FW 3.0)
+ */
+/* first DWORD: status from _OSC invocation (except bit 0) */
+#define	OSC_STATUS_QUERY_ENABLE	0x1	/* Query Support Flag */
+#define	OSC_STATUS_FAILED	0x2	/* _OSC failure */
+#define	OSC_STATUS_INV_UUID	0x4	/* invalid UUID */
+#define	OSC_STATUS_INV_REVID	0x8	/* invalid revision ID */
+#define	OSC_STATUS_CAPS_MASKED	0x10	/* capabilities masked */
+
+#define	OSC_STATUS_ERRORS \
+	(OSC_STATUS_FAILED | OSC_STATUS_INV_UUID | OSC_STATUS_INV_REVID)
+
+/* second DWORD: Support Field (set by OS) */
+#define	OSC_SUPPORT_EXT_PCI_CFG	0x1	/* Extended PCI Config Ops supported */
+#define	OSC_SUPPORT_ACT_PM	0x2	/* Active State PM supported */
+#define	OSC_SUPPORT_CLK_PM_CAP	0x4	/* Clock PM Capability supported */
+#define	OSC_SUPPORT_PCI_SEGS	0x8	/* PCI Segment Groups supported */
+#define	OSC_SUPPORT_MSI		0x10	/* MSI supported */
+
+/* third DWORD: Control Field (set by OS/BIOS) */
+#define	OSC_CONTROL_PCIE_NAT_HP	0x1	/* PCI Exp Native Hot Plug control */
+#define	OSC_CONTROL_SHPC_NAT_HP	0x2	/* SHPC Native Hot Plug control */
+#define	OSC_CONTROL_PCIE_NAT_PM	0x4	/* PCI Exp Native Power Mgmt. control */
+#define	OSC_CONTROL_PCIE_ADV_ERR 0x8	/* PCIE Advanced Err. rep. control */
+#define	OSC_CONTROL_PCIE_CAPS	0x10	/* PCIE Caps Structure control */
+
+#define	OSC_CONTROL_FIELD_INIT \
+	(OSC_CONTROL_PCIE_CAPS | OSC_CONTROL_PCIE_ADV_ERR)
+
+#define	OSC_SUPPORT_FIELD_INIT \
+	(OSC_SUPPORT_EXT_PCI_CFG | \
+	OSC_SUPPORT_ACT_PM | OSC_SUPPORT_CLK_PM_CAP | \
+	OSC_SUPPORT_MSI | OSC_SUPPORT_PCI_SEGS)
+
+typedef struct pcie_x86_priv {
+	/* _OSC related */
+	boolean_t	bus_osc;  	/* Has _OSC method been called */
+	boolean_t	bus_osc_hp;	/* Was native HP control granted */
+	boolean_t	bus_osc_aer;	/* Was AER control granted */
+} pcie_x86_priv_t;
+
+extern int pcie_acpi_osc(dev_info_t *dip, uint32_t *osc_flags);
+extern boolean_t pcie_is_osc(dev_info_t *dip);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_PCIE_ACPI_H */
--- a/usr/src/uts/sparc/Makefile.files	Fri Apr 24 10:24:29 2009 -0700
+++ b/usr/src/uts/sparc/Makefile.files	Fri Apr 24 13:17:47 2009 -0700
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #	This Makefile defines all file modules and build rules for the
@@ -65,6 +65,7 @@
 CPR_SPARC_OBJS +=	cpr_sparc.o
 PCI_PCI_OBJS +=		pci_pci.o pci_debug.o pci_pwr.o pcix.o
 PX_PCI_OBJS +=		px_pci.o pcie_pwr.o
+PCIE_MISC_OBJS += 	pcie_plat.o
 FCODE_OBJS +=		fcode.o
 NSKERN_OBJS +=		nsc_asm.o
 
--- a/usr/src/uts/sparc/Makefile.rules	Fri Apr 24 10:24:29 2009 -0700
+++ b/usr/src/uts/sparc/Makefile.rules	Fri Apr 24 13:17:47 2009 -0700
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #	This Makefile defines all file modules and build rules for the
@@ -48,6 +48,10 @@
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
 
+$(OBJS_DIR)/%.o:		$(UTSBASE)/sparc/io/pciex/%.c
+	$(COMPILE.c) -o $@ $<
+	$(CTFCONVERT_O)
+
 $(OBJS_DIR)/%.o:		$(UTSBASE)/sparc/fpu/%.c
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
@@ -101,6 +105,9 @@
 $(LINTS_DIR)/%.ln:		$(UTSBASE)/sparc/io/%.c
 	@($(LHEAD) $(LINT.c) $< $(LTAIL))
 
+$(LINTS_DIR)/%.ln:		$(UTSBASE)/sparc/io/pciex/%.c
+	@($(LHEAD) $(LINT.c) $< $(LTAIL))
+
 $(LINTS_DIR)/%.ln:		$(UTSBASE)/sparc/fpu/%.c
 	@($(LHEAD) $(LINT.c) $< $(LTAIL))
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/sparc/io/pciex/pcie_plat.c	Fri Apr 24 13:17:47 2009 -0700
@@ -0,0 +1,42 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/sunndi.h>
+#include <sys/pcie_impl.h>
+
+/* ARGSUSED */
+void
+pcie_init_plat(dev_info_t *dip)
+{
+}
+
+/* ARGSUSED */
+void
+pcie_fini_plat(dev_info_t *dip)
+{
+}
--- a/usr/src/uts/sparc/pcie/Makefile	Fri Apr 24 10:24:29 2009 -0700
+++ b/usr/src/uts/sparc/pcie/Makefile	Fri Apr 24 13:17:47 2009 -0700
@@ -20,10 +20,9 @@
 #
 #
 # uts/sparc/pcie/Makefile
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-#ident	"%Z%%M%	%I%	%E% SMI"
 #
 #	This makefile drives the production of the PCIE driver kernel module.
 #
@@ -39,8 +38,8 @@
 #	Define the module and object file sets.
 #
 MODULE		= pcie
-OBJECTS		= $(PCIE_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(PCIE_OBJS:%.o=$(LINTS_DIR)/%.ln)
+OBJECTS		= $(PCIE_MISC_OBJS:%=$(OBJS_DIR)/%)
+LINTS		= $(PCIE_MISC_OBJS:%.o=$(LINTS_DIR)/%.ln)
 ROOTMODULE	= $(ROOT_MISC_DIR)/$(MODULE)
 
 #