Beispiel #1
0
static int
acpi_pci_attach(device_t dev)
{
	int busno, domain, error;

	error = pci_attach_common(dev);
	if (error)
		return (error);

	/*
	 * Since there can be multiple independantly numbered PCI
	 * busses on systems with multiple PCI domains, we can't use
	 * the unit number to decide which bus we are probing. We ask
	 * the parent pcib what our domain and bus numbers are.
	 */
	domain = pcib_get_domain(dev);
	busno = pcib_get_bus(dev);

	/*
	 * First, PCI devices are added as in the normal PCI bus driver.
	 * Afterwards, the ACPI namespace under the bridge driver is
	 * walked to save ACPI handles to all the devices that appear in
	 * the ACPI namespace as immediate descendants of the bridge.
	 *
	 * XXX: Sometimes PCI devices show up in the ACPI namespace that
	 * pci_add_children() doesn't find.  We currently just ignore
	 * these devices.
	 */
	pci_add_children(dev, domain, busno, sizeof(struct acpi_pci_devinfo));
	AcpiWalkNamespace(ACPI_TYPE_DEVICE, acpi_get_handle(dev), 1,
	    acpi_pci_save_handle, NULL, dev, NULL);

	return (bus_generic_attach(dev));
}
Beispiel #2
0
ACPI_STATUS
AcpiDbFindNameInNamespace (
    char                    *NameArg)
{
    char                    AcpiName[5] = "____";
    char                    *AcpiNamePtr = AcpiName;


    if (strlen (NameArg) > 4)
    {
        AcpiOsPrintf ("Name must be no longer than 4 characters\n");
        return (AE_OK);
    }

    /* Pad out name with underscores as necessary to create a 4-char name */

    AcpiUtStrupr (NameArg);
    while (*NameArg)
    {
        *AcpiNamePtr = *NameArg;
        AcpiNamePtr++;
        NameArg++;
    }

    /* Walk the namespace from the root */

    (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
                        AcpiDbWalkAndMatchName, NULL, AcpiName, NULL);

    AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
    return (AE_OK);
}
Beispiel #3
0
void
AcpiDbGetBusInfo (
    void)
{
    /* Search all nodes in namespace */

    (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
                    AcpiDbBusWalk, NULL, NULL, NULL);
}
Beispiel #4
0
ACPI_STATUS
AcpiDsInitializeObjects (
    ACPI_NATIVE_UINT        TableIndex,
    ACPI_NAMESPACE_NODE     *StartNode)
{
    ACPI_STATUS             Status;
    ACPI_INIT_WALK_INFO     Info;
    ACPI_TABLE_HEADER       *Table;
    ACPI_OWNER_ID           OwnerId;


    ACPI_FUNCTION_TRACE (DsInitializeObjects);


    Status = AcpiTbGetOwnerId (TableIndex, &OwnerId);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
        "**** Starting initialization of namespace objects ****\n"));
    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "Parsing all Control Methods:"));

    Info.MethodCount    = 0;
    Info.OpRegionCount  = 0;
    Info.ObjectCount    = 0;
    Info.DeviceCount    = 0;
    Info.TableIndex     = TableIndex;
    Info.OwnerId        = OwnerId;

    /* Walk entire namespace from the supplied root */

    Status = AcpiWalkNamespace (ACPI_TYPE_ANY, StartNode, ACPI_UINT32_MAX,
                    AcpiDsInitOneObject, &Info, NULL);
    if (ACPI_FAILURE (Status))
    {
        ACPI_EXCEPTION ((AE_INFO, Status, "During WalkNamespace"));
    }

    Status = AcpiGetTableByIndex (TableIndex, &Table);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
        "\nTable [%4.4s](id %4.4X) - %hd Objects with %hd Devices %hd Methods %hd Regions\n",
        Table->Signature, OwnerId, Info.ObjectCount,
        Info.DeviceCount, Info.MethodCount, Info.OpRegionCount));

    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
        "%hd Methods, %hd Regions\n", Info.MethodCount, Info.OpRegionCount));

    return_ACPI_STATUS (AE_OK);
}
Beispiel #5
0
static void
AcpiDbTestAllObjects (
    void)
{
    ACPI_STATUS             Status;


    /* Install the debugger read-object control method if necessary */

    if (!ReadHandle)
    {
        Status = AcpiInstallMethod (ReadMethodCode);
        if (ACPI_FAILURE (Status))
        {
            AcpiOsPrintf ("%s, Could not install debugger read method\n",
                AcpiFormatException (Status));
            return;
        }

        Status = AcpiGetHandle (NULL, ACPI_DB_READ_METHOD, &ReadHandle);
        if (ACPI_FAILURE (Status))
        {
            AcpiOsPrintf ("Could not obtain handle for debug method %s\n",
                ACPI_DB_READ_METHOD);
            return;
        }
    }

    /* Install the debugger write-object control method if necessary */

    if (!WriteHandle)
    {
        Status = AcpiInstallMethod (WriteMethodCode);
        if (ACPI_FAILURE (Status))
        {
            AcpiOsPrintf ("%s, Could not install debugger write method\n",
                AcpiFormatException (Status));
            return;
        }

        Status = AcpiGetHandle (NULL, ACPI_DB_WRITE_METHOD, &WriteHandle);
        if (ACPI_FAILURE (Status))
        {
            AcpiOsPrintf ("Could not obtain handle for debug method %s\n",
                ACPI_DB_WRITE_METHOD);
            return;
        }
    }

    /* Walk the entire namespace, testing each supported named data object */

    (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
        ACPI_UINT32_MAX, AcpiDbTestOneObject, NULL, NULL, NULL);
}
static void
acpi_dock_eject_children(device_t dev)
{
	ACPI_HANDLE	sb_handle;
	ACPI_STATUS	status;

	status = AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &sb_handle);
	if (ACPI_SUCCESS(status)) {
		AcpiWalkNamespace(ACPI_TYPE_DEVICE, sb_handle,
		    100, acpi_dock_eject_child, &dev, NULL);
	}
}
Beispiel #7
0
void
AcpiDbCheckIntegrity (
    void)
{
    ACPI_INTEGRITY_INFO     Info = {0,0};

    /* Search all nodes in namespace */

    (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
                    AcpiDbIntegrityWalk, NULL, (void *) &Info, NULL);

    AcpiOsPrintf ("Verified %u namespace nodes with %u Objects\n",
        Info.Nodes, Info.Objects);
}
Beispiel #8
0
void
AcpiDbCheckPredefinedNames (
    void)
{
    UINT32                  Count = 0;


    /* Search all nodes in namespace */

    (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
                AcpiDbWalkForPredefinedNames, NULL, (void *) &Count, NULL);

    AcpiOsPrintf ("Found %u predefined names in the namespace\n", Count);
}
Beispiel #9
0
void
AcpiDbFindReferences (
    char                    *ObjectArg)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;


    /* Convert string to object pointer */

    ObjDesc = ACPI_TO_POINTER (ACPI_STRTOUL (ObjectArg, NULL, 16));

    /* Search all nodes in namespace */

    (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
                    AcpiDbWalkForReferences, NULL, (void *) ObjDesc, NULL);
}
Beispiel #10
0
void
AcpiDbEvaluatePredefinedNames (
    void)
{
    ACPI_DB_EXECUTE_WALK    Info;


    Info.Count = 0;
    Info.MaxCount = ACPI_UINT32_MAX;

    /* Search all nodes in namespace */

    (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
                AcpiDbWalkForExecute, NULL, (void *) &Info, NULL);

    AcpiOsPrintf ("Evaluated %u predefined names in the namespace\n", Info.Count);
}
Beispiel #11
0
ACPI_STATUS
AcpiNsInitializeObjects (
    void)
{
    ACPI_STATUS             Status;
    ACPI_INIT_WALK_INFO     Info;


    ACPI_FUNCTION_TRACE (NsInitializeObjects);


    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
        "[Init] Completing Initialization of ACPI Objects\n"));
    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
        "**** Starting initialization of namespace objects ****\n"));
    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
        "Completing Region/Field/Buffer/Package initialization:\n"));

    /* Set all init info to zero */

    memset (&Info, 0, sizeof (ACPI_INIT_WALK_INFO));

    /* Walk entire namespace from the supplied root */

    Status = AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
        ACPI_UINT32_MAX, AcpiNsInitOneObject, NULL,
        &Info, NULL);
    if (ACPI_FAILURE (Status))
    {
        ACPI_EXCEPTION ((AE_INFO, Status, "During WalkNamespace"));
    }

    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
        "    Initialized %u/%u Regions %u/%u Fields %u/%u "
        "Buffers %u/%u Packages (%u nodes)\n",
        Info.OpRegionInit,  Info.OpRegionCount,
        Info.FieldInit,     Info.FieldCount,
        Info.BufferInit,    Info.BufferCount,
        Info.PackageInit,   Info.PackageCount, Info.ObjectCount));

    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
        "%u Control Methods found\n%u Op Regions found\n",
        Info.MethodCount, Info.OpRegionCount));

    return_ACPI_STATUS (AE_OK);
}
Beispiel #12
0
ACPI_STATUS
AcpiDbDisplayObjects (
    char                    *ObjTypeArg,
    char                    *DisplayCountArg)
{
    ACPI_WALK_INFO          Info;
    ACPI_OBJECT_TYPE        Type;


    /* Get the object type */

    Type = AcpiDbMatchArgument (ObjTypeArg, AcpiDbObjectTypes);
    if (Type == ACPI_TYPE_NOT_FOUND)
    {
        AcpiOsPrintf ("Invalid or unsupported argument\n");
        return (AE_OK);
    }

    AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);
    AcpiOsPrintf (
        "Objects of type [%s] defined in the current ACPI Namespace:\n",
        AcpiUtGetTypeName (Type));

    AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);

    Info.Count = 0;
    Info.OwnerId = ACPI_OWNER_ID_MAX;
    Info.DebugLevel = ACPI_UINT32_MAX;
    Info.DisplayType = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT;

    /* Walk the namespace from the root */

    (void) AcpiWalkNamespace (Type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
                AcpiDbWalkForSpecificObjects, NULL, (void *) &Info, NULL);

    AcpiOsPrintf (
        "\nFound %u objects of type [%s] in the current ACPI Namespace\n",
        Info.Count, AcpiUtGetTypeName (Type));

    AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
    return (AE_OK);
}
Beispiel #13
0
ACPI_STATUS
AcpiDsInitializeObjects (
    ACPI_TABLE_DESC         *TableDesc,
    ACPI_NAMESPACE_NODE     *StartNode)
{
    ACPI_STATUS             Status;
    ACPI_INIT_WALK_INFO     Info;


    ACPI_FUNCTION_TRACE ("DsInitializeObjects");


    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
        "**** Starting initialization of namespace objects ****\n"));
    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "Parsing all Control Methods:"));

    Info.MethodCount    = 0;
    Info.OpRegionCount  = 0;
    Info.ObjectCount    = 0;
    Info.DeviceCount    = 0;
    Info.TableDesc      = TableDesc;

    /* Walk entire namespace from the supplied root */

    Status = AcpiWalkNamespace (ACPI_TYPE_ANY, StartNode, ACPI_UINT32_MAX,
                    AcpiDsInitOneObject, &Info, NULL);
    if (ACPI_FAILURE (Status))
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "WalkNamespace failed, %s\n",
            AcpiFormatException (Status)));
    }

    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
        "\nTable [%4.4s] - %hd Objects with %hd Devices %hd Methods %hd Regions\n",
        TableDesc->Pointer->Signature, Info.ObjectCount,
        Info.DeviceCount, Info.MethodCount, Info.OpRegionCount));

    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
        "%hd Methods, %hd Regions\n", Info.MethodCount, Info.OpRegionCount));

    return_ACPI_STATUS (AE_OK);
}
Beispiel #14
0
static void
AcpiDbEvaluateAllPredefinedNames (
    char                    *CountArg)
{
    ACPI_DB_EXECUTE_WALK    Info;


    Info.Count = 0;
    Info.MaxCount = ACPI_UINT32_MAX;

    if (CountArg)
    {
        Info.MaxCount = ACPI_STRTOUL (CountArg, NULL, 0);
    }

    /* Search all nodes in namespace */

    (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
                AcpiDbEvaluateOnePredefinedName, NULL, (void *) &Info, NULL);

    AcpiOsPrintf ("Evaluated %u predefined names in the namespace\n", Info.Count);
}
Beispiel #15
0
void
AcpiDbDisplayResources (
    char                    *ObjectArg)
{
    ACPI_NAMESPACE_NODE     *Node;


    AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);
    AcpiDbgLevel |= ACPI_LV_RESOURCES;

    /* Asterisk means "display resources for all devices" */

    if (!ObjectArg || (!strcmp (ObjectArg, "*")))
    {
        (void) AcpiWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
            ACPI_UINT32_MAX, AcpiDbDeviceResources, NULL, NULL, NULL);
    }
    else
    {
        /* Convert string to object pointer */

        Node = AcpiDbConvertToNode (ObjectArg);
        if (Node)
        {
            if (Node->Type != ACPI_TYPE_DEVICE)
            {
                AcpiOsPrintf (
                    "%4.4s: Name is not a device object (%s)\n",
                    Node->Name.Ascii, AcpiUtGetTypeName (Node->Type));
            }
            else
            {
                (void) AcpiDbDeviceResources (Node, 0, NULL, NULL);
            }
        }
    }

    AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
}
Beispiel #16
0
void
AcpiDbBatchExecute (
    char                    *CountArg)
{
    ACPI_EXECUTE_WALK       Info;


    Info.Count = 0;
    Info.MaxCount = ACPI_UINT32_MAX;

    if (CountArg)
    {
        Info.MaxCount = ACPI_STRTOUL (CountArg, NULL, 0);
    }


    /* Search all nodes in namespace */

    (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
                AcpiDbWalkForExecute, NULL, (void *) &Info, NULL);

    AcpiOsPrintf ("Executed %u predefined names in the namespace\n", Info.Count);
}
Beispiel #17
0
/* Test function that makes sure processors are under the _SB_ namespace. */
static int acpi_table_sbbr_namespace_check_test1(fwts_framework *fw)
{
	int error_count = 0;

	/* Initializing ACPICA library so we can call AcpiWalkNamespace. */
	if (fwts_acpica_init(fw) != FWTS_OK)
		return FWTS_ERROR;

	/* Searching for all processor devices in the namespace. */
	AcpiWalkNamespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
	                  processor_handler, NULL, NULL, (void **)&error_count);

	/* Deinitializing ACPICA, if we don't call this the terminal will break on exit. */
	fwts_acpica_deinit();

	/* error_count variable counts the number of processors outside of the _SB_ namespace. */
	if (error_count > 0)
		fwts_failed(fw, LOG_LEVEL_HIGH, "SbbrAcpiCpuWrongNamespace", "%d Processor devices "
		            "were found outside of the _SB_ namespace.", error_count);
	else
		fwts_passed(fw, "All processor devices were located in the _SB_ namespace.");

	return FWTS_OK;
}
Beispiel #18
0
void
AcpiDbExecute (
    char                    *Name,
    char                    **Args,
    UINT32                  Flags)
{
    ACPI_STATUS             Status;
    ACPI_BUFFER             ReturnObj;


#ifdef ACPI_DEBUG_OUTPUT
    UINT32                  PreviousAllocations;
    UINT32                  Allocations;


    /* Memory allocation tracking */

    PreviousAllocations = AcpiDbGetOutstandingAllocations ();
#endif

    if (*Name == '*')
    {
        (void) AcpiWalkNamespace (ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
                    AcpiDbExecutionWalk, NULL, NULL);
        return;
    }
    else
    {
        AcpiGbl_DbMethodInfo.Name = Name;
        AcpiGbl_DbMethodInfo.Args = Args;
        AcpiGbl_DbMethodInfo.Flags = Flags;

        ReturnObj.Pointer = NULL;
        ReturnObj.Length = ACPI_ALLOCATE_BUFFER;

        AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo);
        Status = AcpiDbExecuteMethod (&AcpiGbl_DbMethodInfo, &ReturnObj);
    }

    /*
     * Allow any handlers in separate threads to complete.
     * (Such as Notify handlers invoked from AML executed above).
     */
    AcpiOsSleep (0, 10);


