FreeBSD/sys/contrib/dev/acpica/components/resources/rscreate.c
/*******************************************************************************
 *
 * FUNCTION:    AcpiRsCreatePciRoutingTable
 *
 * PARAMETERS:  PackageObject           - Pointer to a package containing one
 *                                        of more ACPI_OPERAND_OBJECTs
 *              OutputBuffer            - Pointer to the user's buffer
 *
 * RETURN:      Status  AE_OK if okay, else a valid ACPI_STATUS code.
 *              If the OutputBuffer is too small, the error will be
 *              AE_BUFFER_OVERFLOW and OutputBuffer->Length will point
 *              to the size buffer needed.
 *
 * DESCRIPTION: Takes the ACPI_OPERAND_OBJECT package and creates a
 *              linked list of PCI interrupt descriptions
 *
 * NOTE: It is the caller's responsibility to ensure that the start of the
 * output buffer is aligned properly (if necessary).
 *
 ******************************************************************************/
AcpiRsCreatePciRoutingTable
PARAMETERS:  PackageObject           - Pointer to a package containing one
of more ACPI_OPERAND_OBJECTs
OutputBuffer            - Pointer to the user's buffer

Status  AE_OK if okay, else a valid ACPI_STATUS code.
If the OutputBuffer is too small, the error will be
AE_BUFFER_OVERFLOW and OutputBuffer->Length will point
to the size buffer needed.

Takes the ACPI_OPERAND_OBJECT package and creates a
linked list of PCI interrupt descriptions

