/** @file
  SSDT Pcie Table Generator.

  Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
  SPDX-License-Identifier: BSD-2-Clause-Patent

  @par Reference(s):
  - PCI Firmware Specification - Revision 3.0
  - ACPI 6.4 specification:
   - s6.2.13 "_PRT (PCI Routing Table)"
   - s6.1.1 "_ADR (Address)"
  - linux kernel code
  - Arm Base Boot Requirements v1.0
**/

#ifndef SSDT_PCIE_GENERATOR_H_
#define SSDT_PCIE_GENERATOR_H_

/** Pci address attributes.

  This can also be denoted as space code, address space or ss.
*/
#define PCI_SS_CONFIG  0
#define PCI_SS_IO      1
#define PCI_SS_M32     2
#define PCI_SS_M64     3

/** Maximum Pci root complexes supported by this generator.

  Note: This is not a hard limitation and can be extended if needed.
        Corresponding changes would be needed to support the Name and
        UID fields describing the Pci root complexes.
*/
#define MAX_PCI_ROOT_COMPLEXES_SUPPORTED  16

/** Maximum number of Pci legacy interrupts.

  Currently 4 for INTA-INTB-INTC-INTD.
*/
#define MAX_PCI_LEGACY_INTERRUPT  4

// _SB scope of the AML namespace.
#define SB_SCOPE  "\\_SB_"

/** C array containing the compiled AML template.
    This symbol is defined in the auto generated C file
    containing the AML bytecode array.
*/
extern CHAR8  ssdtpcieosctemplate_aml_code[];

#pragma pack(1)

/** Structure used to map integer to an index.
*/
typedef struct MappingTable {
  /// Mapping table.
  /// Contains the Index <-> integer mapping
  UINT32    *Table;

  /// Last used index of the Table.
  /// Bound by MaxIndex.
  UINT32    LastIndex;

  /// Number of entries in the Table.
  UINT32    MaxIndex;
} MAPPING_TABLE;

/** A structure holding the Pcie generator and additional private data.
*/
typedef struct AcpiPcieGenerator {
  /// ACPI Table generator header
  ACPI_TABLE_GENERATOR    Header;

  // Private fields are defined from here.

  /** A structure used to handle the Address and Interrupt Map referencing.

    A CM_ARM_PCI_CONFIG_SPACE_INFO structure references two CM_ARM_OBJ_REF:
     - one for the address mapping, referencing
       CM_ARM_PCI_ADDRESS_MAP_INFO structures.
     - one for the interrupt mapping, referencing
       CM_ARM_PCI_INTERRUPT_MAP_INFO structures.

    Example:
    (Pci0)
    CM_ARM_PCI_CONFIG_SPACE_INFO
                |
                +----------------------------------------
                |                                       |
                v                                       v
          CM_ARM_OBJ_REF                          CM_ARM_OBJ_REF
      (List of references to                  (List of references to
         address mappings)                        interrupt mappings)
                |                                       |
                v                                       v
    CM_ARM_PCI_ADDRESS_MAP_INFO[0..N]      CM_ARM_PCI_INTERRUPT_MAP_INFO[0..M]
    (A list of address mappings)           (A list of interrupt mappings)

    The CM_ARM_PCI_INTERRUPT_MAP_INFO objects cannot be handled individually.
    Device's Pci legacy interrupts that are mapped to the same CPU interrupt
    are grouped under a Link device.
    For instance, the following mapping:
     - [INTA of device 0] mapped on [GIC irq 168]
     - [INTB of device 1] mapped on [GIC irq 168]
    will be represented in an SSDT table as:
     - [INTA of device 0] mapped on [Link device A]
     - [INTB of device 1] mapped on [Link device A]
     - [Link device A] mapped on [GIC irq 168]

    Counting the number of Cpu interrupts used and grouping them in Link
    devices is done through this IRQ_TABLE.

    ASL code:
    Scope (_SB) {
      Device (LNKA) {
        [...]
        Name (_PRS, ResourceTemplate () {
          Interrupt (ResourceProducer, Level, ActiveHigh, Exclusive) { 168 }
        })
      }

      Device (PCI0) {
        Name (_PRT, Package () {
          Package (0x0FFFF, 0, LNKA, 0)  // INTA of device 0 <-> LNKA
          Package (0x1FFFF, 1, LNKA, 0)  // INTB of device 1 <-> LNKA
          })
        }
    }
  */
  MAPPING_TABLE    IrqTable;

  /// Table to map: Index <-> Pci device
  MAPPING_TABLE    DeviceTable;
} ACPI_PCI_GENERATOR;

#pragma pack()

#endif // SSDT_PCIE_GENERATOR_H_