#ifdef ACPI_DEBUG_OUTPUT

    /* Memory allocation tracking */

    Allocations = AcpiDbGetOutstandingAllocations () - PreviousAllocations;

    AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);

    if (Allocations > 0)
    {
        AcpiOsPrintf ("Outstanding: %ld allocations after execution\n",
                        Allocations);
    }
#endif

    if (ACPI_FAILURE (Status))
    {
        AcpiOsPrintf ("Execution of %s failed with status %s\n",
            AcpiGbl_DbMethodInfo.Pathname, AcpiFormatException (Status));
    }

    else
    {
        /* Display a return object, if any */

        if (ReturnObj.Length)
        {
            AcpiOsPrintf ("Execution of %s returned object %p Buflen %X\n",
                AcpiGbl_DbMethodInfo.Pathname, ReturnObj.Pointer,
                (UINT32) ReturnObj.Length);
            AcpiDbDumpObject (ReturnObj.Pointer, 1);
        }
        else
        {
            AcpiOsPrintf ("No return object from execution of %s\n",
                AcpiGbl_DbMethodInfo.Pathname);
        }
    }

    AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
}
Beispiel #19
0
/*
 * Initialize the CA subsystem if it hasn't been done already
 */
int
acpica_init()
{
	extern void acpica_find_ioapics(void);
	ACPI_STATUS status;

	/*
	 * Make sure user options are processed,
	 * then fail to initialize if ACPI CA has been
	 * disabled
	 */
	acpica_process_user_options();
	if (!acpica_enable)
		return (AE_ERROR);

	mutex_enter(&acpica_module_lock);
	if (acpica_init_state == ACPICA_INITIALIZED) {
		mutex_exit(&acpica_module_lock);
		return (AE_OK);
	}

	if (ACPI_FAILURE(status = AcpiLoadTables()))
		goto error;

	if (ACPI_FAILURE(status = acpica_install_handlers()))
		goto error;

	/*
	 * Create ACPI-to-devinfo mapping now so _INI and _STA
	 * methods can access PCI config space when needed
	 */
	scan_d2a_map();

	if (ACPI_FAILURE(status = AcpiEnableSubsystem(acpi_init_level)))
		goto error;

	/* do after AcpiEnableSubsystem() so GPEs are initialized */
	acpica_ec_init();	/* initialize EC if present */

	/* This runs all device _STA and _INI methods. */
	if (ACPI_FAILURE(status = AcpiInitializeObjects(0)))
		goto error;

	acpica_init_state = ACPICA_INITIALIZED;

	/*
	 * [ACPI, sec. 4.4.1.1]
	 * As of ACPICA version 20101217 (December 2010), the _PRW methods
	 * (Power Resources for Wake) are no longer automatically executed
	 * as part of the ACPICA initialization.  The OS must do this.
	 */
	(void) AcpiWalkNamespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
	    UINT32_MAX, acpica_init_PRW, NULL, NULL, NULL);
	(void) AcpiUpdateAllGpes();

	/*
	 * If we are running on the Xen hypervisor as dom0 we need to
	 * find the ioapics so we can prevent ACPI from trying to
	 * access them.
	 */
	if (get_hwenv() == HW_XEN_PV && is_controldom())
		acpica_find_ioapics();
	acpica_init_kstats();
