--- /dev/null
+/*
+ * xen_acpi_wmi.c
+ *
+ * Copyright (c) 2009 Kamala Narasimhan
+ * Copyright (c) 2009 Citrix Systems, Inc.
+ *
+ * This program 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* Xen ACPI WMI implementation -
+ * OEMs expose their value add functionalites through firmware level WMI
+ * acpi objects. To support the underlying OEM value add within guest
+ * space, we expose a WMI psuedo device object at our vACPI layer. That
+ * vACPI layer relies on the below implementation to communication to the
+ * base firmware (through xen wmi module and linux acpi wmi wrapper
+ * driver) either it be to execute a WMI method or query or set
+ * data or recieve wmi event data.
+ */
+
+/* NOTE: As the vACPI layer is written to send request and take response in a
+ * synchronized way, there isn't a need to add synchronization logic here.
+ */
+
+#include "hw.h"
+#include "pc.h"
+#include "qemu-xen.h"
+#include "isa.h"
+#include "xen_acpi_wmi.h"
+
+#ifndef CONFIG_NO_XEN_ACPI_WMI
+
+#define XEN_WMI_DEFAULT_OUTPUT_BUFFER_SIZE 256
+
+static xen_acpi_wmi_cmd_info_t cmd_info;
+static int xen_wmi_device = -ENODEV;
+extern FILE *logfile;
+extern int domid;
+
+/* #define XEN_ACPI_WMI_DEBUG */
+/* #define XEN_ACPI_WMI_DEBUG_EXT */
+
+/*
+ * xen_acpi_wmi_set_guid
+ */
+void xen_acpi_wmi_set_guid(uint8_t val)
+{
+ if ( cmd_info.invocation_type == XEN_ACPI_WMI_UNDEFINED )
+ {
+ fprintf(logfile,
+ "XEN WMI: Unable to set guid with invalid invocation type!\n");
+ return;
+ }
+
+ if ( cmd_info.current_index >= XEN_WMI_GUID_SIZE )
+ {
+ fprintf(logfile, "XEN WMI: Guid array index out of range - %d!!!\n",
+ cmd_info.current_index);
+ cmd_info.invocation_type = XEN_ACPI_WMI_UNDEFINED;
+ return;
+ }
+
+ cmd_info.invocation_data.guid[cmd_info.current_index] = val;
+ cmd_info.current_index++;
+}
+
+/*
+ * xen_acpi_wmi_set_cmd_instance
+ */
+void xen_acpi_wmi_set_cmd_instance(uint32_t val)
+{
+ if ( cmd_info.invocation_type == XEN_ACPI_WMI_UNDEFINED )
+ {
+ fprintf(logfile,
+ "XEN WMI: Unable to set cmd instance with invalid invocation type!\n");
+ return;
+ }
+
+ switch( cmd_info.invocation_type )
+ {
+ case XEN_ACPI_WMI_EXEC_METHOD:
+ cmd_info.invocation_data.xen_wmi_arg.xen_wmi_method_arg.instance = val;
+ break;
+ case XEN_ACPI_WMI_QUERY_OBJECT:
+ cmd_info.invocation_data.xen_wmi_arg.xen_wmi_query_obj_arg.instance = val;
+ break;
+ case XEN_ACPI_WMI_SET_OBJECT:
+ cmd_info.invocation_data.xen_wmi_arg.xen_wmi_set_obj_arg.instance = val;
+ break;
+ default:
+ fprintf(logfile,
+ "Invalid attempt to set instance for current invocation type!\n");
+ break;
+ }
+}
+
+/*
+ * xen_acpi_wmi_set_method_id
+ */
+void xen_acpi_wmi_set_method_id(uint32_t val)
+{
+ if ( cmd_info.invocation_type != XEN_ACPI_WMI_EXEC_METHOD )
+ {
+ fprintf(logfile,
+ "Unable to set method id for the current invocation type!\n");
+ return;
+ }
+
+ cmd_info.invocation_data.xen_wmi_arg.xen_wmi_method_arg.method_id = val;
+}
+
+/*
+ * xen_acpi_wmi_get_input_buffer
+ */
+xen_wmi_buffer_t *xen_acpi_wmi_get_input_buffer(void)
+{
+ if ( cmd_info.invocation_type != XEN_ACPI_WMI_EXEC_METHOD &&
+ cmd_info.invocation_type != XEN_ACPI_WMI_SET_OBJECT )
+ return 0;
+
+ if ( cmd_info.invocation_type == XEN_ACPI_WMI_EXEC_METHOD )
+ return &cmd_info.invocation_data.xen_wmi_arg.xen_wmi_method_arg.in_buf;
+ else if ( cmd_info.invocation_type == XEN_ACPI_WMI_SET_OBJECT )
+ return &cmd_info.invocation_data.xen_wmi_arg.xen_wmi_set_obj_arg.in_buf;
+
+ return 0;
+}
+
+/*
+ * xen_acpi_wmi_set_buffer_size
+ * Guest vACPI layer passes to us the size of the input buffer it is
+ * about to transfer to ioemu and this method stores the passed in size
+ * apart from allocating a buffer with the provided size.
+ */
+void xen_acpi_wmi_set_in_buffer_size(uint32_t val)
+{
+ xen_wmi_buffer_t *buffer;
+
+ buffer = xen_acpi_wmi_get_input_buffer();
+ if ( buffer == NULL )
+ return;
+
+ cmd_info.current_index = 0;
+ buffer->length = val;
+ buffer->pointer = malloc(val);
+}
+
+/*
+ * xen_acpi_wmi_set_in_buffer
+ */
+void xen_acpi_wmi_set_in_buffer(uint8_t val)
+{
+ xen_wmi_buffer_t *buffer;
+
+ buffer = xen_acpi_wmi_get_input_buffer();
+ if ( buffer == NULL )
+ return;
+
+ if ( cmd_info.current_index >= buffer->length )
+ {
+ fprintf(logfile,
+ "XEN WMI: Cannot write beyond allocated input buffer size!!!\n");
+ return;
+ }
+
+ ((byte *)buffer->pointer)[cmd_info.current_index] = val;
+ cmd_info.current_index++;
+}
+
+/*
+ * xen_wmi_get_output_buffer
+ */
+xen_wmi_buffer_t *xen_acpi_wmi_get_output_buffer(void)
+{
+ if ( cmd_info.invocation_type != XEN_ACPI_WMI_EXEC_METHOD &&
+ cmd_info.invocation_type != XEN_ACPI_WMI_QUERY_OBJECT &&
+ cmd_info.invocation_type != XEN_ACPI_WMI_GET_EVENT_DATA )
+ {
+ fprintf(logfile,
+ "XEN WMI: Output buffer not available for current invocation type!\n");
+ return 0;
+ }
+
+ if ( cmd_info.invocation_type == XEN_ACPI_WMI_EXEC_METHOD )
+ return &cmd_info.invocation_data.xen_wmi_arg.xen_wmi_method_arg.out_buf;
+ else if ( cmd_info.invocation_type == XEN_ACPI_WMI_QUERY_OBJECT )
+ return &cmd_info.invocation_data.xen_wmi_arg.xen_wmi_query_obj_arg.out_buf;
+ else if ( cmd_info.invocation_type == XEN_ACPI_WMI_GET_EVENT_DATA )
+ return &cmd_info.invocation_data.xen_wmi_arg.xen_wmi_event_data_arg.out_buf;
+
+ return 0;
+}
+
+/*
+ * xen_acpi_wmi_allocate_output_buffer
+ */
+void xen_acpi_wmi_allocate_output_buffer(size_t length)
+{
+ xen_wmi_buffer_t *buffer;
+
+ buffer = xen_acpi_wmi_get_output_buffer();
+ if ( buffer == NULL )
+ return;
+
+ buffer->length = (length > 0) ? length : XEN_WMI_DEFAULT_OUTPUT_BUFFER_SIZE;
+ buffer->pointer = malloc(buffer->length);
+ memset(buffer->pointer, 0, buffer->length);
+
+ buffer->copied_length = malloc(sizeof(size_t));
+ memset(buffer->copied_length, 0, sizeof(size_t));
+}
+
+/*
+ * xen_acpi_wmi_reallocate_output_buffer
+ */
+int xen_acpi_wmi_reallocate_output_buffer()
+{
+ xen_wmi_buffer_t *buffer;
+
+ buffer = xen_acpi_wmi_get_output_buffer();
+ if ( buffer == NULL || buffer->copied_length == NULL || buffer->pointer == NULL )
+ return XEN_WMI_NOT_ENOUGH_MEMORY;
+
+ /* If required length is less than allocated length,
+ * we shouldn't have failed; no point in rellocating.
+ * @TODO: Rename copied_length to something more appropriate.
+ */
+ if ( *buffer->copied_length <= buffer->length )
+ return XEN_WMI_NOT_ENOUGH_MEMORY;
+
+ free(buffer->pointer);
+ buffer->pointer = malloc(*buffer->copied_length);
+ memset(buffer->pointer, 0, *buffer->copied_length);
+ buffer->length = *buffer->copied_length;
+ return XEN_WMI_SUCCESS;
+}
+
+/*
+ * xen_acpi_wmi_free_input_buffer
+ */
+void xen_acpi_wmi_free_input_buffer(void)
+{
+ xen_wmi_buffer_t *buffer;
+
+ buffer = xen_acpi_wmi_get_input_buffer();
+ if ( buffer == NULL )
+ return;
+
+ if ( buffer->length > 0 )
+ free(buffer->pointer);
+ buffer->length = 0;
+}
+
+#ifdef XEN_ACPI_WMI_DEBUG
+
+/*
+ * xen_acpi_wmi_print_input_buffer
+ */
+void xen_acpi_wmi_print_input_buffer(xen_wmi_buffer_t *in_buf)
+{
+ int count;
+
+ fprintf(logfile, "In buffer length - %d\n", in_buf->length);
+ fprintf(logfile, "In buffer: ");
+ for( count = 0; count < in_buf->length; count++ )
+ fprintf(logfile, " %d, ", ((byte *)in_buf->pointer)[count]);
+ fprintf(logfile, "\n");
+}
+
+/*
+ * xen_acpi_wmi_print_input_info
+ */
+void xen_acpi_wmi_print_input_info(void)
+{
+ int count;
+
+ fprintf(logfile, "Command invocation type - %d\n", cmd_info.invocation_type);
+ fprintf(logfile, "Invocation Data: \n");
+ fprintf(logfile, "Guid: ");
+
+ for (count=0; count < XEN_WMI_GUID_SIZE; count++)
+ fprintf(logfile,"%d ", cmd_info.invocation_data.guid[count]);
+
+ fprintf(logfile, "\n");
+
+ if ( cmd_info.invocation_type == XEN_ACPI_WMI_EXEC_METHOD )
+ {
+ fprintf(logfile,
+ "Instance id - %d\n",
+ cmd_info.invocation_data.xen_wmi_arg.xen_wmi_method_arg.instance);
+ fprintf(logfile,
+ "Method id - %d\n",
+ cmd_info.invocation_data.xen_wmi_arg.xen_wmi_method_arg.method_id);
+ xen_acpi_wmi_print_input_buffer(
+ &cmd_info.invocation_data.xen_wmi_arg.xen_wmi_method_arg.in_buf);
+ }
+ else if ( cmd_info.invocation_type == XEN_ACPI_WMI_QUERY_OBJECT )
+ {
+ fprintf(logfile,
+ "Instance id - %d\n",
+ cmd_info.invocation_data.xen_wmi_arg.xen_wmi_query_obj_arg.instance);
+ }
+ else if ( cmd_info.invocation_type == XEN_ACPI_WMI_SET_OBJECT )
+ {
+ fprintf(logfile,
+ "Instance id - %d\n",
+ cmd_info.invocation_data.xen_wmi_arg.xen_wmi_set_obj_arg.instance);
+ xen_acpi_wmi_print_input_buffer(
+ &cmd_info.invocation_data.xen_wmi_arg.xen_wmi_set_obj_arg.in_buf);
+ }
+ else if ( cmd_info.invocation_type == XEN_ACPI_WMI_GET_EVENT_DATA )
+ {
+ fprintf(logfile,
+ "Event id - %d\n",
+ cmd_info.invocation_data.xen_wmi_arg.xen_wmi_event_data_arg.event_id);
+ }
+}
+
+/*
+ * xen_acpi_wmi_print_output_buffer
+ */
+void xen_acpi_wmi_print_output_buffer(void)
+{
+ int count;
+ xen_wmi_buffer_t *buffer = xen_acpi_wmi_get_output_buffer();
+
+ if ( buffer == NULL || buffer->copied_length == NULL || *buffer->copied_length == 0 )
+ return;
+
+ fprintf(logfile, "XEN WMI: Output buffer size is - %d\n",
+ *buffer->copied_length);
+ fprintf(logfile, "XEN WMI output buffer is - ");
+ for (count=0; count < *buffer->copied_length; count++)
+ fprintf(logfile," %d, ", ((byte *)buffer->pointer)[count]);
+
+ fprintf(logfile, "\n");
+}
+
+#endif /* XEN_ACPI_WMI_DEBUG */
+
+/*
+ * xen_acpi_wmi_execute
+ */
+void xen_acpi_wmi_execute(void)
+{
+ int request, ret;
+
+ if ( cmd_info.invocation_type == XEN_ACPI_WMI_UNDEFINED )
+ {
+ fprintf(logfile,
+ "Unable to execute command for the given invocation type!\n");
+ return;
+ }
+
+ switch ( cmd_info.invocation_type )
+ {
+ case XEN_ACPI_WMI_EXEC_METHOD:
+ request = XEN_WMI_IOCTL_CALL_METHOD;
+ break;
+ case XEN_ACPI_WMI_QUERY_OBJECT:
+ request = XEN_WMI_IOCTL_QUERY_OBJECT;
+ break;
+ case XEN_ACPI_WMI_SET_OBJECT:
+ request = XEN_WMI_IOCTL_SET_OBJECT;
+ break;
+ case XEN_ACPI_WMI_GET_EVENT_DATA:
+ request = XEN_WMI_IOCTL_GET_EVENT_DATA;
+ break;
+ default:
+ fprintf(logfile,
+ "Unable to execute command for the given invocation type!\n");
+ return;
+ }
+
+ xen_acpi_wmi_allocate_output_buffer(0);
+#ifdef XEN_ACPI_WMI_DEBUG
+ fprintf(logfile, "XEN WMI Invoking ioctl - %d\n", cmd_info.invocation_type);
+ xen_acpi_wmi_print_input_info();
+#endif
+ ret = ioctl(xen_wmi_device, request, &cmd_info.invocation_data);
+ if ( ret == XEN_WMI_BUFFER_TOO_SMALL )
+ {
+ if ( xen_acpi_wmi_reallocate_output_buffer() == XEN_WMI_SUCCESS )
+ ret = ioctl(xen_wmi_device, request, &cmd_info.invocation_data);
+ }
+
+ if ( ret != XEN_WMI_SUCCESS )
+ fprintf(logfile, "Xen WMI ioctl failed with error - %d\n", ret);
+
+#ifdef XEN_ACPI_WMI_DEBUG
+ xen_acpi_wmi_print_output_buffer();
+#endif
+
+ xen_acpi_wmi_free_input_buffer();
+}
+
+/*
+ * xen_acpi_wmi_set_event_id
+ */
+void xen_acpi_wmi_set_event_id(uint8_t event_id)
+{
+ if ( cmd_info.invocation_type != XEN_ACPI_WMI_GET_EVENT_DATA )
+ {
+ fprintf(logfile,
+ "XEN WMI: Request to set event ID with incorrect invocation type!!!\n");
+ return;
+ }
+
+ cmd_info.invocation_data.xen_wmi_arg.xen_wmi_event_data_arg.event_id = event_id;
+}
+
+/*
+ * xen_acpi_wmi_cmd_port_read
+ */
+static uint32_t xen_acpi_wmi_cmd_port_read(void *opaque, uint32_t addr)
+{
+#ifdef XEN_ACPI_WMI_DEBUG_EXT
+ fprintf(logfile, "XEN WMI: In cmd port read - %d\n",
+ cmd_info.cmd_type);
+#endif
+ return cmd_info.cmd_type;
+}
+
+/*
+ * xen_acpi_wmi_cmd_port_write
+ */
+static void xen_acpi_wmi_cmd_port_write(void *opaque, uint32_t addr, uint32_t val)
+{
+#ifdef XEN_ACPI_WMI_DEBUG_EXT
+ fprintf(logfile, "XEN WMI: In cmd port write - %d\n", val);
+#endif
+ cmd_info.cmd_type = val;
+ if ( val < XEN_ACPI_WMI_CMD_INIT || val >= XEN_ACPI_WMI_CMD_UNDEFINED )
+ {
+ fprintf(logfile,"XEN WMI: Unknown xen acpi wmi command - %d\n", val);
+ cmd_info.invocation_type = XEN_ACPI_WMI_UNDEFINED;
+ cmd_info.current_index = 0;
+ return;
+ }
+
+ if ( val == XEN_ACPI_WMI_CMD_EXECUTE )
+ xen_acpi_wmi_execute();
+}
+
+/*
+ * xen_acpi_wmi_data_port_readb
+ */
+static uint32_t xen_acpi_wmi_data_port_readb(void *opaque, uint32_t addr)
+{
+ xen_wmi_buffer_t *buffer;
+ byte ret;
+
+ if ( cmd_info.cmd_type == XEN_ACPI_WMI_CMD_OUT_BUFFER )
+ {
+ buffer = xen_acpi_wmi_get_output_buffer();
+ if ( buffer == NULL || buffer->copied_length == NULL )
+ return 0x0;
+
+ if ( *buffer->copied_length == 0 )
+ return 0x0;
+
+ if ( cmd_info.current_index >= *buffer->copied_length )
+ {
+ fprintf(logfile,
+ "XEN WMI: Output buffer index overflow. Current - %d Max - %d\n",
+ cmd_info.current_index, *buffer->copied_length);
+ cmd_info.cmd_type = XEN_ACPI_WMI_CMD_UNDEFINED;
+ return 0x0;
+ }
+
+ ret = ((byte*)buffer->pointer)[cmd_info.current_index];
+ if ( cmd_info.current_index == buffer->length-1 )
+ {
+ /* @TODO: We expect that the firmware would read all of
+ * the output buffer before releasing it. This
+ * could result in a leak if the firmware chooses
+ * to ignore the return buffer. It might make sense to
+ * introduce a cleanup command. */
+ cmd_info.cmd_type = XEN_ACPI_WMI_CMD_UNDEFINED;
+ buffer->length = 0;
+ free(buffer->pointer);
+ buffer->pointer = NULL;
+ free(buffer->copied_length);
+ buffer->copied_length = NULL;
+ }
+
+#ifdef XEN_ACPI_WMI_DEBUG_EXT
+ fprintf(logfile, "XEN WMI: Data port read returned - %d\n", ret);
+#endif
+ cmd_info.current_index++;
+ return ret;
+ }
+
+ fprintf(logfile, "XEN WMI: Data port read byte. Shouldn't be here!!!\n");
+ return 0x0;
+}
+
+/*
+ * xen_acpi_wmi_data_port_writeb
+ */
+static void xen_acpi_wmi_data_port_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+#ifdef XEN_ACPI_WMI_DEBUG_EXT
+ fprintf(logfile, "XEN WMI: In data port write byte - %d\n", val);
+#endif
+
+ switch( cmd_info.cmd_type )
+ {
+ case XEN_ACPI_WMI_CMD_INIT:
+ cmd_info.invocation_type = val;
+ cmd_info.current_index = 0;
+ memset(&cmd_info.invocation_data, 0, sizeof(cmd_info.invocation_data));
+ break;
+ case XEN_ACPI_WMI_CMD_GUID:
+ xen_acpi_wmi_set_guid(val);
+ break;
+ case XEN_ACPI_WMI_CMD_IN_BUFFER:
+ xen_acpi_wmi_set_in_buffer(val);
+ break;
+ case XEN_ACPI_WMI_CMD_EVENT_ID:
+ xen_acpi_wmi_set_event_id(val);
+ break;
+ default:
+ fprintf(logfile,
+ "XEN WMI: Attempting to write to data(byte) port with incompatible cmd type %d\n",
+ cmd_info.cmd_type);
+ break;
+ }
+}
+
+/*
+ * xen_acpi_wmi_data_port_readl
+ */
+static uint32_t xen_acpi_wmi_data_port_readl(void *opaque, uint32_t addr)
+{
+ xen_wmi_buffer_t *buffer;
+
+ if ( cmd_info.cmd_type == XEN_ACPI_WMI_CMD_OUT_BUFFER_SIZE )
+ {
+ buffer = xen_acpi_wmi_get_output_buffer();
+ if ( buffer == NULL || buffer->copied_length == NULL )
+ return 0x0;
+
+ if (*buffer->copied_length == 0 )
+ return 0x0;
+
+ cmd_info.current_index = 0;
+#ifdef XEN_ACPI_WMI_DEBUG_EXT
+ fprintf(logfile, "XEN WMI: Output buffer length is - %d\n", *buffer->copied_length);
+#endif
+ return *buffer->copied_length;
+ }
+
+ fprintf(logfile, "XEN WMI: Data port read long. Shouldn't be here!!!\n");
+ return 0x0;
+}
+
+/*
+ * xen_acpi_wmi_data_port_writel
+ */
+static void xen_acpi_wmi_data_port_writel(void *opaque, uint32_t addr, uint32_t val)
+{
+#ifdef XEN_ACPI_WMI_DEBUG_EXT
+ fprintf(logfile, "XEN WMI: In data port write long - %d\n", val);
+#endif
+
+ switch( cmd_info.cmd_type )
+ {
+ case XEN_ACPI_WMI_CMD_OBJ_INSTANCE:
+ xen_acpi_wmi_set_cmd_instance(val);
+ break;
+ case XEN_ACPI_WMI_CMD_METHOD_ID:
+ xen_acpi_wmi_set_method_id(val);
+ break;
+ case XEN_ACPI_WMI_CMD_IN_BUFFER_SIZE:
+ xen_acpi_wmi_set_in_buffer_size(val);
+ break;
+ default:
+ fprintf(logfile,
+ "XEN WMI: Attempting to write to data(long) port with incompatible cmd type %d\n",
+ cmd_info.cmd_type);
+ break;
+ }
+}
+
+/*
+ * xen_acpi_wmi_init
+ */
+void xen_acpi_wmi_init(PCIDevice *device)
+{
+ char dev_name[64];
+ char *oem_buffer;
+
+ cmd_info.invocation_type = XEN_ACPI_WMI_UNDEFINED;
+ cmd_info.current_index = 0;
+
+ oem_buffer = xenstore_device_model_read(domid, "oem_value_add", NULL);
+ if ( oem_buffer == NULL )
+ {
+#ifdef XEN_ACPI_WMI_DEBUG
+ fprintf(logfile,"OEM value add disabled!\n");
+#endif
+ return;
+ }
+
+ sprintf(dev_name, "/dev/%s", XEN_WMI_DEVICE_NAME);
+ xen_wmi_device = open(dev_name, 0);
+ if ( xen_wmi_device < 0 )
+ {
+ fprintf(logfile,
+ "XEN WMI: Unable to open device - %s\n", XEN_WMI_DEVICE_NAME);
+ return;
+ }
+
+ register_ioport_read(XEN_ACPI_WMI_CMD_PORT, 1, 1, xen_acpi_wmi_cmd_port_read, device);
+ register_ioport_write(XEN_ACPI_WMI_CMD_PORT, 1, 1, xen_acpi_wmi_cmd_port_write, device);
+ register_ioport_read(XEN_ACPI_WMI_DATA_PORTB, 1, 1, xen_acpi_wmi_data_port_readb, device);
+ register_ioport_write(XEN_ACPI_WMI_DATA_PORTB, 1, 1, xen_acpi_wmi_data_port_writeb, device);
+ register_ioport_read(XEN_ACPI_WMI_DATA_PORTL, 4, 4, xen_acpi_wmi_data_port_readl, device);
+ register_ioport_write(XEN_ACPI_WMI_DATA_PORTL, 4, 4, xen_acpi_wmi_data_port_writel, device);
+
+ xenstore_register_for_oem_events();
+#ifdef XEN_ACPI_WMI_DEBUG
+ fprintf(logfile, "XEN WMI: XEN ACPI WMI registration succeeded!!!\n");
+#endif
+}
+
+/*
+ * xen_acpi_wmi_cleanup(void)
+ */
+void xen_acpi_wmi_cleanup(void)
+{
+ if ( xen_wmi_device > 0 )
+ close(xen_wmi_device);
+}
+
+#else
+
+void xen_acpi_wmi_init(PCIDevice *device) { }
+void xen_acpi_wmi_cleanup(void) { }
+
+#endif /* CONFIG_NO_XEN_ACPI_WMI */
+