It is the caller's responsibility to ensure that the start of the
output buffer is aligned properly (if necessary).
AcpiRsCreatePciRoutingTable PARAMETERS : PackageObject - Pointer to a package containing one of more ACPI_OPERAND_OBJECTs OutputBuffer - Pointer to the user ' s buffer Status AE_OK if okay else a valid ACPI_STATUS code . If the OutputBuffer is too small the error will be AE_BUFFER_OVERFLOW and OutputBuffer - > Length will point to the size buffer needed . Takes the ACPI_OPERAND_OBJECT package and creates a linked list of PCI interrupt descriptions It is the caller ' s responsibility to ensure that the start of the output buffer is aligned properly ( if necessary ) .
ACPI_STATUS
AcpiRsCreatePciRoutingTable (
    ACPI_OPERAND_OBJECT     *PackageObject,
    ACPI_BUFFER             *OutputBuffer)
{
    UINT8                   *Buffer;
    ACPI_OPERAND_OBJECT     **TopObjectList;
    ACPI_OPERAND_OBJECT     **SubObjectList;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_SIZE               BufferSizeNeeded = 0;
    UINT32                  NumberOfElements;
    UINT32                  Index;
    ACPI_PCI_ROUTING_TABLE  *UserPrt;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_STATUS             Status;
    ACPI_BUFFER             PathBuffer;
    ACPI_FUNCTION_TRACE (RsCreatePciRoutingTable);
    Status = AcpiRsGetPciRoutingTableLength (
        PackageObject,&BufferSizeNeeded);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }
    ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "BufferSizeNeeded = %X\n",
        (UINT32) BufferSizeNeeded));
    Status = AcpiUtInitializeBuffer (OutputBuffer, BufferSizeNeeded);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }
    TopObjectList = PackageObject->Package.Elements;
    NumberOfElements = PackageObject->Package.Count;
    Buffer = OutputBuffer->Pointer;
    UserPrt = ACPI_CAST_PTR (ACPI_PCI_ROUTING_TABLE, Buffer);
    for (Index = 0; Index < NumberOfElements; Index++)
    {
        Buffer += UserPrt->Length;
        UserPrt = ACPI_CAST_PTR (ACPI_PCI_ROUTING_TABLE, Buffer);
        UserPrt->Length = (sizeof (ACPI_PCI_ROUTING_TABLE) - 4);
        if ((*TopObjectList)->Package.Count != 4)
        {
            ACPI_ERROR ((AE_INFO,
                "(PRT[%u]) Need package of length 4, found length %u",
                Index, (*TopObjectList)->Package.Count));
            return_ACPI_STATUS (AE_AML_PACKAGE_LIMIT);
        }
        SubObjectList = (*TopObjectList)->Package.Elements;
        ObjDesc = SubObjectList[0];
        if (!ObjDesc || ObjDesc->Common.Type != ACPI_TYPE_INTEGER)
        {
            ACPI_ERROR ((AE_INFO,
                "(PRT[%u].Address) Need Integer, found %s",
                Index, AcpiUtGetObjectTypeName (ObjDesc)));
            return_ACPI_STATUS (AE_BAD_DATA);
        }
        UserPrt->Address = ObjDesc->Integer.Value;
        ObjDesc = SubObjectList[1];
        if (!ObjDesc || ObjDesc->Common.Type != ACPI_TYPE_INTEGER)
        {
            ACPI_ERROR ((AE_INFO, "(PRT[%u].Pin) Need Integer, found %s",
                Index, AcpiUtGetObjectTypeName (ObjDesc)));
            return_ACPI_STATUS (AE_BAD_DATA);
        }
        UserPrt->Pin = (UINT32) ObjDesc->Integer.Value;
        ObjDesc = SubObjectList[2];
        if (ObjDesc)
        {
            switch (ObjDesc->Common.Type)
            {
            case ACPI_TYPE_LOCAL_REFERENCE:
                if (ObjDesc->Reference.Class != ACPI_REFCLASS_NAME)
                {
                    ACPI_ERROR ((AE_INFO,
                        "(PRT[%u].Source) Need name, found Reference Class 0x%X",
                        Index, ObjDesc->Reference.Class));
                    return_ACPI_STATUS (AE_BAD_DATA);
                }
                Node = ObjDesc->Reference.Node;
                PathBuffer.Length = OutputBuffer->Length -
                    (UINT32) ((UINT8 *) UserPrt->Source -
                    (UINT8 *) OutputBuffer->Pointer);
                PathBuffer.Pointer = UserPrt->Source;
                Status = AcpiNsHandleToPathname (
                    (ACPI_HANDLE) Node, &PathBuffer, FALSE);
                UserPrt->Length += (UINT32) strlen (UserPrt->Source) + 1;
                break;
            case ACPI_TYPE_STRING:
                strcpy (UserPrt->Source, ObjDesc->String.Pointer);
                UserPrt->Length += ObjDesc->String.Length + 1;
                break;
            case ACPI_TYPE_INTEGER:
                UserPrt->Length += sizeof (UINT32);
                break;
            default:
               ACPI_ERROR ((AE_INFO,
                   "(PRT[%u].Source) Need Ref/String/Integer, found %s",
                   Index, AcpiUtGetObjectTypeName (ObjDesc)));
               return_ACPI_STATUS (AE_BAD_DATA);
            }
        }
        UserPrt->Length = (UINT32) ACPI_ROUND_UP_TO_64BIT (UserPrt->Length);
        ObjDesc = SubObjectList[3];
        if (!ObjDesc || ObjDesc->Common.Type != ACPI_TYPE_INTEGER)
        {
            ACPI_ERROR ((AE_INFO,
                "(PRT[%u].SourceIndex) Need Integer, found %s",
                Index, AcpiUtGetObjectTypeName (ObjDesc)));
            return_ACPI_STATUS (AE_BAD_DATA);
        }
        UserPrt->SourceIndex = (UINT32) ObjDesc->Integer.Value;
        TopObjectList++;
    }
    ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "OutputBuffer %p Length %X\n",
        OutputBuffer->Pointer, (UINT32) OutputBuffer->Length));
    return_ACPI_STATUS (AE_OK);
}
ACPI_STATUS AcpiRsCreatePciRoutingTable ( ACPI_OPERAND_OBJECT * PackageObject , ACPI_BUFFER * OutputBuffer ) { UINT8 * Buffer ; ACPI_OPERAND_OBJECT * * TopObjectList ; ACPI_OPERAND_OBJECT * * SubObjectList ; ACPI_OPERAND_OBJECT * ObjDesc ; ACPI_SIZE BufferSizeNeeded = 0 ; UINT32 NumberOfElements ; UINT32 Index ; ACPI_PCI_ROUTING_TABLE * UserPrt ; ACPI_NAMESPACE_NODE * Node ; ACPI_STATUS Status ; ACPI_BUFFER PathBuffer ; ACPI_FUNCTION_TRACE ( RsCreatePciRoutingTable ) ; Status = AcpiRsGetPciRoutingTableLength ( PackageObject , & BufferSizeNeeded ) ; if ( ACPI_FAILURE ( Status ) ) { return_ACPI_STATUS ( Status ) ; } ACPI_DEBUG_PRINT ( ( ACPI_DB_INFO , " \n " , ( UINT32 ) BufferSizeNeeded ) ) ; Status = AcpiUtInitializeBuffer ( OutputBuffer , BufferSizeNeeded ) ; if ( ACPI_FAILURE ( Status ) ) { return_ACPI_STATUS ( Status ) ; } TopObjectList = PackageObject -> Package . Elements ; NumberOfElements = PackageObject -> Package . Count ; Buffer = OutputBuffer -> Pointer ; UserPrt = ACPI_CAST_PTR ( ACPI_PCI_ROUTING_TABLE , Buffer ) ; for ( Index = 0 ; Index < NumberOfElements ; Index ++ ) { Buffer += UserPrt -> Length ; UserPrt = ACPI_CAST_PTR ( ACPI_PCI_ROUTING_TABLE , Buffer ) ; UserPrt -> Length = ( sizeof ( ACPI_PCI_ROUTING_TABLE ) - 4 ) ; if ( ( * TopObjectList ) -> Package . Count != 4 ) { ACPI_ERROR ( ( AE_INFO , " " , Index , ( * TopObjectList ) -> Package . Count ) ) ; return_ACPI_STATUS ( AE_AML_PACKAGE_LIMIT ) ; } SubObjectList = ( * TopObjectList ) -> Package . Elements ; ObjDesc = SubObjectList [ 0 ] ; if ( ! ObjDesc || ObjDesc -> Common . Type != ACPI_TYPE_INTEGER ) { ACPI_ERROR ( ( AE_INFO , " " , Index , AcpiUtGetObjectTypeName ( ObjDesc ) ) ) ; return_ACPI_STATUS ( AE_BAD_DATA ) ; } UserPrt -> Address = ObjDesc -> Integer . Value ; ObjDesc = SubObjectList [ 1 ] ; if ( ! ObjDesc || ObjDesc -> Common . Type != ACPI_TYPE_INTEGER ) { ACPI_ERROR ( ( AE_INFO , " " , Index , AcpiUtGetObjectTypeName ( ObjDesc ) ) ) ; return_ACPI_STATUS ( AE_BAD_DATA ) ; } UserPrt -> Pin = ( UINT32 ) ObjDesc -> Integer . Value ; ObjDesc = SubObjectList [ 2 ] ; if ( ObjDesc ) { switch ( ObjDesc -> Common . Type ) { case ACPI_TYPE_LOCAL_REFERENCE : if ( ObjDesc -> Reference . Class != ACPI_REFCLASS_NAME ) { ACPI_ERROR ( ( AE_INFO , " " , Index , ObjDesc -> Reference . Class ) ) ; return_ACPI_STATUS ( AE_BAD_DATA ) ; } Node = ObjDesc -> Reference . Node ; PathBuffer . Length = OutputBuffer -> Length - ( UINT32 ) ( ( UINT8 * ) UserPrt -> Source - ( UINT8 * ) OutputBuffer -> Pointer ) ; PathBuffer . Pointer = UserPrt -> Source ; Status = AcpiNsHandleToPathname ( ( ACPI_HANDLE ) Node , & PathBuffer , FALSE ) ; UserPrt -> Length += ( UINT32 ) strlen ( UserPrt -> Source ) + 1 ; break ; case ACPI_TYPE_STRING : strcpy ( UserPrt -> Source , ObjDesc -> String . Pointer ) ; UserPrt -> Length += ObjDesc -> String . Length + 1 ; break ; case ACPI_TYPE_INTEGER : UserPrt -> Length += sizeof ( UINT32 ) ; break ; default : ACPI_ERROR ( ( AE_INFO , " " , Index , AcpiUtGetObjectTypeName ( ObjDesc ) ) ) ; return_ACPI_STATUS ( AE_BAD_DATA ) ; } } UserPrt -> Length = ( UINT32 ) ACPI_ROUND_UP_TO_64BIT ( UserPrt -> Length ) ; ObjDesc = SubObjectList [ 3 ] ; if ( ! ObjDesc || ObjDesc -> Common . Type != ACPI_TYPE_INTEGER ) { ACPI_ERROR ( ( AE_INFO , " " , Index , AcpiUtGetObjectTypeName ( ObjDesc ) ) ) ; return_ACPI_STATUS ( AE_BAD_DATA ) ; } UserPrt -> SourceIndex = ( UINT32 ) ObjDesc -> Integer . Value ; TopObjectList ++ ; } ACPI_DEBUG_PRINT ( ( ACPI_DB_INFO , " \n " , OutputBuffer -> Pointer , ( UINT32 ) OutputBuffer -> Length ) ) ; return_ACPI_STATUS ( AE_OK ) ; }
FUNCTION:    AcpiRsCreatePciRoutingTable
 PARAMETERS:  PackageObject           - Pointer to a package containing one
                                        of more ACPI_OPERAND_OBJECTs
              OutputBuffer            - Pointer to the user's buffer