error:
	if (acpica_init_state != ACPICA_INITIALIZED) {
		cmn_err(CE_NOTE, "!failed to initialize ACPI services");
	}

	/*
	 * Set acpi-status to 13 if acpica has been initialized successfully.
	 * This indicates that acpica is up and running.  This variable name
	 * and value were chosen in order to remain compatible with acpi_intp.
	 */
	e_ddi_prop_update_int(DDI_DEV_T_NONE, ddi_root_node(), "acpi-status",
	    (ACPI_SUCCESS(status)) ? (ACPI_BOOT_INIT | ACPI_BOOT_ENABLE |
	    ACPI_BOOT_BOOTCONF) : 0);

	/* Mark acpica subsystem as fully initialized. */
	if (ACPI_SUCCESS(status) &&
	    acpi_init_level == ACPI_FULL_INITIALIZATION) {
		acpica_set_core_feature(ACPI_FEATURE_FULL_INIT);
	}

	mutex_exit(&acpica_module_lock);
	return (status);
}
Beispiel #20
0
ACPI_STATUS
AcpiDbDisplayObjects (
    char                    *ObjTypeArg,
    char                    *DisplayCountArg)
{
    ACPI_WALK_INFO          Info;
    ACPI_OBJECT_TYPE        Type;
    ACPI_OBJECT_INFO        *ObjectInfo;
    UINT32                  i;
    UINT32                  TotalObjects = 0;


    /* No argument means display summary/count of all object types */

    if (!ObjTypeArg)
    {
        ObjectInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_OBJECT_INFO));

        /* Walk the namespace from the root */

        (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
            ACPI_UINT32_MAX, AcpiDbWalkForObjectCounts, NULL,
            (void *) ObjectInfo, NULL);

        AcpiOsPrintf ("\nSummary of namespace objects:\n\n");

        for (i = 0; i < ACPI_TOTAL_TYPES; i++)
        {
            AcpiOsPrintf ("%8u   %s\n", ObjectInfo->Types[i],
                AcpiUtGetTypeName (i));

            TotalObjects += ObjectInfo->Types[i];
        }

        AcpiOsPrintf ("\n%8u   Total namespace objects\n\n",
            TotalObjects);

        ACPI_FREE (ObjectInfo);
        return (AE_OK);
    }

    /* Get the object type */

    Type = AcpiDbMatchArgument (ObjTypeArg, AcpiDbObjectTypes);
    if (Type == ACPI_TYPE_NOT_FOUND)
    {
        AcpiOsPrintf ("Invalid or unsupported argument\n");
        return (AE_OK);
    }

    AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);
    AcpiOsPrintf (
        "Objects of type [%s] defined in the current ACPI Namespace:\n",
        AcpiUtGetTypeName (Type));

    AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);

    Info.Count = 0;
    Info.OwnerId = ACPI_OWNER_ID_MAX;
    Info.DebugLevel = ACPI_UINT32_MAX;
    Info.DisplayType = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT;

    /* Walk the namespace from the root */

    (void) AcpiWalkNamespace (Type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
        AcpiDbWalkForSpecificObjects, NULL, (void *) &Info, NULL);

    AcpiOsPrintf (
        "\nFound %u objects of type [%s] in the current ACPI Namespace\n",
        Info.Count, AcpiUtGetTypeName (Type));

    AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
    return (AE_OK);
}
Beispiel #21
0
void
acpi_secondary_init(void)
{
  ACPI_STATUS Status;
  ACPI_STATUS DisplayOneDevice (ACPI_HANDLE, UINT32, void *, void **);
  /* Complete the ACPICA initialization sequence */

  Status = AcpiInitializeSubsystem ();
  if (ACPI_FAILURE (Status)) {
    DLOG_COM1 ("Failed to initialize ACPI.\n");
  }
  Status = AcpiReallocateRootTable ();
  if (ACPI_FAILURE (Status)) {
    DLOG_COM1 ("Failed: AcpiReallocateRootTable %d.\n", Status);
  }
  Status = AcpiLoadTables ();
  if (ACPI_FAILURE (Status)) {
    DLOG_COM1 ("Failed: AcpiLoadTables.\n");
  }
  Status = AcpiEnableSubsystem (ACPI_FULL_INITIALIZATION);
  if (ACPI_FAILURE (Status)) {
    DLOG_COM1 ("Failed: AcpiEnableSubsystem.\n");
  }
  Status = AcpiInitializeObjects (ACPI_FULL_INITIALIZATION);
  if (ACPI_FAILURE (Status)) {
    DLOG_COM1 ("Failed: AcpiInitializeObjects.\n");
  }

  /* Must enable IOAPIC before checking any PCI routing tables. */
  acpi_enable_IOAPIC ();

  /* Install System Control Interrupt */
  u8 vector = find_unused_vector (MINIMUM_VECTOR_PRIORITY);
  if (vector) {
    u64 flags = IOAPIC_DELIVERY_FIXED | IOAPIC_DESTINATION_LOGICAL;
    u8 gsi = acpi_sci_irq;
    /* SCI defaults to LEVEL/LOW in IO-APIC mode. */
    if ((acpi_sci_flags & ACPI_MADT_POLARITY_MASK) == ACPI_MADT_POLARITY_ACTIVE_HIGH)
      flags |= IOAPIC_POLARITY_HIGH;
    else
      flags |= IOAPIC_POLARITY_LOW;
    if ((acpi_sci_flags & ACPI_MADT_TRIGGER_MASK) == ACPI_MADT_TRIGGER_EDGE)
      flags |= IOAPIC_TRIGGER_EDGE;
    else
      flags |= IOAPIC_TRIGGER_LEVEL;
    if (IOAPIC_map_GSI (gsi, vector, 0x0100000000000000ULL | flags) != -1) {
      set_vector_handler (vector, acpi_irq_handler);
      DLOG ("ACPI: mapped GSI 0x%X to vector 0x%X (%s, %s)\n",
                     gsi, vector,
                     flags & IOAPIC_TRIGGER_LEVEL ? "level" : "edge",
                     flags & IOAPIC_POLARITY_LOW ? "low" : "high");
    } else
      DLOG ("ACPI: failed to map GSI\n");
  } else
    DLOG ("ACPI: failed to find unused vector\n");

  DLOG ("AcpiEnableEvent returned %d\n",
                 AcpiEnableEvent (ACPI_EVENT_POWER_BUTTON, 0));
  DLOG ("AcpiInstallFixedEventHandler returned %d\n",
                 AcpiInstallFixedEventHandler (ACPI_EVENT_POWER_BUTTON, acpi_power_button, NULL));
  DLOG ("AcpiInstallNotifyHandler returned %d\n",
                 AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, acpi_notify_handler, NULL));
  DLOG ("AcpiInstallNotifyHandler returned %d\n",
                 AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_DEVICE_NOTIFY, acpi_notify_handler, NULL));

  extern u8 AcpiGbl_OsiData;
  AcpiGbl_OsiData=0;

  /* Walk the System Bus "\_SB_" and output info about each object
   * found. */

