fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango/*
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * CDDL HEADER START
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango *
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * The contents of this file are subject to the terms of the
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * Common Development and Distribution License (the "License").
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * You may not use this file except in compliance with the License.
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango *
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * or http://www.opensolaris.org/os/licensing.
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * See the License for the specific language governing permissions
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * and limitations under the License.
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango *
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * When distributing Covered Code, include this CDDL HEADER in each
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * If applicable, add the following below this CDDL HEADER, with the
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * fields enclosed by brackets "[]" replaced with your own identifying
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * information: Portions Copyright [yyyy] [name of copyright owner]
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango *
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * CDDL HEADER END
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango/*
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * Use is subject to license terms.
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango#include <sys/sysmacros.h>
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango#include <sys/types.h>
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango#include <sys/kmem.h>
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango#include <sys/ddi.h>
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango#include <sys/sunddi.h>
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango#include <sys/sunndi.h>
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango#include <sys/promif.h>
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango#include <sys/pcie.h>
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango#include <sys/pci_cap.h>
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango#include <sys/pcie_impl.h>
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango#include <sys/pcie_acpi.h>
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango#include <sys/acpi/acpi.h>
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango#include <sys/acpica.h>
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna ElangoACPI_STATUS pcie_acpi_eval_osc(dev_info_t *dip, ACPI_HANDLE osc_hdl,
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango uint32_t *osc_flags);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elangostatic ACPI_STATUS pcie_acpi_find_osc(ACPI_HANDLE busobj,
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango ACPI_HANDLE *osc_hdlp);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango#ifdef DEBUG
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elangostatic void pcie_dump_acpi_obj(ACPI_HANDLE pcibus_obj);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elangostatic ACPI_STATUS pcie_walk_obj_namespace(ACPI_HANDLE hdl, uint32_t nl,
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango void *context, void **ret);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elangostatic ACPI_STATUS pcie_print_acpi_name(ACPI_HANDLE hdl, uint32_t nl,
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango void *context, void **ret);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango#endif /* DEBUG */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elangoint
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elangopcie_acpi_osc(dev_info_t *dip, uint32_t *osc_flags)
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango{
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango ACPI_HANDLE pcibus_obj;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango int status = AE_ERROR;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango ACPI_HANDLE osc_hdl;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango pcie_bus_t *bus_p = PCIE_DIP2BUS(dip);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango pcie_x86_priv_t *osc_p = (pcie_x86_priv_t *)bus_p->bus_plat_private;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /* Mark this so we know _OSC has been called for this device */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango osc_p->bus_osc = B_TRUE;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /*
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * (1) Find the ACPI device node for this bus node.
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango status = acpica_get_handle(dip, &pcibus_obj);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango if (status != AE_OK) {
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango PCIE_DBG("No ACPI device found (dip %p)\n", (void *)dip);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango return (DDI_FAILURE);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango }
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /*
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * (2) Check if _OSC method is present.
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango if (pcie_acpi_find_osc(pcibus_obj, &osc_hdl) != AE_OK) {
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /* no _OSC method present */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango PCIE_DBG("no _OSC method present for dip %p\n",
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango (void *)dip);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango return (DDI_FAILURE);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango }
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /*
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * (3) _OSC method exists; evaluate _OSC.
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango if (pcie_acpi_eval_osc(dip, osc_hdl, osc_flags) != AE_OK) {
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango PCIE_DBG("Failed to evaluate _OSC method for dip 0x%p\n",
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango (void *)dip);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango return (DDI_FAILURE);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango }
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango osc_p->bus_osc_hp = (*osc_flags & OSC_CONTROL_PCIE_NAT_HP) ?
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango B_TRUE : B_FALSE;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango osc_p->bus_osc_aer = (*osc_flags & OSC_CONTROL_PCIE_ADV_ERR) ?
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango B_TRUE : B_FALSE;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango#ifdef DEBUG
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango if (pcie_debug_flags > 1)
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango pcie_dump_acpi_obj(pcibus_obj);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango#endif /* DEBUG */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango return (DDI_SUCCESS);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango}
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elangostatic ACPI_STATUS
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elangopcie_acpi_find_osc(ACPI_HANDLE busobj, ACPI_HANDLE *osc_hdlp)
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango{
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango ACPI_HANDLE parentobj = busobj;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango ACPI_STATUS status = AE_NOT_FOUND;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango *osc_hdlp = NULL;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /*
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * Walk up the ACPI device tree looking for _OSC method.
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango do {
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango busobj = parentobj;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango if ((status = AcpiGetHandle(busobj, "_OSC", osc_hdlp)) == AE_OK)
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango break;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango } while (AcpiGetParent(busobj, &parentobj) == AE_OK);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango if (*osc_hdlp == NULL)
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango status = AE_NOT_FOUND;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango return (status);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango}
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango/* UUID for for PCI/PCI-X/PCI-Exp hierarchy as defined in PCI fw ver 3.0 */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elangostatic uint8_t pcie_uuid[16] =
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango {0x5b, 0x4d, 0xdb, 0x33, 0xf7, 0x1f, 0x1c, 0x40,
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango 0x96, 0x57, 0x74, 0x41, 0xc0, 0x3d, 0xd7, 0x66};
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango/*
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * Evaluate _OSC method.
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna ElangoACPI_STATUS
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elangopcie_acpi_eval_osc(dev_info_t *dip, ACPI_HANDLE osc_hdl, uint32_t *osc_flags)
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango{
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango ACPI_STATUS status;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango ACPI_OBJECT_LIST arglist;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango ACPI_OBJECT args[4];
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango UINT32 caps_buffer[3];
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango ACPI_BUFFER rb;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango UINT32 *rbuf;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango UINT32 tmp_ctrl;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /* construct argument list */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango arglist.Count = 4;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango arglist.Pointer = args;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /* arg0 - UUID */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango args[0].Type = ACPI_TYPE_BUFFER;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango args[0].Buffer.Length = 16; /* size of UUID string */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango args[0].Buffer.Pointer = pcie_uuid;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /* arg1 - Revision ID */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango args[1].Type = ACPI_TYPE_INTEGER;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango args[1].Integer.Value = PCIE_OSC_REVISION_ID;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /* arg2 - Count */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango args[2].Type = ACPI_TYPE_INTEGER;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango args[2].Integer.Value = 3; /* no. of DWORDS in caps_buffer */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /* arg3 - Capabilities Buffer */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango args[3].Type = ACPI_TYPE_BUFFER;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango args[3].Buffer.Length = 12;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango args[3].Buffer.Pointer = (void *)caps_buffer;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /* Initialize Capabilities Buffer */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /* DWORD1: no query flag set */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango caps_buffer[0] = 0;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /* DWORD2: Support Field */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango caps_buffer[1] = OSC_SUPPORT_FIELD_INIT;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /* DWORD3: Control Field */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango caps_buffer[2] = OSC_CONTROL_FIELD_INIT;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /* If hotplug is supported add the corresponding control fields */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango if (*osc_flags & OSC_CONTROL_PCIE_NAT_HP)
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango caps_buffer[2] |= (OSC_CONTROL_PCIE_NAT_HP |
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango OSC_CONTROL_PCIE_NAT_PM);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango tmp_ctrl = caps_buffer[2];
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango rb.Length = ACPI_ALLOCATE_BUFFER;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango rb.Pointer = NULL;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango status = AcpiEvaluateObjectTyped(osc_hdl, NULL, &arglist, &rb,
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango ACPI_TYPE_BUFFER);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango if (status != AE_OK) {
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango PCIE_DBG("Failed to execute _OSC method (status %d)\n",
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango status);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango return (status);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango }
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /* LINTED pointer alignment */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango rbuf = (UINT32 *)((ACPI_OBJECT *)rb.Pointer)->Buffer.Pointer;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /* check the STATUS word in the capability buffer */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango if (rbuf[0] & OSC_STATUS_ERRORS) {
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango PCIE_DBG("_OSC method failed (STATUS %d)\n", rbuf[0]);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango AcpiOsFree(rb.Pointer);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango return (AE_ERROR);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango }
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango *osc_flags = rbuf[2];
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango PCIE_DBG("_OSC method evaluation completed for 0x%p: "
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango "STATUS 0x%x SUPPORT 0x%x CONTROL req 0x%x, CONTROL ret 0x%x\n",
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango (void *)dip, rbuf[0], rbuf[1], tmp_ctrl, rbuf[2]);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango AcpiOsFree(rb.Pointer);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango return (AE_OK);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango}
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango/*
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango * Checks if _OSC method has been called for this device.
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elangoboolean_t
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elangopcie_is_osc(dev_info_t *dip)
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango{
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango pcie_bus_t *bus_p = PCIE_DIP2BUS(dip);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango pcie_x86_priv_t *osc_p = (pcie_x86_priv_t *)bus_p->bus_plat_private;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango return (osc_p->bus_osc);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango}
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango#ifdef DEBUG
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elangostatic void
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elangopcie_dump_acpi_obj(ACPI_HANDLE pcibus_obj)
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango{
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango int status;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango ACPI_BUFFER retbuf;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango if (pcibus_obj == NULL)
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango return;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /* print the full path name */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango retbuf.Pointer = NULL;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango retbuf.Length = ACPI_ALLOCATE_BUFFER;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango status = AcpiGetName(pcibus_obj, ACPI_FULL_PATHNAME, &retbuf);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango if (status != AE_OK)
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango return;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango PCIE_DBG("PCIE BUS PATHNAME: %s\n", (char *)retbuf.Pointer);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango AcpiOsFree(retbuf.Pointer);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /* dump all the methods for this bus node */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango PCIE_DBG(" METHODS: \n");
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango status = AcpiWalkNamespace(ACPI_TYPE_METHOD, pcibus_obj, 1,
571909175b4f9a1ef15ec4afead6d6d463dbe760Dana Myers pcie_print_acpi_name, NULL, " ", NULL);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /* dump all the child devices */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango status = AcpiWalkNamespace(ACPI_TYPE_DEVICE, pcibus_obj, 1,
571909175b4f9a1ef15ec4afead6d6d463dbe760Dana Myers pcie_walk_obj_namespace, NULL, NULL, NULL);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango}
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango/*ARGSUSED*/
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elangostatic ACPI_STATUS
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elangopcie_walk_obj_namespace(ACPI_HANDLE hdl, uint32_t nl, void *context,
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango void **ret)
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango{
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango int status;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango ACPI_BUFFER retbuf;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango char buf[32];
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /* print the full path name */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango retbuf.Pointer = NULL;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango retbuf.Length = ACPI_ALLOCATE_BUFFER;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango status = AcpiGetName(hdl, ACPI_FULL_PATHNAME, &retbuf);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango if (status != AE_OK)
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango return (status);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango buf[0] = 0;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango while (nl--)
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango (void) strcat(buf, " ");
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango PCIE_DBG("%sDEVICE: %s\n", buf, (char *)retbuf.Pointer);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango AcpiOsFree(retbuf.Pointer);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango /* dump all the methods for this device */
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango PCIE_DBG("%s METHODS: \n", buf);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango status = AcpiWalkNamespace(ACPI_TYPE_METHOD, hdl, 1,
571909175b4f9a1ef15ec4afead6d6d463dbe760Dana Myers pcie_print_acpi_name, NULL, (void *)buf, NULL);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango return (status);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango}
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango/*ARGSUSED*/
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elangostatic ACPI_STATUS
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elangopcie_print_acpi_name(ACPI_HANDLE hdl, uint32_t nl, void *context, void **ret)
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango{
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango int status;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango ACPI_BUFFER retbuf;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango char name[16];
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango retbuf.Pointer = name;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango retbuf.Length = 16;
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango status = AcpiGetName(hdl, ACPI_SINGLE_NAME, &retbuf);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango if (status == AE_OK)
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango PCIE_DBG("%s %s \n", (char *)context, name);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango return (AE_OK);
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango}
fc51f9bbbff02dbd8c3adf640b1a184ceeb58fa5Krishna Elango#endif /* DEBUG */