/*
 * hal_acpi.h - ACPI-specific values and structures
 *
 * Copyright (c) 2017 Maxime Villard
 * Inspired by ACPICA.
 *
 * This file is part of ALMOS-MKH.
 *
 * ALMOS-MKH is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2.0 of the License.
 *
 * ALMOS-MKH is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

/*
 * Copyright (C) 2000 - 2017, Intel Corp.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer,
 *    without modification.
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
 *    substantially similar to the "NO WARRANTY" disclaimer below
 *    ("Disclaimer") and any redistribution must be conditioned upon
 *    including a substantially similar Disclaimer requirement for further
 *    binary redistribution.
 * 3. Neither the names of the above-listed copyright holders nor the names
 *    of any contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 *
 * NO WARRANTY
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 */

void hal_acpi_init();

#define ACPI_RSDP_ALIGN	16
#define ACPI_RSDP_SIGNATURE	"RSD PTR "
#define ACPI_RSDP_SIGNATURE_SIZE	8

#define ACPI_OEM_ID_SIZE	6

#define ACPI_NAME_SIZE	4

/* Sizes for ACPI table headers */
#define ACPI_OEM_ID_SIZE		6
#define ACPI_OEM_TABLE_ID_SIZE	8


/*******************************************************************************
 * RSDP - Root System Description Pointer (Signature is "RSD PTR ")
 *        Version 2
 ******************************************************************************/

struct acpi_table_rsdp {
	char Signature[8];            /* ACPI signature, contains "RSD PTR " */
	uint8_t Checksum;             /* ACPI 1.0 checksum */
	char OemId[ACPI_OEM_ID_SIZE]; /* OEM identification */
	uint8_t Revision;             /* Must be (0) for ACPI 1.0 or (2) for ACPI 2.0+ */
	uint32_t RsdtPhysicalAddress; /* 32-bit physical address of the RSDT */
	uint32_t Length;              /* Table length in bytes, including header (ACPI 2.0+) */
	uint64_t XsdtPhysicalAddress; /* 64-bit physical address of the XSDT (ACPI 2.0+) */
	uint8_t ExtendedChecksum;     /* Checksum of entire table (ACPI 2.0+) */
	uint8_t Reserved[3];          /* Reserved, must be zero */
} __packed;
typedef struct acpi_table_rsdp	rsdp_t;

/*******************************************************************************
 * Master ACPI Table Header. This common header is used by all ACPI tables
 * except the RSDP and FACS.
 ******************************************************************************/

struct acpi_table_header {
	char Signature[ACPI_NAME_SIZE];          /* ASCII table signature */
	uint32_t Length;                         /* Length of table in bytes, including this header */
	uint8_t Revision;                        /* ACPI Specification minor version number */
	uint8_t Checksum;                        /* To make sum of entire table == 0 */
	char OemId[ACPI_OEM_ID_SIZE];            /* ASCII OEM identification */
	char OemTableId[ACPI_OEM_TABLE_ID_SIZE]; /* ASCII OEM table identification */
	uint32_t OemRevision;                    /* OEM revision number */
	char AslCompilerId[ACPI_NAME_SIZE];      /* ASCII ASL compiler vendor ID */
	uint32_t AslCompilerRevision;            /* ASL compiler version */
} __packed;
typedef struct acpi_table_header	header_t;

/*******************************************************************************
 * RSDT - Root System Description Tables
 *        Version 1
 ******************************************************************************/

struct acpi_table_rsdt {
	header_t Header;              /* Common ACPI table header */
    uint32_t TableOffsetEntry[1]; /* Array of pointers to ACPI tables */
} __packed;
typedef struct acpi_table_rsdt	rsdt_t;

/*******************************************************************************
 * Common subtable headers
 ******************************************************************************/

struct acpi_subtable_header {
	uint8_t Type;
	uint8_t Length;
} __packed;
typedef struct acpi_subtable_header	subheader_t;

/*******************************************************************************
 * MADT - Multiple APIC Description Table
 *        Version 3
 ******************************************************************************/

struct acpi_table_madt {
	header_t Header;  /* Common ACPI table header */
	uint32_t Address; /* Physical address of local APIC */
	uint32_t Flags;
} __packed;
typedef struct acpi_table_madt	madt_t;

/*******************************************************************************
 * MADT structures
 ******************************************************************************/

#define ACPI_MADT_LAPIC_ENABLED	0x01