#if 0
  ACPI_HANDLE SysBusHandle;
  AcpiGetHandle (ACPI_ROOT_OBJECT, ACPI_NS_SYSTEM_BUS, &SysBusHandle);
  AcpiWalkNamespace (ACPI_TYPE_ANY, SysBusHandle, INT_MAX,
                     DisplayOneDevice, NULL, NULL);
#else
  AcpiGetDevices (NULL, DisplayOneDevice, NULL, NULL);
#endif
}
Beispiel #22
0
void
AcpiDbDisplayHandlers (
    void)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_OPERAND_OBJECT     *HandlerObj;
    ACPI_ADR_SPACE_TYPE     SpaceId;
    UINT32                  i;


    /* Operation region handlers */

    AcpiOsPrintf ("\nOperation Region Handlers at the namespace root:\n");

    ObjDesc = AcpiNsGetAttachedObject (AcpiGbl_RootNode);
    if (ObjDesc)
    {
        for (i = 0; i < ACPI_ARRAY_LENGTH (AcpiGbl_SpaceIdList); i++)
        {
            SpaceId = AcpiGbl_SpaceIdList[i];
            HandlerObj = ObjDesc->Device.Handler;

            AcpiOsPrintf (ACPI_PREDEFINED_PREFIX,
                AcpiUtGetRegionName ((UINT8) SpaceId), SpaceId);

            while (HandlerObj)
            {
                if (AcpiGbl_SpaceIdList[i] ==
                    HandlerObj->AddressSpace.SpaceId)
                {
                    AcpiOsPrintf (ACPI_HANDLER_PRESENT_STRING,
                        (HandlerObj->AddressSpace.HandlerFlags &
                            ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) ?
                            "Default" : "User",
                        HandlerObj->AddressSpace.Handler);

                    goto FoundHandler;
                }

                HandlerObj = HandlerObj->AddressSpace.Next;
            }

            /* There is no handler for this SpaceId */

            AcpiOsPrintf ("None\n");

        FoundHandler:;
        }

        /* Find all handlers for user-defined SpaceIDs */

        HandlerObj = ObjDesc->Device.Handler;
        while (HandlerObj)
        {
            if (HandlerObj->AddressSpace.SpaceId >= ACPI_USER_REGION_BEGIN)
            {
                AcpiOsPrintf (ACPI_PREDEFINED_PREFIX,
                    "User-defined ID", HandlerObj->AddressSpace.SpaceId);
                AcpiOsPrintf (ACPI_HANDLER_PRESENT_STRING,
                    (HandlerObj->AddressSpace.HandlerFlags &
                        ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) ?
                        "Default" : "User",
                    HandlerObj->AddressSpace.Handler);
            }

            HandlerObj = HandlerObj->AddressSpace.Next;
        }
    }

