]> xenbits.xen.org Git - xenclient/linux-2.6.27-pq.git/commitdiff
Add acpi-wmi files inadvertently removed by previous patch.
authorKamala Narasimhan <kamala.narasimhan@citrix.com>
Thu, 14 May 2009 20:56:41 +0000 (16:56 -0400)
committerKamala Narasimhan <kamala.narasimhan@citrix.com>
Thu, 14 May 2009 20:56:41 +0000 (16:56 -0400)
master/xen-acpi-wmi

index 7ad3ea5682c6b29f73e1a2cda4035d845c482726..6fe9b70a5b14e64f21173dc9a46a34b79ea8d53c 100644 (file)
@@ -559,3 +559,469 @@ index ab35228..873e5a3 100644
  obj-$(CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND)   += sfc_netfront/
  obj-$(CONFIG_XEN_NETDEV_ACCEL_SFC_BACKEND)    += sfc_netback/
 +obj-$(CONFIG_XEN_ACPI_WMI_WRAPPER)              += acpi-wmi/
+diff --git a/drivers/xen/acpi-wmi/Makefile b/drivers/xen/acpi-wmi/Makefile
+new file mode 100644
+index 0000000..afe5d9d
+--- /dev/null
++++ b/drivers/xen/acpi-wmi/Makefile
+@@ -0,0 +1,2 @@
++
++obj-y := acpi-wmi.o
+diff --git a/drivers/xen/acpi-wmi/acpi-wmi.c b/drivers/xen/acpi-wmi/acpi-wmi.c
+new file mode 100644
+index 0000000..90d1e3f
+--- /dev/null
++++ b/drivers/xen/acpi-wmi/acpi-wmi.c
+@@ -0,0 +1,352 @@
++/******************************************************************************
++ * drivers/xen/acpi-wmi/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 version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++/* Xen acpi-wmi implementation provides the interface required for userspace 
++ * module (qemu) to communicate with acpi wmi wrapper kernel driver.
++ * Upon receiving request from qemu to call a WMI method or query or set WMI
++ * data, it communicates the request to kernel acpi wmi layer which then 
++ * interacts with the base firmware to get the necessary information/execute
++ * relevant AML method etc.  The result returned by the base firmware is then
++ * communicated back to the userspace module (qemu). 
++ */
++
++#include <linux/module.h>
++#include <linux/miscdevice.h>
++#include <linux/acpi.h>
++#include <asm/uaccess.h>
++#include <xen/public/acpi-wmi.h>
++
++/* #define XEN_WMI_DEBUG */
++
++static bool xen_wmi_misc_dev_registered = false;
++static int xen_wmi_ioctl(struct inode *inode, struct file *filp, 
++                         unsigned int cmd, unsigned long arg);
++
++static struct file_operations xen_wmi_fops = {
++    .owner = THIS_MODULE,
++    .ioctl = xen_wmi_ioctl,
++};
++
++static struct miscdevice xen_wmi_misc = {
++        .minor    = MISC_DYNAMIC_MINOR,
++        .name     = XEN_WMI_DEVICE_NAME,
++        .fops     = &xen_wmi_fops,
++};
++
++/*
++ * xen_wmi_copy_input_buffer
++ */
++int xen_wmi_copy_input_buffer(xen_wmi_buffer_t *user_buf, struct acpi_buffer *acpi_buf)
++{
++    if ( user_buf->length <= 0 )
++        return XEN_WMI_SUCCESS; 
++
++    acpi_buf->pointer = kmalloc(user_buf->length, GFP_KERNEL);
++    if ( acpi_buf->pointer == NULL )
++    {
++        printk("XEN WMI: xen_wmi_copy_input_buffer - Buffer allocation failure\n");
++        return XEN_WMI_NOT_ENOUGH_MEMORY; 
++    }
++
++    if ( copy_from_user(acpi_buf->pointer,
++                        (char __user *)user_buf->pointer,
++                        user_buf->length) )
++    {
++        printk("XEN WMI: Unable to copy input buffer argument\n");
++        kfree(acpi_buf->pointer);
++        return XEN_WMI_EFAULT;
++    }
++
++    acpi_buf->length = user_buf->length; 
++    return XEN_WMI_SUCCESS; 
++}
++
++/*
++ * xen_wmi_copy_output_buffer
++ */
++int xen_wmi_copy_output_buffer(struct acpi_buffer *acpi_buf, xen_wmi_buffer_t *user_buf)
++{
++    /* IMPORTANT NOTE:  It is a little short sighted to assume that the return type
++     * will not be anything other than buffer type.  A follow-up check-in will
++     * cover more types. 
++     */
++
++    union acpi_object *acpi_obj = acpi_buf->pointer;
++
++    if ( acpi_obj == NULL )
++    {
++        printk("XEN WMI: Invalid acpi buffer!\n");
++        return XEN_WMI_EFAULT;
++    }
++
++    if ( acpi_obj->type != ACPI_TYPE_BUFFER )
++    {
++        printk("XEN WMI: Unsupported acpi return object type - %d\n", acpi_obj->type);
++        return XEN_WMI_UNSUPPORTED_TYPE;
++    }
++
++    if ( copy_to_user((char __user *) user_buf->copied_length, &acpi_obj->buffer.length, sizeof(size_t)) )
++    {
++        printk("XEN WMI: Invalid copied length user buffer!\n");
++        return XEN_WMI_INVALID_ARGUMENT;
++    }
++
++    if ( user_buf->length < acpi_obj->buffer.length ) 
++    {
++        printk("XEN WMI: Required buffer length is - %d\n", acpi_obj->buffer.length);
++        printk("XEN WMI: Passed in length is - %d\n", user_buf->length);
++        return XEN_WMI_BUFFER_TOO_SMALL;
++    }
++
++    if ( copy_to_user((char __user *) user_buf->pointer, acpi_obj->buffer.pointer, acpi_obj->buffer.length) )
++    {
++        printk("XEN WMI: Invalid user output buffer\n");
++        return XEN_WMI_NOT_ENOUGH_MEMORY; 
++    }
++
++    return XEN_WMI_SUCCESS; 
++} 
++
++#ifdef XEN_WMI_DEBUG
++
++/*
++ * xen_wmi_print_buffer
++ */
++void xen_wmi_print_buffer(struct acpi_buffer *acpi_buf)
++{
++    int count;
++    union acpi_object *acpi_obj = acpi_buf->pointer;
++
++    if ( acpi_obj == NULL || acpi_obj->type != ACPI_TYPE_BUFFER )
++    {
++        printk("XEN WMI: Unsupported output buffer data!\n");
++        return ;
++    }
++
++    printk("XEN WMI: Output buffer length is - %d\n", acpi_obj->buffer.length);
++    printk("XEN WMI:  Buffer:  ");
++    for (count=0; count < acpi_obj->buffer.length; count++)
++        printk("%d  ", ((byte *)(acpi_obj->buffer.pointer))[count]);
++    printk("\n");
++}
++
++#endif /* XEN_WMI_DEBUG */
++
++/*
++ * xen_wmi_invoke_method 
++ */
++int xen_wmi_invoke_method(xen_wmi_obj_invocation_data_t *obj_inv_data)
++{
++    int result;
++    struct acpi_buffer in_buf, *in_arg = NULL, out_buf = {ACPI_ALLOCATE_BUFFER, NULL};
++
++    result = xen_wmi_copy_input_buffer(&obj_inv_data->xen_wmi_arg.xen_wmi_method_arg.in_buf,
++                                       &in_buf); 
++    if ( result != XEN_WMI_SUCCESS )
++        return result;
++
++    if ( in_buf.length > 0 ) 
++        in_arg = &in_buf;
++
++    result = wmi_evaluate_method(obj_inv_data->guid, 
++                 obj_inv_data->xen_wmi_arg.xen_wmi_method_arg.instance, 
++                 obj_inv_data->xen_wmi_arg.xen_wmi_method_arg.method_id, 
++                 in_arg, &out_buf);
++
++    if ( in_arg != NULL )
++        kfree(in_buf.pointer);
++
++    if ( out_buf.length > 0  && result == XEN_WMI_SUCCESS )
++    {
++#ifdef XEN_WMI_DEBUG
++        xen_wmi_print_buffer(&out_buf);
++#endif
++        result = xen_wmi_copy_output_buffer(&out_buf,
++                                            &obj_inv_data->xen_wmi_arg.xen_wmi_method_arg.out_buf);
++        kfree(out_buf.pointer); 
++    }
++    else if ( result != XEN_WMI_SUCCESS )
++        printk("XEN WMI- Invoke WMI method failed with error - %d\n", result);
++
++    return result;
++} 
++
++/*
++ * xen_wmi_query_object
++ */
++int xen_wmi_query_object(xen_wmi_obj_invocation_data_t *obj_inv_data)
++{
++    int result; 
++    struct acpi_buffer out_buf = {ACPI_ALLOCATE_BUFFER, NULL};
++
++    result = wmi_query_block(obj_inv_data->guid, 
++                             obj_inv_data->xen_wmi_arg.xen_wmi_query_obj_arg.instance,
++                             &out_buf);
++
++    if ( out_buf.length > 0 && result == XEN_WMI_SUCCESS )
++    {
++#ifdef XEN_WMI_DEBUG
++        xen_wmi_print_buffer(&out_buf);
++#endif
++        result = xen_wmi_copy_output_buffer(&out_buf,
++                                            &obj_inv_data->xen_wmi_arg.xen_wmi_query_obj_arg.out_buf);
++        kfree(out_buf.pointer);
++    }
++    else
++        printk("XEN WMI - Query WMI object failed with error - %d; output buffer length - %d\n",
++               result, out_buf.length);
++
++    return result;
++}
++
++/*
++ * xen_wmi_set_object
++ */
++int xen_wmi_set_object(xen_wmi_obj_invocation_data_t *obj_inv_data) 
++{
++    int result;
++    struct acpi_buffer in_buf;
++
++    if ( obj_inv_data->xen_wmi_arg.xen_wmi_set_obj_arg.in_buf.length <= 0 )
++        return XEN_WMI_INVALID_ARGUMENT;
++
++    result = xen_wmi_copy_input_buffer(&obj_inv_data->xen_wmi_arg.xen_wmi_set_obj_arg.in_buf,
++                                       &in_buf);
++    if ( result != XEN_WMI_SUCCESS )
++        return result;
++
++    result = wmi_set_block(obj_inv_data->guid, 
++                           obj_inv_data->xen_wmi_arg.xen_wmi_set_obj_arg.instance,
++                           &in_buf); 
++    if ( result != XEN_WMI_SUCCESS )
++        printk("XEN WMI: Set object failed with error - %d\n", result);
++
++    kfree(in_buf.pointer);
++    return result;
++}
++
++/*
++ * xen_wmi_get_event_data 
++ */
++int xen_wmi_get_event_data(xen_wmi_obj_invocation_data_t *obj_inv_data) 
++{
++    int result;
++    struct acpi_buffer out_buf = {ACPI_ALLOCATE_BUFFER, NULL};
++
++    result = wmi_get_event_data(obj_inv_data->xen_wmi_arg.xen_wmi_event_data_arg.event_id,
++                       &out_buf);
++
++    if ( out_buf.length > 0 && result == XEN_WMI_SUCCESS )
++    {
++#ifdef XEN_WMI_DEBUG
++        xen_wmi_print_buffer(&out_buf);
++#endif
++        result = xen_wmi_copy_output_buffer(&out_buf,
++                                            &obj_inv_data->xen_wmi_arg.xen_wmi_event_data_arg.out_buf);
++        kfree(out_buf.pointer);
++    }
++    else
++        printk("XEN WMI: Get event data failed with error - %d\n", result);
++
++    return result;
++}
++
++/*
++ * xen_wmi_ioctl 
++ */
++static int xen_wmi_ioctl(struct inode *inode, struct file *filp,
++                         unsigned int cmd, unsigned long arg)
++{
++    xen_wmi_obj_invocation_data_t obj_inv_data;
++
++#ifdef XEN_WMI_DEBUG
++    printk("XEN WMI:  In xen_wmi_ioctl - %d\n", cmd);
++#endif
++
++    memset(&obj_inv_data, 0, sizeof(obj_inv_data));
++    if ( copy_from_user(&obj_inv_data, (char __user *)arg, sizeof(obj_inv_data)) )
++    {
++        printk("XEN WMI: Invalid object invocation parameter\n");
++        return XEN_WMI_EFAULT;
++    }
++ 
++    switch ( cmd ) 
++    {
++        case XEN_WMI_IOCTL_CALL_METHOD:
++            return xen_wmi_invoke_method(&obj_inv_data);
++        case XEN_WMI_IOCTL_QUERY_OBJECT:
++            return xen_wmi_query_object(&obj_inv_data); 
++        case XEN_WMI_IOCTL_SET_OBJECT:
++            return xen_wmi_set_object(&obj_inv_data); 
++        case XEN_WMI_IOCTL_GET_EVENT_DATA:
++            return xen_wmi_get_event_data(&obj_inv_data); 
++    }
++
++    return XEN_WMI_ENOIOCTLCMD;
++}
++
++/*
++ * xen_wmi_init 
++ */
++static int __init xen_wmi_init(void)
++{
++    int ret;
++
++    ret = misc_register(&xen_wmi_misc);
++    if ( ret < 0 )
++        printk("XEN WMI: misc_register failed with error - %d\n", ret);
++    else
++        xen_wmi_misc_dev_registered = true;
++
++#ifdef XEN_WMI_DEBUG
++    printk("XEN WMI: xen-acpi-wmi misc_register succeeded!\n"); 
++#endif
++    return ret;
++}
++
++/*
++ * xen_wmi_exit 
++ */
++static void xen_wmi_exit(void)
++{
++    int ret;
++
++    if ( xen_wmi_misc_dev_registered == false )
++        return;
++
++    if ( (ret = misc_deregister(&xen_wmi_misc)) < 0 )
++        printk("XEN WMI: misc_deregister failed with error - %d\n", ret); 
++}
++
++module_init(xen_wmi_init);
++module_exit(xen_wmi_exit);
++MODULE_LICENSE("Dual BSD/GPL");
++
+diff --git a/include/xen/public/acpi-wmi.h b/include/xen/public/acpi-wmi.h
+new file mode 100644
+index 0000000..097639b
+--- /dev/null
++++ b/include/xen/public/acpi-wmi.h
+@@ -0,0 +1,94 @@
++/******************************************************************************
++ * acpi-wmi.h
++ *
++ * Interface to /proc/misc/xen-acpi-wmi
++ *
++ * 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 version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++
++#ifndef _XEN_WMI_ACPI
++#define _XEN_WMI_ACPI
++
++/*
++ * Userspace Interface
++ */
++
++#define XEN_WMI_DEVICE_NAME              "xen-acpi-wmi"
++#define XEN_WMI_GUID_SIZE                16
++
++#define XEN_WMI_SUCCESS                  0
++#define XEN_WMI_UNSUPPORTED_TYPE        -1
++#define XEN_WMI_BUFFER_TOO_SMALL        -11
++#define XEN_WMI_NOT_ENOUGH_MEMORY       -12
++#define XEN_WMI_EFAULT                  -14
++#define XEN_WMI_INVALID_ARGUMENT        -22
++#define XEN_WMI_ENOIOCTLCMD             -515
++ 
++#define XEN_WMI_IOCTL_CALL_METHOD        100
++#define XEN_WMI_IOCTL_QUERY_OBJECT       101
++#define XEN_WMI_IOCTL_SET_OBJECT         102
++#define XEN_WMI_IOCTL_GET_EVENT_DATA     103
++
++typedef unsigned char byte;
++
++typedef struct xen_wmi_buffer {
++    size_t       length; 
++    void        *pointer;
++    size_t      *copied_length;
++} xen_wmi_buffer_t;
++
++typedef struct xen_wmi_obj_invocation_data { 
++    byte                       guid[XEN_WMI_GUID_SIZE];
++    union {
++        struct {
++            ushort             instance;
++            uint               method_id;
++            xen_wmi_buffer_t   in_buf;
++            xen_wmi_buffer_t   out_buf;
++        } xen_wmi_method_arg;
++
++        struct {
++            ushort             instance;
++            xen_wmi_buffer_t   out_buf;
++        } xen_wmi_query_obj_arg;
++
++        struct {
++            ushort             instance;
++            xen_wmi_buffer_t   in_buf;
++        } xen_wmi_set_obj_arg;
++
++        struct {
++            ushort             event_id;
++            xen_wmi_buffer_t   out_buf;
++        } xen_wmi_event_data_arg;
++    } xen_wmi_arg;
++} xen_wmi_obj_invocation_data_t;
++
++#endif /* _XEN_WMI_ACPI */
++