From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:45276) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UhoYL-0002vV-F0 for qemu-devel@nongnu.org; Wed, 29 May 2013 18:09:13 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UhoYF-0004WR-1Q for qemu-devel@nongnu.org; Wed, 29 May 2013 18:09:05 -0400 Received: from vms173023pub.verizon.net ([206.46.173.23]:37477) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UhoYE-0004Sz-S1 for qemu-devel@nongnu.org; Wed, 29 May 2013 18:08:58 -0400 Received: from wf-rch.minyard.home ([unknown] [173.74.121.95]) by vms173023.mailsrvcs.net (Sun Java(tm) System Messaging Server 7u2-7.02 32bit (built Apr 16 2009)) with ESMTPA id <0MNK0051YYUBPC10@vms173023.mailsrvcs.net> for qemu-devel@nongnu.org; Wed, 29 May 2013 17:08:37 -0500 (CDT) From: minyard@acm.org Date: Wed, 29 May 2013 17:08:14 -0500 Message-id: <1369865296-19584-19-git-send-email-minyard@acm.org> In-reply-to: <1369865296-19584-1-git-send-email-minyard@acm.org> References: <1369865296-19584-1-git-send-email-minyard@acm.org> Subject: [Qemu-devel] [PATCH 18/20] ipmi: Add ACPI table entries for BMCs List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Corey Minyard , openipmi-developer@lists.sourceforge.net From: Corey Minyard Use the new ACPI table construction tools to create an ACPI entry for IPMI. Signed-off-by: Corey Minyard --- hw/ipmi/isa_ipmi.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/hw/ipmi/isa_ipmi.c b/hw/ipmi/isa_ipmi.c index 7664b66..92afb88 100644 --- a/hw/ipmi/isa_ipmi.c +++ b/hw/ipmi/isa_ipmi.c @@ -23,6 +23,8 @@ */ #include "hw/hw.h" #include "hw/isa/isa.h" +#include "hw/acpi/acpi-elements.h" +#include "hw/acpi/acpi.h" #include "hw/i386/pc.h" #include "qemu/timer.h" #include "sysemu/char.h" @@ -36,16 +38,134 @@ typedef struct ISAIPMIDevice { ISADevice dev; char *interface; + int intftype; uint32_t iobase; + uint32_t endaddr; uint32_t isairq; + uint8_t regspacing; uint8_t slave_addr; + uint8_t version; CharDriverState *chr; IPMIInterface *intf; } ISAIPMIDevice; +static int +acpi_ipmi_crs_ops(char **data, int dlen, void *opaque) +{ + ISAIPMIDevice *info = opaque; + int len, rv; + uint8_t regspacing = info->regspacing; + + if (regspacing == 1) + regspacing = 0; + /* IO(Decode16, x, y, z, c) */ + len = acpi_add_IO16(data, dlen, info->iobase, info->endaddr, + regspacing, info->endaddr - info->iobase + 1); + if (len < 0) + return len; + if (info->isairq) { + /* Interrupt(ResourceConsumer,Level,ActiveHigh,Exclusive) {n} */ + rv = acpi_add_Interrupt(data, dlen, info->isairq, + ACPI_RESOURCE_CONSUMER, + ACPI_INTERRUPT_MODE_LEVEL, + ACPI_INTERRUPT_POLARITY_ACTIVE_HIGH, + ACPI_INTERRUPT_EXCLUSIVE); + if (rv < 0) + return rv; + len += rv; + } + rv = acpi_add_EndResource(data, dlen); + if (rv < 0) + return rv; + len += rv; + return len; +} + +static int +acpi_ipmi_crs(char **data, int dlen, void *opaque) +{ + ISAIPMIDevice *info = opaque; + int len; + + len = acpi_add_BufferOp(NULL, 0, acpi_ipmi_crs_ops, info); + if (len < 0) + return len; + if (len <= dlen) { + acpi_add_BufferOp(data, dlen, acpi_ipmi_crs_ops, info); + } + return len; +} + +static int +acpi_ipmi_dev(char **data, int dlen, void *opaque) +{ + ISAIPMIDevice *info = opaque; + int len, rv; + char *name; + uint64_t val; + + name = g_strdup_printf("ipmi_%s", info->interface); + + /* Name(_HID, EISAID("IPI0001")) */ + len = acpi_add_Name(data, dlen, "_HID", acpi_add_EISAID, + (void *) "IPI0001"); + if (len < 0) + return len; + /* Name(_STR, Unicode("ipmi_xxx")) */ + rv = acpi_add_Name(data, dlen, "_STR", acpi_add_Unicode, name); + if (rv < 0) + return rv; + len += rv; + val = 0; + /* Name(_UID, 0) */ + rv = acpi_add_Name(data, dlen, "_UID", acpi_add_Integer, &val); + if (rv < 0) + return rv; + len += rv; + /* Name(_CRS, ResourceTemplate() { */ + rv = acpi_add_Name(data, dlen, "_CRS", acpi_ipmi_crs, info); + if (rv < 0) + return rv; + len += rv; + val = info->intftype; + /* Method(_IFT) { Return(i) } */ + rv = acpi_add_Method(data, dlen, "_IFT", 0, acpi_add_Return, &val); + if (rv < 0) + return rv; + len += rv; + val = ((info->version & 0xf0) << 4) | (info->version & 0x0f); + /* Method(_SRV) { Return(version) } */ + rv = acpi_add_Method(data, dlen, "_SRV", 0, acpi_add_Return, &val); + if (rv < 0) + return rv; + len += rv; + return len; +} + +static void +ipmi_encode_acpi(ISAIPMIDevice *info) +{ + char ipmitable[200]; + char *tblptr = ipmitable; + int rc; + Error *err = NULL; + + /* Device(MI0) { */ + rc = acpi_add_Device(&tblptr, sizeof(ipmitable), "MI0", + acpi_ipmi_dev, info); + /* } */ + if (rc < 0) { + fprintf(stderr, "Unable to format IPMI ACPI table entry\n"); + return; + } + + acpi_append_to_table("DSDT", ipmitable, rc, &err); +} + static int ipmi_isa_initfn(ISADevice *dev) { ISAIPMIDevice *isa = ISA_IPMI(dev); + IPMIInterfaceClass *intfk; char typename[20]; Object *intfobj; IPMIInterface *intf; @@ -69,6 +189,7 @@ static int ipmi_isa_initfn(ISADevice *dev) TYPE_IPMI_INTERFACE_PREFIX "%s", isa->interface); intfobj = object_new(typename); intf = IPMI_INTERFACE(intfobj); + intfk = IPMI_INTERFACE_GET_CLASS(intf); bmc->intf = intf; intf->bmc = bmc; intf->io_base = isa->iobase; @@ -85,6 +206,10 @@ static int ipmi_isa_initfn(ISADevice *dev) /* These may be set by the interface. */ isa->iobase = intf->io_base; isa->slave_addr = intf->slave_addr; + isa->regspacing = 1; + isa->endaddr = cpu_to_le64(intf->io_base + intf->io_length - 1); + isa->intftype = intfk->smbios_type; + isa->version = 0x20; /* Version 2.0 */ if (isa->isairq != 0) { isa_init_irq(dev, &intf->irq, isa->isairq); @@ -107,6 +232,8 @@ static int ipmi_isa_initfn(ISADevice *dev) isa_register_ioport(dev, &intf->io, intf->io_base); + ipmi_encode_acpi(isa); + return 0; } -- 1.7.9.5