#if (!ACPI_REDUCED_HARDWARE)

    /* Fixed event handlers */

    AcpiOsPrintf ("\nFixed Event Handlers:\n");

    for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++)
    {
        AcpiOsPrintf (ACPI_PREDEFINED_PREFIX, AcpiUtGetEventName (i), i);
        if (AcpiGbl_FixedEventHandlers[i].Handler)
        {
            AcpiOsPrintf (ACPI_HANDLER_PRESENT_STRING, "User",
                AcpiGbl_FixedEventHandlers[i].Handler);
        }
        else
        {
            AcpiOsPrintf (ACPI_HANDLER_NOT_PRESENT_STRING, "None");
        }
    }

#endif /* !ACPI_REDUCED_HARDWARE */

    /* Miscellaneous global handlers */

    AcpiOsPrintf ("\nMiscellaneous Global Handlers:\n");

    for (i = 0; i < ACPI_ARRAY_LENGTH (AcpiGbl_HandlerList); i++)
    {
        AcpiOsPrintf (ACPI_HANDLER_NAME_STRING,
            AcpiGbl_HandlerList[i].Name);

        if (AcpiGbl_HandlerList[i].Handler)
        {
            AcpiOsPrintf (ACPI_HANDLER_PRESENT_STRING, "User",
                AcpiGbl_HandlerList[i].Handler);
        }
        else
        {
            AcpiOsPrintf (ACPI_HANDLER_NOT_PRESENT_STRING, "None");
        }
    }


    /* Other handlers that are installed throughout the namespace */

    AcpiOsPrintf ("\nOperation Region Handlers for specific devices:\n");

    (void) AcpiWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
        ACPI_UINT32_MAX, AcpiDbDisplayNonRootHandlers,
        NULL, NULL, NULL);
}
Beispiel #23
0
/*
 * Event handler for BUS_CHECK/DEVICE_CHECK/DEVICE_CHECK_LIGHT notifications.
 * These events may be signaled on parent/ancestor of devices to be hot-added,
 * so need to scan ACPI namespace to figure out devices in question.
 * It also invokes ACPI _OST method to update event status if call_ost is true.
 */