FUNCTION : AcpiRsCreatePciRoutingTable PARAMETERS : PackageObject - Pointer to a package containing one of more ACPI_OPERAND_OBJECTs OutputBuffer - Pointer to the user ' s buffer
/* Params already validated, so we don't re-validate here */ /* Get the required buffer length */ /* Validate/Allocate/Clear caller buffer */ /*
     * Loop through the ACPI_INTERNAL_OBJECTS - Each object should be a
     * package that in turn contains an UINT64 Address, a UINT8 Pin,
     * a Name, and a UINT8 SourceIndex.
     */ /*
         * Point UserPrt past this current structure
         *
         * NOTE: On the first iteration, UserPrt->Length will
         * be zero because we cleared the return buffer earlier
         */ /*
         * Fill in the Length field with the information we have at this
         * point. The minus four is to subtract the size of the UINT8
         * Source[4] member because it is added below.
         */ /* Each subpackage must be of length 4 */ /*
         * Dereference the subpackage.
         * The SubObjectList will now point to an array of the four IRQ
         * elements: [Address, Pin, Source, SourceIndex]
         */ /* 1) First subobject: Dereference the PRT.Address */ /* 2) Second subobject: Dereference the PRT.Pin */ /*
         * 3) Third subobject: Dereference the PRT.SourceName
         * The name may be unresolved (slack mode), so allow a null object
         */ /* Use *remaining* length of the buffer as max for pathname */ /* +1 to include null terminator */ /*
                 * Add to the Length field the length of the string
                 * (add 1 for terminator)
                 */ /*
                 * If this is a number, then the Source Name is NULL, since
                 * the entire buffer was zeroed out, we can leave this alone.
                 *
                 * Add to the Length field the length of the UINT32 NULL
                 */ /* Now align the current length */ /* 4) Fourth subobject: Dereference the PRT.SourceIndex */ /* Point to the next ACPI_OPERAND_OBJECT in the top level package */