enum AcpiMadtType {
	ACPI_MADT_TYPE_LOCAL_APIC            = 0,
	ACPI_MADT_TYPE_IO_APIC               = 1,
	ACPI_MADT_TYPE_INTERRUPT_OVERRIDE    = 2,
	ACPI_MADT_TYPE_NMI_SOURCE            = 3,
	ACPI_MADT_TYPE_LOCAL_APIC_NMI        = 4,
	ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE   = 5,
	ACPI_MADT_TYPE_IO_SAPIC              = 6,
	ACPI_MADT_TYPE_LOCAL_SAPIC           = 7,
	ACPI_MADT_TYPE_INTERRUPT_SOURCE      = 8,
	ACPI_MADT_TYPE_LOCAL_X2APIC          = 9,
	ACPI_MADT_TYPE_LOCAL_X2APIC_NMI      = 10,
	ACPI_MADT_TYPE_GENERIC_INTERRUPT     = 11,
	ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR   = 12,
	ACPI_MADT_TYPE_GENERIC_MSI_FRAME     = 13,
	ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR = 14,
	ACPI_MADT_TYPE_GENERIC_TRANSLATOR    = 15,
	ACPI_MADT_TYPE_RESERVED              = 16  /* 16 and greater are reserved */
};

struct acpi_madt_local_apic {
	subheader_t Header;
	uint8_t ProcessorId; /* ACPI processor id */
	uint8_t Id;          /* Processor's local APIC id */
	uint32_t LapicFlags;
} __packed;
typedef struct acpi_madt_local_apic	madt_lapic_t;

struct acpi_madt_local_apic_override {
	subheader_t Header;
	uint16_t Reserved; /* Reserved, must be zero */
	uint64_t Address;  /* APIC physical address */
} __packed;
typedef struct acpi_madt_local_apic_override madt_lapic_override_t;

struct acpi_madt_io_apic {
	subheader_t Header;
	uint8_t Id;             /* I/O APIC ID */
	uint8_t Reserved;       /* Reserved - must be zero */
	uint32_t Address;       /* APIC physical address */
	uint32_t GlobalIrqBase; /* Global system interrupt where INTI lines start */
} __packed;
typedef struct acpi_madt_io_apic madt_ioapic_t;

/*******************************************************************************
 * SRAT - System Resource Affinity Table
 *        Version 3
 ******************************************************************************/

struct acpi_table_srat {
	header_t Header;        /* Common ACPI table header */
	uint32_t TableRevision; /* Must be value '1' */
	uint64_t Reserved;      /* Reserved, must be zero */
};
typedef struct acpi_table_srat	srat_t;

/*******************************************************************************
 * SRAT structures
 ******************************************************************************/

enum AcpiSratType {
	ACPI_SRAT_TYPE_CPU_AFFINITY        = 0,
	ACPI_SRAT_TYPE_MEMORY_AFFINITY     = 1,
	ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY = 2,
	ACPI_SRAT_TYPE_GICC_AFFINITY       = 3,
	ACPI_SRAT_TYPE_RESERVED            = 4  /* 4 and greater are reserved */
};

#define ACPI_SRAT_CPU_USE_AFFINITY  (1) /* 00: Use affinity structure */

struct acpi_srat_cpu_affinity {
	subheader_t Header;
	uint8_t ProximityDomainLo;
	uint8_t ApicId;
	uint32_t Flags;
	uint8_t LocalSapicEid;
	uint8_t ProximityDomainHi[3];
	uint32_t ClockDomain;
};
typedef struct acpi_srat_cpu_affinity	srat_cpu_affinity_t;

#define ACPI_SRAT_MEM_ENABLED       (1)    /* 00: Use affinity structure */
#define ACPI_SRAT_MEM_HOT_PLUGGABLE (1<<1) /* 01: Memory region is hot pluggable */
#define ACPI_SRAT_MEM_NON_VOLATILE  (1<<2) /* 02: Memory region is non-volatile */

struct acpi_srat_mem_affinity {
	subheader_t Header;
	uint32_t ProximityDomain;
	uint16_t Reserved;        /* Reserved, must be zero */
	uint64_t BaseAddress;
	uint64_t Length;
	uint32_t Reserved1;
	uint32_t Flags;
	uint64_t Reserved2;       /* Reserved, must be zero */
};
typedef struct acpi_srat_mem_affinity	srat_mem_affinity_t;