static void
acpinex_event_handle_check_request(int event, ACPI_HANDLE hdl,
    acpinex_softstate_t *sp, boolean_t call_ost)
{
	ACPI_STATUS rv;
	int code;
	char *objname;
	struct acpinex_event_check_arg arg;

	ASSERT(hdl != NULL);
	objname = acpidev_get_object_name(hdl);

	ASSERT(sp != NULL);
	ASSERT(sp->ans_dip != NULL && sp->ans_hdl != NULL);
	if (sp == NULL || sp->ans_dip == NULL || sp->ans_hdl == NULL) {
		if (call_ost) {
			(void) acpidev_eval_ost(hdl, event,
			    ACPI_OST_STA_FAILURE, NULL, 0);
		}
		ACPINEX_DEBUG(CE_WARN,
		    "!acpinex: softstate data structure is invalid.");
		cmn_err(CE_WARN, "!acpinex: failed to handle "
		    "BUS/DEVICE_CHECK event from %s.", objname);
		acpidev_free_object_name(objname);
		return;
	}

	bzero(&arg, sizeof (arg));
	arg.event_type = event;
	arg.softstatep = sp;
	rv = acpinex_event_handle_check_one(hdl, 0, &arg, NULL);
	if (ACPI_SUCCESS(rv)) {
		rv = AcpiWalkNamespace(ACPI_TYPE_DEVICE, hdl,
		    ACPIDEV_MAX_ENUM_LEVELS,
		    &acpinex_event_handle_check_one, NULL, &arg, NULL);
	}

	if (ACPI_FAILURE(rv)) {
		/* Failed to scan the ACPI namespace. */
		cmn_err(CE_WARN, "!acpinex: failed to handle event %d from %s.",
		    event, objname);
		code = ACPI_OST_STA_FAILURE;
	} else if (arg.device_remove != 0) {
		/* Surprising removal happened. */
		ACPINEX_DEBUG(CE_WARN,
		    "!acpinex: some devices have been surprisingly removed.");
		code = ACPI_OST_STA_NOT_SUPPORT;
	} else if (arg.device_fail != 0) {
		/* Failed to handle some devices. */
		ACPINEX_DEBUG(CE_WARN,
		    "!acpinex: failed to check status of some devices.");
		code = ACPI_OST_STA_FAILURE;
	} else if (arg.device_insert == 0) {
		/* No hot-added devices found. */
		cmn_err(CE_WARN,
		    "!acpinex: no hot-added devices under %s found.", objname);
		code = ACPI_OST_STA_FAILURE;
	} else {
		code = ACPI_OST_STA_INSERT_IN_PROGRESS;
	}
	if (call_ost) {
		(void) acpidev_eval_ost(hdl, event, code, NULL, 0);
	}

	acpidev_free_object_name(objname);
}
Beispiel #24
0
static void
sony_acpi_attach(device_t parent, device_t self, void *aux)
{
	struct sony_acpi_softc *sc = device_private(self);
	struct acpi_attach_args *aa = aux;
	ACPI_STATUS rv;
	int i;

	aprint_naive(": Sony Miscellaneous Controller\n");
	aprint_normal(": Sony Miscellaneous Controller\n");

	sc->sc_node = aa->aa_node;
	sc->sc_dev = self;

	rv = AcpiWalkNamespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 100,
	    sony_acpi_find_pic, sc, NULL);
	if (ACPI_FAILURE(rv))
		aprint_error_dev(self, "couldn't walk namespace: %s\n",
		    AcpiFormatException(rv));

	/*
	 * If we don't find an SNY6001 device, assume that we need the
	 * Fn key initialization sequence.
	 */
	if (sc->sc_has_pic == false)
		sc->sc_quirks |= SONY_ACPI_QUIRK_FNINIT;

	sony_acpi_quirk_setup(sc);

	/* Configure suspend button and hotkeys */
	sc->sc_smpsw[SONY_PSW_SLEEP].smpsw_name = device_xname(self);
	sc->sc_smpsw[SONY_PSW_SLEEP].smpsw_type = PSWITCH_TYPE_SLEEP;
	sc->sc_smpsw[SONY_PSW_DISPLAY_CYCLE].smpsw_name =
	    PSWITCH_HK_DISPLAY_CYCLE;
	sc->sc_smpsw[SONY_PSW_DISPLAY_CYCLE].smpsw_type = PSWITCH_TYPE_HOTKEY;
	sc->sc_smpsw[SONY_PSW_ZOOM].smpsw_name = PSWITCH_HK_ZOOM_BUTTON;
	sc->sc_smpsw[SONY_PSW_ZOOM].smpsw_type = PSWITCH_TYPE_HOTKEY;
	sc->sc_smpsw_valid = 1;

	for (i = 0; i < SONY_PSW_LAST; i++)
		if (sysmon_pswitch_register(&sc->sc_smpsw[i]) != 0) {
			aprint_error_dev(self, 
			    "couldn't register %s with sysmon\n",
			    sc->sc_smpsw[i].smpsw_name);
			sc->sc_smpsw_valid = 0;
		}

	/* Install notify handler */
	rv = AcpiInstallNotifyHandler(sc->sc_node->ad_handle,
	    ACPI_DEVICE_NOTIFY, sony_acpi_notify_handler, self);
	if (ACPI_FAILURE(rv))
		aprint_error_dev(self,
		    "couldn't install notify handler (%d)\n", rv);

	/* Install sysctl handler */
	rv = AcpiWalkNamespace(ACPI_TYPE_METHOD,
	    sc->sc_node->ad_handle, 1, sony_walk_cb, sc, NULL);
