/*
 * IPMI ACPI firmware handling
 *
 * Copyright (c) 2015,2016 Corey Minyard, MontaVista Software, LLC
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 */

#include "qemu/osdep.h"
#include "hw/ipmi/ipmi.h"
#include "hw/acpi/aml-build.h"
#include "hw/acpi/acpi.h"
#include "hw/acpi/ipmi.h"

static Aml *aml_ipmi_crs(IPMIFwInfo *info)
{
    Aml *crs = aml_resource_template();

    /*
     * The base address is fixed and cannot change.  That may be different
     * if someone does PCI, but we aren't there yet.
     */
    switch (info->memspace) {
    case IPMI_MEMSPACE_IO:
        aml_append(crs, aml_io(AML_DECODE16, info->base_address,
                               info->base_address + info->register_length - 1,
                               info->register_spacing, info->register_length));
        break;
    case IPMI_MEMSPACE_MEM32:
        aml_append(crs,
                   aml_dword_memory(AML_POS_DECODE,
                            AML_MIN_FIXED, AML_MAX_FIXED,
                            AML_NON_CACHEABLE, AML_READ_WRITE,
                            0xffffffff,
                            info->base_address,
                            info->base_address + info->register_length - 1,
                            info->register_spacing, info->register_length));
        break;
    case IPMI_MEMSPACE_MEM64:
        aml_append(crs,
                   aml_qword_memory(AML_POS_DECODE,
                            AML_MIN_FIXED, AML_MAX_FIXED,
                            AML_NON_CACHEABLE, AML_READ_WRITE,
                            0xffffffffffffffffULL,
                            info->base_address,
                            info->base_address + info->register_length - 1,
                            info->register_spacing, info->register_length));
        break;
    case IPMI_MEMSPACE_SMBUS:
        aml_append(crs, aml_i2c_serial_bus_device(info->base_address,
                                                  "^"));
        break;
    default:
        abort();
    }

    if (info->interrupt_number) {
        aml_append(crs, aml_irq_no_flags(info->interrupt_number));
    }

    return crs;
}

void build_ipmi_dev_aml(AcpiDevAmlIf *adev, Aml *scope)
{
    Aml *dev;
    IPMIFwInfo info = {};
    IPMIInterface *ii = IPMI_INTERFACE(adev);
    IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
    uint16_t version;

    iic->get_fwinfo(ii, &info);
    assert(info.ipmi_spec_minor_revision <= 15);
    version = ((info.ipmi_spec_major_revision << 8)
              | (info.ipmi_spec_minor_revision << 4));

    dev = aml_device("MI%d", info.uuid);
    aml_append(dev, aml_name_decl("_HID", aml_eisaid("IPI0001")));
    aml_append(dev, aml_name_decl("_STR", aml_string("ipmi_%s",
                                                     info.interface_name)));
    aml_append(dev, aml_name_decl("_UID", aml_int(info.uuid)));
    aml_append(dev, aml_name_decl("_CRS", aml_ipmi_crs(&info)));
    aml_append(dev, aml_name_decl("_IFT", aml_int(info.interface_type)));
    aml_append(dev, aml_name_decl("_SRV", aml_int(version)));

    aml_append(scope, dev);
}