#ifdef DIAGNOSTIC
	if (ACPI_FAILURE(rv))
		aprint_error_dev(self, "Cannot walk ACPI namespace (%d)\n",
		    rv);
#endif

	if (!pmf_device_register(self, sony_acpi_suspend, sony_acpi_resume))
		aprint_error_dev(self, "couldn't establish power handler\n");

	if (!pmf_event_register(self, PMFE_DISPLAY_BRIGHTNESS_UP,
				 sony_acpi_brightness_up, true))
		aprint_error_dev(self, "couldn't register BRIGHTNESS UP handler\n");

	if (!pmf_event_register(self, PMFE_DISPLAY_BRIGHTNESS_DOWN,
				 sony_acpi_brightness_down, true))
		aprint_error_dev(self, "couldn't register BRIGHTNESS DOWN handler\n");
}
Beispiel #25
0
void
AcpiDbExecute (
    char                    *Name,
    char                    **Args,
    ACPI_OBJECT_TYPE        *Types,
    UINT32                  Flags)
{
    ACPI_STATUS             Status;
    ACPI_BUFFER             ReturnObj;
    char                    *NameString;


#ifdef ACPI_DEBUG_OUTPUT
    UINT32                  PreviousAllocations;
    UINT32                  Allocations;


    /* Memory allocation tracking */

    PreviousAllocations = AcpiDbGetOutstandingAllocations ();
#endif

    if (*Name == '*')
    {
        (void) AcpiWalkNamespace (ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT,
                    ACPI_UINT32_MAX, AcpiDbExecutionWalk, NULL, NULL, NULL);
        return;
    }
    else
    {
        NameString = ACPI_ALLOCATE (ACPI_STRLEN (Name) + 1);
        if (!NameString)
        {
            return;
        }

        ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO));

        ACPI_STRCPY (NameString, Name);
        AcpiUtStrupr (NameString);
        AcpiGbl_DbMethodInfo.Name = NameString;
        AcpiGbl_DbMethodInfo.Args = Args;
        AcpiGbl_DbMethodInfo.Types = Types;
        AcpiGbl_DbMethodInfo.Flags = Flags;

        ReturnObj.Pointer = NULL;
        ReturnObj.Length = ACPI_ALLOCATE_BUFFER;

        Status = AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo);
        if (ACPI_FAILURE (Status))
        {
            ACPI_FREE (NameString);
            return;
        }

        /* Get the NS node, determines existence also */

        Status = AcpiGetHandle (NULL, AcpiGbl_DbMethodInfo.Pathname,
            &AcpiGbl_DbMethodInfo.Method);
        if (ACPI_SUCCESS (Status))
        {
            Status = AcpiDbExecuteMethod (&AcpiGbl_DbMethodInfo, &ReturnObj);
        }
        ACPI_FREE (NameString);
    }

    /*
     * Allow any handlers in separate threads to complete.
     * (Such as Notify handlers invoked from AML executed above).
     */
    AcpiOsSleep ((UINT64) 10);

#ifdef ACPI_DEBUG_OUTPUT

    /* Memory allocation tracking */

    Allocations = AcpiDbGetOutstandingAllocations () - PreviousAllocations;

    AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);

    if (Allocations > 0)
    {
        AcpiOsPrintf ("0x%X Outstanding allocations after evaluation of %s\n",
                        Allocations, AcpiGbl_DbMethodInfo.Pathname);
    }
#endif

    if (ACPI_FAILURE (Status))
    {
        AcpiOsPrintf ("Evaluation of %s failed with status %s\n",
            AcpiGbl_DbMethodInfo.Pathname, AcpiFormatException (Status));
    }
    else
    {
        /* Display a return object, if any */

        if (ReturnObj.Length)
        {
            AcpiOsPrintf (
                "Evaluation of %s returned object %p, external buffer length %X\n",
                AcpiGbl_DbMethodInfo.Pathname, ReturnObj.Pointer,
                (UINT32) ReturnObj.Length);
            AcpiDbDumpExternalObject (ReturnObj.Pointer, 1);

            /* Dump a _PLD buffer if present */

            if (ACPI_COMPARE_NAME ((ACPI_CAST_PTR (ACPI_NAMESPACE_NODE,
                    AcpiGbl_DbMethodInfo.Method)->Name.Ascii), METHOD_NAME__PLD))
            {
                AcpiDbDumpPldBuffer (ReturnObj.Pointer);
            }
        }
        else
        {
            AcpiOsPrintf ("No object was returned from evaluation of %s\n",
                AcpiGbl_DbMethodInfo.Pathname);
        }
    }

    AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
}
Beispiel #26
0
static zx_status_t pciroot_op_get_auxdata(void* context, const char* args,
                                          void* data, size_t bytes,
                                          size_t* actual) {
    acpi_device_t* dev = (acpi_device_t*)context;

    char type[16];
    uint32_t bus_id, dev_id, func_id;
    int n;
    if ((n = sscanf(args, "%[^,],%02x:%02x:%02x", type, &bus_id, &dev_id, &func_id)) != 4) {
        return ZX_ERR_INVALID_ARGS;
    }

    zxlogf(SPEW, "bus-acpi: get_auxdata type '%s' device %02x:%02x:%02x\n", type,
           bus_id, dev_id, func_id);

    if (strcmp(type, "i2c-child")) {
        return ZX_ERR_NOT_SUPPORTED;
    }

    if (bytes < (2 * sizeof(uint32_t))) {
        return ZX_ERR_BUFFER_TOO_SMALL;
    }

    ACPI_HANDLE pci_node = NULL;
    uint32_t addr = (dev_id << 16) | func_id;

    // Look for the child node with this device and function id
    ACPI_STATUS acpi_status = AcpiWalkNamespace(ACPI_TYPE_DEVICE, dev->ns_node, 1,
                                                find_pci_child_callback, NULL,
                                                &addr, &pci_node);
    if ((acpi_status != AE_OK) && (acpi_status != AE_CTRL_TERMINATE)) {
        return acpi_to_zx_status(acpi_status);
    }
    if (pci_node == NULL) {
        return ZX_ERR_NOT_FOUND;
    }

    memset(data, 0, bytes);

    // Look for as many children as can fit in the provided buffer
    pci_child_auxdata_ctx_t ctx = {
        .max = static_cast<uint8_t>(bytes / sizeof(auxdata_i2c_device_t)),
        .i = 0,
        .data = static_cast<auxdata_i2c_device_t*>(data),
    };

    acpi_status = AcpiWalkNamespace(ACPI_TYPE_DEVICE, pci_node, 1,
                                    pci_child_data_callback, NULL, &ctx, NULL);
    if ((acpi_status != AE_OK) && (acpi_status != AE_CTRL_TERMINATE)) {
        *actual = 0;
        return acpi_to_zx_status(acpi_status);
    }

    *actual = ctx.i * sizeof(auxdata_i2c_device_t);

    zxlogf(SPEW, "bus-acpi: get_auxdata '%s' %u devs actual %zu\n",
           args, ctx.i, *actual);

    return ZX_OK;
}

static zx_status_t pciroot_op_get_bti(void* context, uint32_t bdf, uint32_t index,
                                      zx_handle_t* bti) {
    // The x86 IOMMU world uses PCI BDFs as the hardware identifiers, so there
    // will only be one BTI per device.
    if (index != 0) {
        return ZX_ERR_OUT_OF_RANGE;
    }
    // For dummy IOMMUs, the bti_id just needs to be unique.  For Intel IOMMUs,
    // the bti_ids correspond to PCI BDFs.
    zx_handle_t iommu_handle;
    zx_status_t status = iommu_manager_iommu_for_bdf(bdf, &iommu_handle);
    if (status != ZX_OK) {
        return status;
    }
    return zx_bti_create(iommu_handle, 0, bdf, bti);
}

#ifdef ENABLE_USER_PCI
static zx_status_t pciroot_op_get_pci_platform_info(void* ctx, pci_platform_info_t* info) {
    pciroot_ctx_t* pciroot = static_cast<pciroot_ctx_t*>(ctx);
    *info = pciroot->info;
    return ZX_OK;
}