+++ /dev/null
-diff --git a/hw/battery_mgmt.c b/hw/battery_mgmt.c
-index 3ddeb09..883b150 100644
---- a/hw/battery_mgmt.c
-+++ b/hw/battery_mgmt.c
-@@ -229,15 +229,21 @@ static uint32_t battery_port_2_readb(void *opaque, uint32_t addr)
-
- static uint32_t battery_port_3_readb(void *opaque, uint32_t addr)
- {
-- if ( power_mgmt_mode == PM_MODE_PT || power_mgmt_mode == PM_MODE_NON_PT ) {
-- if ( (power_mgmt_mode == PM_MODE_PT) && (is_battery_pt_feasible() == 0) )
-- return 0x0F;
-- return 0x1F;
-- }
-+ uint32_t system_state;
-
-- return 0x0F;
--}
-+ if ( power_mgmt_mode != PM_MODE_PT && power_mgmt_mode != PM_MODE_NON_PT )
-+ return 0x0;
-+
-+ if ( (power_mgmt_mode == PM_MODE_PT) && (is_battery_pt_feasible() == 0) )
-+ return 0x0;
-
-+ system_state = xenstore_read_ac_adapter_state();
-+ if ( xenstore_read_lid_state() == 1 )
-+ system_state |= 0x4;
-+
-+ system_state |= 0x2;
-+ return system_state;
-+}
-
- void battery_mgmt_non_pt_mode_init(PCIDevice *device)
- {
-@@ -290,6 +296,7 @@ void battery_mgmt_init(PCIDevice *device)
- }
-
- register_ioport_read(BATTERY_PORT_3, 1, 1, battery_port_3_readb, device);
-+ xenstore_register_for_pm_events();
-
- #ifdef BATTERY_MGMT_DEBUG
- fprintf(logfile, "Power management mode set to - %d\n", power_mgmt_mode);
-diff --git a/hw/pass-through.c b/hw/pass-through.c
-index 3420e95..e7c968d 100644
---- a/hw/pass-through.c
-+++ b/hw/pass-through.c
-@@ -107,7 +107,9 @@ struct dpci_infos {
- PCIBus *e_bus;
- struct pci_access *pci_access;
-
--} dpci_infos;
-+};
-+
-+struct dpci_infos dpci_infos;
-
- char mapped_machine_irq[PT_NR_IRQS] = {0};
-
-@@ -899,6 +901,12 @@ static int pci_slot_match(int bus, int dev, int func, int slot)
- return 0;
- }
-
-+int pcibus_devnfn_in_use(int slot)
-+{
-+ PCIBus *e_bus = dpci_infos.e_bus;
-+ return pci_devfn_in_use(e_bus, slot << 3);
-+}
-+
- /* Insert a new pass-through device into a specific pci slot.
- * input dom:bus:dev.func@slot, chose free one if slot == AUTO_PHP_SLOT
- * return -2: requested slot not available
-diff --git a/hw/pass-through.h b/hw/pass-through.h
-index 1752e8d..96d802a 100644
---- a/hw/pass-through.h
-+++ b/hw/pass-through.h
-@@ -396,5 +396,7 @@ u8 pt_pci_host_read_byte(int bus, int dev, int fn, u32 addr);
- u16 pt_pci_host_read_word(int bus, int dev, int fn, u32 addr);
- u32 pt_pci_host_read_long(int bus, int dev, int fn, u32 addr);
-
-+int pcibus_devnfn_in_use(int slot);
-+
- #endif /* __PASSTHROUGH_H__ */
-
-diff --git a/hw/pc.h b/hw/pc.h
-index 8b71d48..cc6246a 100644
---- a/hw/pc.h
-+++ b/hw/pc.h
-@@ -106,6 +106,9 @@ int acpi_table_add(const char *table_desc);
-
- void acpi_php_add(int);
- void acpi_php_del(int);
-+void acpi_ac_adapter_state_changed(void);
-+void acpi_power_button_pressed(void);
-+void acpi_lid_state_changed(void);
-
- /* hpet.c */
- extern int no_hpet;
-diff --git a/hw/piix4acpi.c b/hw/piix4acpi.c
-index 7844cb8..99359ff 100644
---- a/hw/piix4acpi.c
-+++ b/hw/piix4acpi.c
-@@ -53,6 +53,10 @@
-
- /* The bit in GPE0_STS/EN to notify the pci hotplug event */
- #define ACPI_PHP_GPE_BIT 3
-+#define ACPI_PHP_SLOT_NUM NR_PCI_DEV
-+#define ACPI_AC_POWER_STATE_BIT 0x1c
-+#define ACPI_POWER_BUTTON_BIT 0x1
-+#define ACPI_LID_STATE_BIT 0x17
-
- typedef struct AcpiDeviceState AcpiDeviceState;
- AcpiDeviceState *acpi_device_table;
-@@ -192,8 +196,6 @@ static void acpi_map(PCIDevice *pci_dev, int region_num,
- battery_mgmt_init(pci_dev);
- }
-
--#ifdef CONFIG_PASSTHROUGH
--
- static inline int test_bit(uint8_t *map, int bit)
- {
- return ( map[bit / 8] & (1 << (bit % 8)) );
-@@ -210,6 +212,44 @@ static inline void clear_bit(uint8_t *map, int bit)
- }
-
- extern FILE *logfile;
-+
-+void acpi_ac_adapter_state_changed(void)
-+{
-+ GPEState *s = &gpe_state;
-+
-+ if ( !test_bit(&s->gpe0_sts[0], ACPI_AC_POWER_STATE_BIT) &&
-+ test_bit(&s->gpe0_en[0], ACPI_AC_POWER_STATE_BIT) ) {
-+ set_bit(&s->gpe0_sts[0], ACPI_AC_POWER_STATE_BIT);
-+ s->sci_asserted = 1;
-+ qemu_irq_raise(sci_irq);
-+ }
-+}
-+
-+void acpi_power_button_pressed(void)
-+{
-+ GPEState *s = &gpe_state;
-+ if ( !test_bit(&s->gpe0_sts[0], ACPI_POWER_BUTTON_BIT) &&
-+ test_bit(&s->gpe0_en[0], ACPI_POWER_BUTTON_BIT) ) {
-+ set_bit(&s->gpe0_sts[0], ACPI_POWER_BUTTON_BIT);
-+ s->sci_asserted = 1;
-+ qemu_irq_raise(sci_irq);
-+ }
-+}
-+
-+void acpi_lid_state_changed(void)
-+{
-+ GPEState *s = &gpe_state;
-+
-+ if ( !test_bit(&s->gpe0_sts[0], ACPI_LID_STATE_BIT) &&
-+ test_bit(&s->gpe0_en[0], ACPI_LID_STATE_BIT) ) {
-+ set_bit(&s->gpe0_sts[0], ACPI_LID_STATE_BIT);
-+ s->sci_asserted = 1;
-+ qemu_irq_raise(sci_irq);
-+ }
-+}
-+
-+#ifdef CONFIG_PASSTHROUGH
-+
- static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
- {
- #if defined(DEBUG)
-@@ -238,11 +278,8 @@ static uint32_t acpi_php_readb(void *opaque, uint32_t addr)
- case ACPI_PHP_IO_ADDR:
- val = hotplug_slots->plug_evt;
- break;
-- case ACPI_PHP_IO_ADDR + 1:
-- val = hotplug_slots->plug_slot;
-- break;
- default:
-- num = addr - ACPI_PHP_IO_ADDR - 2;
-+ num = addr - ACPI_PHP_IO_ADDR - 1;
- val = hotplug_slots->status[num];
- }
-
-@@ -255,7 +292,7 @@ static uint32_t acpi_php_readb(void *opaque, uint32_t addr)
- static void acpi_php_writeb(void *opaque, uint32_t addr, uint32_t val)
- {
- PHPSlots *hotplug_slots = opaque;
-- int slot;
-+ int php_slot;
-
- fprintf(logfile, "ACPI PCI hotplug: write addr=0x%x, val=0x%x.\n",
- addr, val);
-@@ -263,21 +300,17 @@ static void acpi_php_writeb(void *opaque, uint32_t addr, uint32_t val)
- switch (addr)
- {
- case ACPI_PHP_IO_ADDR:
-- case ACPI_PHP_IO_ADDR + 1:
- break;
- default:
-- slot = addr - ACPI_PHP_IO_ADDR - 2;
-+ php_slot = addr - ACPI_PHP_IO_ADDR - 1;
- if ( val == 0x1 ) { /* Eject command */
- /* make _STA of the slot 0 */
-- hotplug_slots->status[slot] = 0;
-+ hotplug_slots->status[php_slot] = 0;
-
- /* clear the hotplug event */
- hotplug_slots->plug_evt = 0;
-- hotplug_slots->plug_slot = 0;
--
- /* power off the slot */
-- power_off_php_slot(slot);
--
-+ power_off_php_slot(php_slot);
- /* signal the CP ACPI hot remove done. */
- xenstore_record_dm_state("pci-removed");
- }
-@@ -563,9 +596,9 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
- d->pm1_control = SCI_EN;
-
- acpi_map((PCIDevice *)d, 0, 0x1f40, 0x10, PCI_ADDRESS_SPACE_IO);
-+ gpe_acpi_init();
-
- #ifdef CONFIG_PASSTHROUGH
-- gpe_acpi_init();
- php_slots_init();
- register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, d);
- #endif
-diff --git a/qemu-xen.h b/qemu-xen.h
-index 387ca35..2654b67 100644
---- a/qemu-xen.h
-+++ b/qemu-xen.h
-@@ -130,6 +130,9 @@ char *xenstore_vm_read(int domid, const char *key, unsigned int *len);
- char *xenstore_device_model_read(int domid, const char *key, unsigned int *len);
- char *xenstore_read_battery_data(int battery_status);
- int xenstore_refresh_battery_status(void);
-+void xenstore_register_for_pm_events(void);
-+int xenstore_read_ac_adapter_state(void);
-+int xenstore_read_lid_state(void);
- int xenstore_pv_driver_build_blacklisted(uint16_t product_number,
- uint32_t build_nr);
-
-diff --git a/xenstore.c b/xenstore.c
-index 383e010..659bc00 100644
---- a/xenstore.c
-+++ b/xenstore.c
-@@ -27,6 +27,7 @@
-
- #include "hw.h"
- #include "pci.h"
-+#include "pc.h"
- #include "qemu-timer.h"
- #include "qemu-xen.h"
-
-@@ -981,6 +982,21 @@ void xenstore_process_event(void *opaque)
- xenstore_watch_callbacks[i].cb(vec[XS_WATCH_TOKEN],
- xenstore_watch_callbacks[i].opaque);
-
-+ if (!strcmp(vec[XS_WATCH_TOKEN], "acadapterstatechangeevt")) {
-+ acpi_ac_adapter_state_changed();
-+ goto out;
-+ }
-+
-+ if (!strcmp(vec[XS_WATCH_TOKEN], "pwrbuttonpressedevt")) {
-+ acpi_power_button_pressed();
-+ goto out;
-+ }
-+
-+ if (!strcmp(vec[XS_WATCH_TOKEN], "lidstatechangeevt")) {
-+ acpi_lid_state_changed();
-+ goto out;
-+ }
-+
- if (!strcmp(vec[XS_WATCH_TOKEN], "logdirty")) {
- xenstore_process_logdirty_event();
- goto out;
-@@ -1710,3 +1726,37 @@ int *xenstore_get_domids(int *len)
- return tab;
- }
-
-+void xenstore_register_for_pm_events(void)
-+{
-+ xs_watch(xsh, "/pm/events/acadapterstatechanged", "acadapterstatechangeevt");
-+ xs_watch(xsh, "/pm/events/lidstatechanged", "lidstatechangeevt");
-+ xs_watch(xsh, "/pm/events/powerbuttonpressed", "pwrbuttonpressedevt");
-+}
-+
-+int xenstore_read_ac_adapter_state(void)
-+{
-+ int ac_state = 1;
-+ char *buffer;
-+
-+ buffer = xenstore_extended_power_mgmt_read("ac_adapter", NULL);
-+ if ( buffer == NULL )
-+ return ac_state;
-+
-+ ac_state = strtoull(buffer, NULL, 10);
-+ free(buffer);
-+ return ac_state;
-+}
-+
-+int xenstore_read_lid_state(void)
-+{
-+ int lid_state = 1;
-+ char * buffer;
-+
-+ buffer = xenstore_extended_power_mgmt_read("lid_state", NULL);
-+ if ( buffer == NULL )
-+ return lid_state;
-+
-+ lid_state = strtoull(buffer, NULL, 10);
-+ free(buffer);
-+ return lid_state;
-+}
+void hid_linux_probe(int grab);
+
#endif
+diff --git a/dom0_driver.c b/dom0_driver.c
+new file mode 100644
+index 0000000..1b5cd06
+--- /dev/null
++++ b/dom0_driver.c
+@@ -0,0 +1,697 @@
++/*
++ * QEMU dom0_driver
++ *
++ * Copyright (c) 2009 Citrix Systems
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (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.
++ */
++
++#include "qemu-common.h"
++#include "console.h"
++#include "qemu-timer.h"
++#include "qemu-xen.h"
++
++#include <sys/types.h>
++#include <linux/input.h>
++#include <linux/kd.h>
++#include <dirent.h>
++#include <stdio.h>
++#include <string.h>
++#include <fcntl.h>
++#include <limits.h>
++#include <unistd.h>
++#include <stdlib.h>
++#include <errno.h>
++#include <string.h>
++#include <assert.h>
++#include <time.h>
++
++extern int vga_passthrough;
++extern int intel;
++
++static void dom0_driver_state_change(const char *path, void *opaque);
++static void dom0_driver_command(const char *path, void *opaque);
++static void dom0_driver_leave_done(void);
++
++#define DEBUG_DOM0_DRIVER 1
++#define XS_REFRESH_INTERVAL 1000
++#define DOM0_DRIVER_SWITCH_TIMEOUT 2
++
++#define DOM0_MOUSE 1
++#define DOM0_KEYBOARD 2
++
++#if DEBUG_DOM0_DRIVER
++# define DEBUG(_format_, args...) \
++ do { \
++ char *__str = get_time(); \
++ fprintf(stderr, "[%s] dom0_driver(%d):%d: " _format_, __str, domid, __LINE__, ## args);\
++ free(__str); \
++ } while (false)
++#else
++# define DEBUG(_format_, args...) (void)0
++#endif
++
++#define NB_SLOTS 10
++
++static void dom0_read(void *opaque);
++static void dom0_driver_reset_keyboard(void);
++static void dom0_read_secure(void *opaque);
++struct dom0_driver
++{
++ QEMUTimer *xs_timer;
++ int secure_fd;
++ int (*enter)(void);
++ int (*leave)(void);
++};
++
++struct dom0_driver_handler
++{
++ void (*init)(void);
++ void (*probe)(int);
++ int (*grab_keyboard)(int);
++ int (*grab_mouse)(int);
++ void (*secure_keyboard)(void (*)(int));
++ void (*reset_keyboard)(void);
++ void (*add_binding)(const int *, void (*)(void *), void *);
++};
++
++struct dom0_driver_xs_info
++{
++ int state;
++ int domid;
++ int new_slot;
++ int timestamp;
++ int pre;
++};
++
++static struct dom0_driver_handler dom0_driver_hid_linux =
++{
++ .init = hid_linux_init,
++ .probe = hid_linux_probe,
++ .grab_keyboard = hid_linux_grab_keyboard,
++ .grab_mouse = hid_linux_grab_mouse,
++ .secure_keyboard = hid_linux_secure_keyboard,
++ .reset_keyboard = hid_linux_reset_keyboard,
++ .add_binding = hid_linux_add_binding,
++};
++
++static struct dom0_driver driver;
++static struct dom0_driver_handler *dom0_driver_handler = NULL;
++
++static int dom0_driver_xs_read_dom0(const char *key)
++{
++ char *str = NULL;
++
++ if (!(str = xenstore_read_dom0_driver(key)))
++ {
++ fprintf(stderr, "dom0_driver: fatal the node %s don't exits\n", key);
++ exit(2);
++ }
++ return strtol(str, NULL, 10);
++}
++
++static void dom0_driver_read_xs_info(struct dom0_driver_xs_info *info,
++ int controller)
++{
++ char *str = NULL;
++ char path[128];
++ int val[10];
++ const char *key[] = {"state", "domid", "new-slot", "timestamp", "pre"};
++
++ memset(info, -1, sizeof (struct dom0_driver_xs_info));
++ for (int i = 0; i < sizeof (key) / sizeof (key[0]); i++)
++ {
++ if (controller == DOM0_MOUSE)
++ sprintf(path, "mouse/%s", key[i]);
++ else if (controller == DOM0_KEYBOARD)
++ sprintf(path, "keyboard/%s", key[i]);
++ else
++ {
++ fprintf(stderr, "dom0_driver unknown controller type\n");
++ exit(2);
++ }
++
++ val[i] = -1;
++ if ((str = xenstore_read_dom0_driver(path)))
++ {
++ val[i] = strtol(str, NULL, 10);
++ free(str);
++ }
++ }
++
++ info->state = val[0];
++ info->domid = val[1];
++ info->new_slot = val[2];
++ info->timestamp = val[3];
++ info->pre = val[4];
++}
++
++static void dom0_driver_xs_write(const char *key, int val, int controller)
++{
++ char path[256], str[20];
++
++ if (controller == DOM0_MOUSE)
++ sprintf(path, "mouse/%s", key);
++ else if (controller == DOM0_KEYBOARD)
++ sprintf(path, "keyboard/%s", key);
++ else
++ {
++ DEBUG("unknown controller type\n");
++ exit(2);
++ }
++
++ sprintf(str, "%d", val);
++ DEBUG("write %s=%d\n", path, val);
++ xenstore_write_dom0_driver(path, str);
++}
++
++/*
++** Blanker fonctions
++*/
++static void dom0_driver_blank_changed(void)
++{
++ char *str;
++ int blank;
++
++ if (!(str = xenstore_read_dom0_driver("blank")))
++ return;
++ blank = strtol(str, NULL, 10);
++ free(str);
++ if (blank == 2)
++ {
++ usleep(100 * 1000); /* 100 ms */
++ dom0_driver_leave_done();
++ }
++}
++static int dom0_driver_blank(void)
++{
++ xenstore_write_dom0_driver("blank", "1");
++ return 0;
++}
++static int dom0_driver_unblank(void)
++{
++ xenstore_write_dom0_driver("blank", "0");
++ return 0;
++}
++
++static void dom0_driver_key_switch(int new_slot)
++{
++ struct dom0_driver_xs_info info;
++ char buff[128];
++
++ dom0_driver_read_xs_info(&info, DOM0_MOUSE);
++ assert(info.state == 1);
++
++ sprintf(buff, "switch %d", new_slot);
++
++ DEBUG("Write \"%s\" into xenstore\n", buff);
++ xenstore_write_dom0_driver("command", buff);
++}
++
++static void dom0_driver_read_secure(int ascii)
++{
++ int write_sz;
++
++ if (ascii)
++ {
++ DEBUG("Send %d to xenmgr\n", ascii);
++ write_sz = write(driver.secure_fd, &ascii, 1);
++ if (ascii == -1 || ascii == 27 || write_sz != 1)
++ {
++ dom0_driver_handler->reset_keyboard();
++ dom0_driver_handler->secure_keyboard(NULL);
++ return;
++ }
++ }
++}
++
++static void dom0_driver_detect_secure_auth(void* opaque)
++{
++ struct stat s;
++ int sas_ascii = 1, ret = 0;;
++
++ DEBUG("Received SAS keystroke\n");
++ if ((driver.secure_fd = open("/var/lib/xenmgr/keys", O_WRONLY)) > 0)
++ {
++ DEBUG("write SAS ascii code\n");
++ if ((ret = write(driver.secure_fd, &sas_ascii, 1)) == 1)
++ {
++ DEBUG("Redirect fds to secure callback\n");
++ dom0_driver_handler->secure_keyboard(dom0_driver_read_secure);
++ }
++ DEBUG("writing SAS ret %d\n", ret);
++
++ }
++ else
++ DEBUG("xenmgr file is not there\n");
++}
++
++static void dom0_get_positions(int *positions)
++{
++ int *domids = NULL;
++ int num;
++ char *tmp;
++ unsigned int len;
++ int pos = 0;
++
++ for (int i = 0; i < NB_SLOTS; i++)
++ positions[i] = 0;
++
++ /* Get all the positions */
++ domids = xenstore_get_domids(&num);
++ for (int i = 0; i < num; i++)
++ if (domids[i])
++ {
++ if (!(tmp = xenstore_dom_read(domids[i], "dom0_input/pos", &len)))
++ continue;
++ pos = strtol(tmp, NULL, 10);
++ free(tmp);
++
++ positions[pos] = domids[i];
++ }
++ free(domids);
++}
++
++static void dom0_gr_devices(int grab, int controller)
++{
++ if (controller == DOM0_MOUSE)
++ {
++ DEBUG("%s mouse\n", grab ? "Grab" : "Release");
++ assert(dom0_driver_handler->grab_mouse(grab));
++ }
++ if (controller == DOM0_KEYBOARD)
++ {
++ DEBUG("%s keyboard\n", grab ? "Grab" : "Release");
++ assert(dom0_driver_handler->grab_keyboard(grab));
++ }
++
++ dom0_driver_handler->reset_keyboard();
++ if (!grab)
++ dom0_driver_xs_write("pre", domid, controller);
++ dom0_driver_xs_write("domid", domid, controller);
++ dom0_driver_xs_write("state", grab ? 1 : 2, controller);
++}
++
++static int dom0_dom_alive(int id)
++{
++ xc_dominfo_t info;
++ int rc;
++
++ rc = xc_domain_getinfo(xc_handle, id, 1, &info);
++ return rc == 1 && info.domid == id;
++}
++
++
++static int dom0_driver_failover_switch(void *opaque)
++{
++ int ret = 1;
++ uint32_t t = time(NULL);
++ struct dom0_driver_xs_info mouse, keyboard;
++
++ dom0_driver_read_xs_info(&mouse, DOM0_MOUSE);
++ dom0_driver_read_xs_info(&keyboard, DOM0_KEYBOARD);
++ if (mouse.domid == domid)
++ dom0_driver_handler->probe(1);
++ else
++ dom0_driver_handler->probe(0);
++
++ if (!vga_passthrough)
++ return 0;
++
++ if (mouse.state == -1)
++ {
++ DEBUG("No state grab the device\n");
++ dom0_gr_devices(1, DOM0_KEYBOARD);
++ dom0_gr_devices(1, DOM0_MOUSE);
++ driver.enter();
++ goto out;
++ }
++
++ /* The domain which has the focus crash */
++ if (!dom0_dom_alive(mouse.domid))
++ {
++ DEBUG("steal the focus from %d\n", mouse.domid);
++ dom0_gr_devices(1, DOM0_KEYBOARD);
++ dom0_gr_devices(1, DOM0_MOUSE);
++ driver.enter();
++ goto out;
++ }
++
++ if ( keyboard.state == 2 &&
++ (t - keyboard.timestamp) > DOM0_DRIVER_SWITCH_TIMEOUT)
++ {
++ DEBUG("Keyboard in state 2 for to long, take it back\n");
++ dom0_gr_devices(1, DOM0_KEYBOARD);
++ }
++
++ if (mouse.state == 2 &&
++ (t - mouse.timestamp) > DOM0_DRIVER_SWITCH_TIMEOUT)
++ {
++ DEBUG("Mouse in state 2 for to long, take it back\n");
++ dom0_gr_devices(1, DOM0_MOUSE);
++ DEBUG("Get the focus now !\n");
++ driver.enter();
++ goto out;
++ }
++
++ ret = 0;
++out:
++ qemu_mod_timer(driver.xs_timer, qemu_get_clock(rt_clock) + XS_REFRESH_INTERVAL);
++ return ret;
++}
++
++static void dom0_driver_dom_command(const char *path, void *opaque)
++{
++ unsigned int len;
++ char *str;
++ char buff[256];
++ int positions[NB_SLOTS];
++ int natif_domid;
++ int i;
++ struct dom0_driver_xs_info mouse;
++
++ if (!(str = xenstore_read(path)) || !*str)
++ return;
++
++ DEBUG("Received private command %s\n", path);
++ dom0_get_positions(positions);
++ natif_domid = dom0_driver_xs_read_dom0("natif");
++
++ dom0_driver_read_xs_info(&mouse, DOM0_MOUSE);
++ if (mouse.domid != natif_domid)
++ {
++ DEBUG("Natif should have the focus for that.\n");
++ return;
++ }
++
++ for (i = 0; i < NB_SLOTS; ++i)
++ {
++ if (!strcmp("take", str) && positions[i] == domid)
++ break;
++ if (!strcmp("release", str) && positions[i] == natif_domid)
++ break;
++ }
++ if (i == NB_SLOTS)
++ {
++ DEBUG("Try to %s on a bad slot\n", str);
++ free(str);
++ return;
++ }
++
++ sprintf(buff, "keyboard %d", i);
++ DEBUG("Write \"%s\" into xenstore\n", buff);
++ xenstore_write_dom0_driver("command", buff);
++ free(str);
++}
++
++static void dom0_driver_event_init(const char *str_arg)
++{
++ int positions[NB_SLOTS];
++ char str[20];
++ int pos = 0;
++ int i = 0;
++
++ pos = strtol(str_arg, NULL, 10);
++ dom0_get_positions(positions);
++ if (positions[pos])
++ {
++ DEBUG("There is already a vm at this slot\n");
++ exit(1);
++ }
++ else
++ {
++ snprintf(str, 9, "%d", pos);
++ xenstore_dom_write(domid, "dom0_input/pos", str);
++ }
++
++ if (vga_passthrough)
++ {
++ sprintf(str, "%d", domid);
++ xenstore_write_dom0_driver("natif", str);
++ xenstore_watch_dom0_driver("command", dom0_driver_command, NULL);
++ }
++ else
++ {
++ xenstore_dom_write(domid, "dom0_input/command", "");
++ sprintf(str, "w%d", domid);
++ xenstore_dom_chmod(domid, "dom0_input/command", str);
++ xenstore_dom_watch(domid, "dom0_input/command", dom0_driver_dom_command, NULL);
++ }
++
++ xenstore_watch_dom0_driver("mouse/state", dom0_driver_state_change, NULL);
++ xenstore_watch_dom0_driver("keyboard/state", dom0_driver_state_change, NULL);
++ xenstore_watch_dom0_driver("leave", dom0_driver_state_change, NULL);
++ xenstore_watch_dom0_driver("blank", dom0_driver_state_change, NULL);
++
++ /* Register the failover switch */
++ driver.xs_timer = qemu_new_timer(rt_clock,
++ (void (*)(void *))dom0_driver_failover_switch,
++ NULL);
++ qemu_mod_timer(driver.xs_timer, qemu_get_clock(rt_clock) + XS_REFRESH_INTERVAL);
++}
++
++static void dom0_driver_slots(int controller)
++{
++ struct dom0_driver_xs_info info;
++ int next_domid;
++ int positions[NB_SLOTS];
++
++ if (dom0_driver_failover_switch(NULL))
++ return;
++
++ dom0_driver_read_xs_info(&info, controller);
++
++ if (info.new_slot != -1)
++ {
++ dom0_get_positions(positions);
++ if (positions[info.new_slot] != 0)
++ {
++ if (info.state == 0 && info.domid == domid)
++ {
++ dom0_gr_devices(0, controller);
++ return;
++ }
++
++ if (info.state == 2 && positions[info.new_slot] == domid)
++ {
++ dom0_gr_devices(1, controller);
++ return;
++ }
++
++ }
++ }
++}
++
++static void dom0_driver_switch_controller(int slot, int controller)
++{
++ int positions[NB_SLOTS];
++ char *str;
++ int len;
++ int ready;
++ struct dom0_driver_xs_info info;
++
++ dom0_get_positions(positions);
++ if (positions[slot] == 0)
++ {
++ DEBUG("Cannot switch controller %d to %d slot empty\n", controller, slot);
++ return;
++ }
++
++ str = xenstore_dom_read(positions[slot], "dom0_input/ready", &len);
++ ready = strtol(str, NULL, 10);
++ free(str);
++ if (ready != 1)
++ {
++ DEBUG("Cannot switch controller %d to %d slot not ready\n", controller, slot);
++ return;
++ }
++
++ dom0_driver_read_xs_info(&info, controller);
++ if (info.state != 1)
++ {
++ DEBUG("Cannot switch controller %d to %d, unstable state\n", controller, slot);
++ return;
++ }
++
++ dom0_driver_xs_write("new-slot", slot, controller);
++ dom0_driver_xs_write("timestamp", time(NULL), controller);
++ dom0_driver_xs_write("state", 0, controller);
++}
++
++void dom0_driver_command(const char *path, void *opaque)
++{
++ char *val = NULL;
++
++ val = xenstore_read(path);
++ if (val == NULL)
++ return;
++
++ if (!strncmp(val, "switch ", 7))
++ {
++ int slot = strtol(val + 7, NULL, 10);
++
++ if (errno == EINVAL)
++ goto out;
++
++ DEBUG("switch the keyboard/mouse to slot %d\n", slot);
++ dom0_driver_switch_controller(slot, DOM0_KEYBOARD);
++ dom0_driver_switch_controller(slot, DOM0_MOUSE);
++ xenstore_write(path, "done");
++ }
++ else if (!strncmp(val, "keyboard ", 9))
++ {
++ int slot = strtol(val + 9, NULL, 10);
++
++ if (errno == EINVAL)
++ goto out;
++
++ DEBUG("switch the keyboard to slot %d\n", slot);
++ dom0_driver_switch_controller(slot, DOM0_KEYBOARD);
++ xenstore_write(path, "done");
++ }
++out:
++ free(val);
++}
++
++static void dom0_driver_leave_done(void)
++{
++ char *str;
++ int id;
++
++ if (!(str = xenstore_read_dom0_driver("leave")))
++ return;
++ id = strtol(str, NULL, 10);
++ free(str);
++ if (id == 1)
++ xenstore_write_dom0_driver("leave", "2");
++}
++
++static void dom0_driver_leave_changed(void)
++{
++ char *str;
++ int id;
++ struct dom0_driver_xs_info mouse;
++
++ if (!(str = xenstore_read_dom0_driver("leave")))
++ return;
++ id = strtol(str, NULL, 10);
++ free(str);
++ dom0_driver_read_xs_info(&mouse, DOM0_MOUSE);
++ if (id == 2 && mouse.domid == domid)
++ {
++ xenstore_write_dom0_driver("leave", "0");
++ driver.enter();
++ }
++}
++
++static void dom0_driver_state_change(const char *path, void *opaque)
++{
++
++ if (strstr(path, "/keyboard/state"))
++ dom0_driver_slots(DOM0_KEYBOARD);
++ if (strstr(path, "/mouse/state"))
++ dom0_driver_slots(DOM0_MOUSE);
++ if (strstr(path, "/leave"))
++ dom0_driver_leave_changed();
++ else if (strstr(path, "/blank"))
++ dom0_driver_blank_changed();
++ else
++ {
++ struct dom0_driver_xs_info mouse, keyboard;
++
++ dom0_driver_read_xs_info(&mouse, DOM0_MOUSE);
++ dom0_driver_read_xs_info(&keyboard, DOM0_KEYBOARD);
++
++ if (mouse.state == 1 && keyboard.state == 1)
++ if (mouse.pre != -1 && mouse.pre == domid)
++ {
++ xenstore_write_dom0_driver("leave", "1");
++ if (driver.leave())
++ dom0_driver_leave_done();
++ }
++ }
++}
++
++static void dom0_driver_switch(void *slot_arg)
++{
++ int slot = (int)slot_arg;
++ char buff[64];
++
++ DEBUG("%d pressed switch to slot %d\n", slot, slot);
++ sprintf(buff, "switch %d", slot);
++ xenstore_write_dom0_driver("command", buff);
++}
++
++static void dom0_driver_switch_bind(void)
++{
++ int i = 0;
++ int binds[4];
++
++ for (i = 0; i < 4; i++)
++ binds[i] = -1;
++
++ for (i = 0; i < 9; i++)
++ {
++ binds[0] = KEY_LEFTCTRL;
++ binds[1] = KEY_1 + i;
++ dom0_driver_handler->add_binding(binds, dom0_driver_switch, (void*)(i + 1));
++ }
++
++ binds[0] = KEY_LEFTCTRL;
++ binds[1] = KEY_LEFTALT;
++ binds[2] = KEY_BACKSPACE;
++ binds[3] = -1;
++ dom0_driver_handler->add_binding(binds, dom0_driver_detect_secure_auth, NULL);
++}
++
++static int dom0_driver_dummy_enter_leave(void)
++{
++ return 1;
++}
++
++void dom0_driver_init(const char *position)
++{
++ memset(&driver, 0, sizeof (driver));
++
++ dom0_driver_handler = &dom0_driver_hid_linux;
++ dom0_driver_handler->init();
++
++ if (vga_passthrough)
++ {
++ driver.enter = dom0_driver_unblank;
++ driver.leave = dom0_driver_blank;
++ }
++ else if (intel)
++ {
++ driver.enter = intel_enter;
++ driver.enter = intel_leave;
++ }
++ else
++ {
++ driver.enter = dom0_driver_dummy_enter_leave;
++ driver.leave = dom0_driver_dummy_enter_leave;
++ }
++
++ dom0_driver_switch_bind();
++ dom0_driver_event_init(position);
++ dom0_driver_failover_switch(NULL);
++
++ DEBUG("done\n");
++ xenstore_dom_write(domid, "dom0_input/ready", "1");
++}
+diff --git a/hid-linux.c b/hid-linux.c
+new file mode 100644
+index 0000000..4ec6bdd
+--- /dev/null
++++ b/hid-linux.c
+@@ -0,0 +1,513 @@
++/*
++ * QEMU hid-linux /dev/input driver
++ *
++ * Copyright (c) 2008 Citrix Systems
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (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.
++ */
++
++#include "qemu-common.h"
++#include "console.h"
++#include "qemu-timer.h"
++#include "qemu-xen.h"
++
++#include <sys/types.h>
++#include <linux/input.h>
++#include <linux/kd.h>
++#include <dirent.h>
++#include <stdio.h>
++#include <string.h>
++#include <fcntl.h>
++#include <limits.h>
++#include <unistd.h>
++#include <stdlib.h>
++#include <errno.h>
++#include <string.h>
++#include <assert.h>
++#include <time.h>
++#include <sys/time.h>
++
++#define HID_LINUX_XS_PATH "/local/domain/0/hid_linux"
++#define ABS(x) ((x) > 0 ? (x) : -(x))
++#define EVENT_PATH "/dev/input/event"
++#define HID_LINUX_MAX_DEV 16
++
++#define DEBUG_HID_LINUX
++
++#ifdef DEBUG_HID_LINUX
++# define DEBUG(_format_, args...) \
++ do \
++{ \
++ char *__str = get_time(); \
++ fprintf(stderr, "[%s] hid-linux(%d):%d: " _format_, (__str), domid, __LINE__, ## args);\
++ free(__str);\
++} \
++while (0);
++#else
++# define DEBUG(_format_, args...) (void)0
++#endif
++
++static struct hid_linux_driver
++{
++ int keyboard_fds[HID_LINUX_MAX_DEV / 2];
++ int mouse_fds[HID_LINUX_MAX_DEV / 2];
++ char *controller_paths[HID_LINUX_MAX_DEV];
++ int mouse_button_state;
++ int key_status[256];
++ void (*secure_key)(int ascii);
++} hid_linux_driver;
++
++struct hid_linux_binding
++{
++ int *binding;
++ void (*cb)(void *);
++ void *payload;
++};
++
++static struct hid_linux_binding *hid_linux_binding = NULL;
++
++static const int ascii2keycode_table[] =
++{
++ KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K,
++ KEY_L, KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U,
++ KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z
++};
++
++static char keycode2ascii(int keycode)
++{
++ int i = 0;
++
++ switch (keycode)
++ {
++ case KEY_ESC: return 27;
++ case KEY_BACKSPACE: return 8;
++ case KEY_ENTER: return 10;
++ case KEY_LEFT: return 17;
++ case KEY_RIGHT: return 18;
++ case KEY_DELETE: return 127;
++ case KEY_HOME: return 2;
++ case KEY_END: return 3;
++ case KEY_INSERT: return 19;
++ case KEY_SPACE: return 20;
++ default:
++ for (i = 0; i < sizeof (ascii2keycode_table) / sizeof (int); i++)
++ if (ascii2keycode_table[i] == keycode)
++ return i + 'a';
++ }
++ return 0;
++}
++
++static int ascii2keycode(char ascii)
++{
++ return ascii2keycode_table[ascii - 'a'];
++}
++
++static char *hid_linux_xs_read(const char *key)
++{
++ char *path = NULL;
++ char *ret;
++
++ if (asprintf(&path, HID_LINUX_XS_PATH"/%s", key) == -1)
++ return NULL;
++ ret = xenstore_read(path);
++ free(path);
++ return ret;
++}
++
++void hid_linux_add_binding(const int *tab, void (*cb)(void*), void *payload)
++{
++ int i = 0, j = 0;
++
++ for (i = 0; hid_linux_binding && hid_linux_binding[i].cb; i++)
++ ;
++ hid_linux_binding = realloc(hid_linux_binding,
++ (i + 2) * sizeof (struct hid_linux_binding));
++ hid_linux_binding[i + 1].cb = NULL;
++ hid_linux_binding[i].cb = cb;
++ hid_linux_binding[i].payload = payload;
++ hid_linux_binding[i].binding = NULL;
++
++ j = 0;
++ do
++ {
++ hid_linux_binding[i].binding = realloc(hid_linux_binding[i].binding,
++ (j + 1) * sizeof (int));
++ hid_linux_binding[i].binding[j] = tab[j];
++ }
++ while (tab[j++] != -1);
++}
++
++static int hid_linux_detect_binding(void)
++{
++ int i, j;
++
++ for (i = 0; hid_linux_binding && hid_linux_binding[i].cb; i++)
++ {
++ int *tab = hid_linux_binding[i].binding;
++
++ for (j = 0; tab[j] != -1; j++)
++ if (hid_linux_driver.key_status[tab[j]] == 0)
++ break;
++ if (tab[j] != -1)
++ continue;
++ else /* We match a binding */
++ {
++ DEBUG("binding payload %d\n", (int)(hid_linux_binding[i].payload));
++ hid_linux_binding[i].cb(hid_linux_binding[i].payload);
++ hid_linux_reset_keyboard();
++ return 1;
++ }
++ }
++ return 0;
++}
++
++static void hid_linux_key_inject(int code, uint32_t keycode)
++{
++ int first = 0;
++
++ switch (keycode)
++ {
++ case KEY_F11: keycode = 0X57; break; /* F11 */
++ case KEY_F12: keycode = 0X58; break; /* F12 */
++ case KEY_INSERT: keycode = 0X52; break;
++ case KEY_HOME: keycode = 0X47; break;
++ case KEY_PAGEUP: keycode = 0X49; break;
++ case KEY_DELETE: keycode = 0X53; break;
++ case KEY_END: keycode = 0X4F; break;
++ case KEY_PAGEDOWN: keycode = 0x51; break;
++ case KEY_UP: keycode = 0X48; break;
++ case KEY_LEFT: keycode = 0X4B; break;
++ case KEY_DOWN: keycode = 0X50; break;
++ case KEY_RIGHT: keycode = 0X4D; break;
++ case KEY_RIGHTALT: keycode = 0x38; first = 0xe0; break;
++ case KEY_LEFTMETA: keycode = 0x5B; first = 0xe0; break;
++ case KEY_RIGHTMETA: keycode = 0x5C; first = 0xe0; break;
++ }
++
++ if (first)
++ kbd_put_keycode(first);
++
++ if (code == 0)
++ kbd_put_keycode(keycode | 0x80);
++ else
++ kbd_put_keycode(keycode & 0x7f);
++}
++
++
++
++static void hid_linux_key_event(int code, uint32_t keycode)
++{
++ if (code == 1)
++ if (hid_linux_detect_binding())
++ return;
++ hid_linux_key_inject(code, keycode);
++}
++
++static void hid_linux_read(void *opaque)
++{
++ struct input_event event[5];
++ int i = 0;
++ int read_sz = 0;
++ int fd = *(int *)opaque;
++
++ read_sz = read(fd, event, sizeof (event));
++ for (i = 0; i < read_sz / (sizeof (struct input_event)); i++)
++ {
++ if (event[i].type == EV_KEY)
++ {
++ if (event[i].code >= BTN_MOUSE)
++ {
++ /* Mouse Key */
++ int type = 0;
++
++ switch(event[i].code)
++ {
++ case BTN_LEFT: type = MOUSE_EVENT_LBUTTON; break;
++ case BTN_RIGHT: type = MOUSE_EVENT_RBUTTON; break;
++ case BTN_MIDDLE: type = MOUSE_EVENT_MBUTTON; break;
++ }
++
++ if (event[i].value)
++ hid_linux_driver.mouse_button_state |= type;
++ else
++ hid_linux_driver.mouse_button_state &= ~type;
++ kbd_mouse_event(0, 0, 0, hid_linux_driver.mouse_button_state);
++ }
++ else
++ {
++ hid_linux_driver.key_status[event[i].code] = event[i].value;
++ hid_linux_key_event(event[i].value, event[i].code);
++ }
++ }
++
++ if (event[i].type == EV_REL || event[i].type == EV_ABS)
++ {
++ /* Mouse motion */
++ int x = 0, y = 0, z = 0;
++
++ if (event[i].type == EV_REL)
++ switch (event[i].code)
++ {
++ case REL_X : x = event[i].value; break;
++ case REL_Y : y = event[i].value; break;
++ case REL_WHEEL : z = -event[i].value; break;
++ }
++ if (event[i].type == EV_ABS)
++ {
++ static int last_x = 1, last_y = 1;
++ int px = 0, py = 0, l = 50;
++ double div = 1;
++ char *str = NULL;
++
++ str = hid_linux_xs_read("touchpad-limit");
++ if (str)
++ l = strtol(str, NULL, 10);
++ str = hid_linux_xs_read("touchpad-div");
++ if (str)
++ div = strtol(str, NULL, 10) / 1000.;
++
++ switch (event[i].code)
++ {
++ case ABS_X : x = event[i].value; break;
++ case ABS_Y : y = event[i].value; break;
++ }
++
++ if (x)
++ {
++ px = x - last_x;
++ last_x = x;
++ }
++ if (y)
++ {
++ py = y - last_y;
++ last_y = y;
++ }
++
++ x = (ABS(px) < l ? px : 0) / div;
++ y = (ABS(py) < l ? py : 0) / div;
++ }
++
++ kbd_mouse_event(x, y, z, hid_linux_driver.mouse_button_state);
++ }
++ }
++}
++
++void hid_linux_reset_keyboard(void)
++{
++ int i = 0;
++
++ for (i = 0; i < 256; i++)
++ if (hid_linux_driver.key_status[i])
++ {
++ hid_linux_key_inject(0, i);
++ hid_linux_driver.key_status[i] = 0;
++ }
++}
++
++
++
++static void hid_linux_redirect_fds(int *fd, IOHandler *cb)
++{
++ assert(fd != NULL);
++
++ while (*fd != -1)
++ {
++ qemu_set_fd_handler(*fd, cb, NULL, fd);
++ fd++;
++ }
++}
++
++static void hid_linux_secure_read(void *opaque)
++{
++ struct input_event event[5];
++ int i = 0;
++ int read_sz = 0;
++ int fd = *(int *)opaque;
++
++ assert(hid_linux_driver.secure_key);
++
++ read_sz = read(fd, event, sizeof (event));
++ for (i = 0; i < read_sz / (sizeof (struct input_event)); i++)
++ if (event[i].type == EV_KEY && event[i].code < BTN_MOUSE &&
++ event[i].value > 0)
++ hid_linux_driver.secure_key(keycode2ascii(event[i].code));
++}
++
++
++void hid_linux_secure_keyboard(void (*cb)(int ascii))
++{
++ hid_linux_driver.secure_key = cb;
++ if (cb)
++ hid_linux_redirect_fds(hid_linux_driver.keyboard_fds,
++ hid_linux_secure_read);
++ else
++ hid_linux_redirect_fds(hid_linux_driver.keyboard_fds,
++ hid_linux_read);
++}
++
++static int hid_linux_grab_devices(int grab, int *fd)
++{
++ int rc = 0;
++ int try = 10;
++
++ assert(fd != NULL && *fd != -1);
++ for (; *fd != -1; fd++)
++ {
++ while (try--)
++ {
++ if ((rc = ioctl(*fd, EVIOCGRAB, grab)) == -1)
++ {
++ char *er;
++
++ if (errno == EBUSY)
++ continue;
++ er = strerror(errno);
++ DEBUG("ioctl(%d, EVOCGRAB) failed, %s\n", *fd, er);
++ return 0;
++ }
++ else
++ break;
++ }
++ assert(try);
++
++ DEBUG("ioctl(%d, EVOCGRAB) succed\n", *fd);
++
++ if (grab)
++ qemu_set_fd_handler(*fd, hid_linux_read, NULL, fd);
++ else
++ qemu_set_fd_handler(*fd, NULL, NULL, fd);
++ }
++ return 1;
++}
++
++int hid_linux_grab_keyboard(int grab)
++{
++ return hid_linux_grab_devices(grab, hid_linux_driver.keyboard_fds);
++}
++
++int hid_linux_grab_mouse(int grab)
++{
++ return hid_linux_grab_devices(grab, hid_linux_driver.mouse_fds);
++}
++
++static int hid_linux_open_timeout(const char *path, int flags)
++{
++ int try = 10;
++ int fd = 0;
++
++ while (try-- && ((fd = open(path, flags)) == -1))
++ usleep(100000); /* 10 ms */
++ if (try == 0)
++ return 0;
++ return fd == -1 ? 0 : fd;
++}
++
++static int hid_linux_ioctl_timeout(int fd, int arg1, void *arg2)
++{
++ int try = 10;
++
++ while (try-- && ioctl(fd, arg1, arg2) == -1)
++ usleep(100000); /* 10 ms */
++ if (try == 0)
++ return 0;
++ return 1;
++}
++
++void hid_linux_probe(int grab)
++{
++ int i = 0, j = 0, c = 0;
++ int fd = -1;
++ int keyboard = 0, mouse = 0;
++ char path[strlen(EVENT_PATH) + 3];
++ char name[128];
++ int *controllers;
++ struct stat st;
++
++ while (1)
++ {
++ sprintf(path, "%s%i", EVENT_PATH, i++);
++
++ if (stat(path, &st) == -1)
++ break;
++
++ for ( c = 0; c < HID_LINUX_MAX_DEV && hid_linux_driver.controller_paths[c]; c++)
++ if (!strcmp(hid_linux_driver.controller_paths[c], path))
++ break;
++ assert(c != HID_LINUX_MAX_DEV);
++ if (hid_linux_driver.controller_paths[c])
++ continue;
++
++ if ((fd = open(path, O_RDONLY)) == -1)
++ break;
++
++ if (ioctl(fd, EVIOCGNAME(128), name) == -1)
++ {
++ DEBUG("Input get name failed on %s\n", path);
++ break;
++ }
++
++ if (strcasestr(name, "keyboard"))
++ {
++ DEBUG("Add %s %s as a keyboard, fd=%d\n", path, name, fd);
++ controllers = hid_linux_driver.keyboard_fds;
++ }
++ else
++ {
++ DEBUG("Add %s %s as a mouse, fd=%d\n", path, name, fd);
++ controllers = hid_linux_driver.mouse_fds;
++ }
++
++ for ( j = 0; j < (HID_LINUX_MAX_DEV / 2) && controllers[j] != -1; j++)
++ ;
++ assert(j != (HID_LINUX_MAX_DEV / 2));
++
++ controllers[j] = fd;
++ controllers[j + 1] = -1;
++
++ if (grab)
++ {
++ if (!hid_linux_grab_devices(1, controllers + j))
++ {
++ DEBUG("Grabing failed, try next time...\n");
++ controllers[j] = -1;
++ break;
++ }
++ }
++
++ hid_linux_driver.controller_paths[c] = strdup(path);
++ hid_linux_driver.controller_paths[c + 1] = NULL;
++
++ fd = -1;
++ }
++ if (fd != -1)
++ close(fd);
++}
++
++void hid_linux_init(void)
++{
++ hid_linux_driver.keyboard_fds[0] = -1;
++ hid_linux_driver.mouse_fds[0] = -1;
++ hid_linux_driver.controller_paths[0] = NULL;
++
++ while (hid_linux_driver.keyboard_fds[0] == -1)
++ {
++ hid_linux_probe(0);
++ usleep(100000); /* 10 ms */
++ }
++}
diff --git a/qemu-xen.h b/qemu-xen.h
index 0cc5dd8..2646ec7 100644
--- a/qemu-xen.h
ifdef CONFIG_STUBDOM
CPPFLAGS += $(TARGET_CPPFLAGS) -DNEED_CPU_H \
diff --git a/xenstore.c b/xenstore.c
-index ccd167f..244f906 100644
+index 01afcf0..20ca8cf 100644
--- a/xenstore.c
+++ b/xenstore.c
-@@ -1728,3 +1728,63 @@ void xenstore_dm_finished_startup(void)
+@@ -1727,3 +1727,63 @@ void xenstore_dm_finished_startup(void)
free(buf);
free(path);
}
/* Allocate video memory in the GPFN space */
void xen_vga_populate_vram(uint64_t vram_addr, uint32_t vga_ram_size)
{
+diff --git a/intel.c b/intel.c
+new file mode 100644
+index 0000000..4c5f773
+--- /dev/null
++++ b/intel.c
+@@ -0,0 +1,494 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <sys/mman.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <assert.h>
++#include <signal.h>
++#include <pci/pci.h>
++
++#include "qemu-common.h"
++#include "console.h"
++#include "sysemu.h"
++
++#define INTEL_DEBUG(format, args...) \
++ fprintf (stderr, "intel.c:%d:%s " format , __LINE__, __func__, ## args)
++
++#define TileW 128
++#define TileH 8
++
++#define REG_DR_DSPASURF 0x7019C
++#define REG_DR_DSPACNTR 0x70180
++#define REG_DR_DSPASTRIDE 0x70188
++#define REG_DR_PIPEACONF 0x70008
++
++#define REG_DR_DSPBSURF 0x7119C
++#define REG_DR_DSPBCNTR 0x71180
++#define REG_DR_DSPBSTRIDE 0x71188
++#define REG_DR_PIPEBCONF 0x71008
++
++#define REG_DE_PIPEASRC 0x6001c
++
++extern int vga_passthrough;
++uint32_t guest_framebuffer;
++
++static int display = 0;
++
++static int mmio_fd = -1;
++static int mem_fd = -1;
++static uint8_t *intel_mem = NULL;
++static uint8_t *intel_mmio = NULL;
++static int intel_force_full_update = 0;
++static int intel_have_focus;
++static int IntelPitch = 16;
++static int IntelX = 1280;
++static int IntelY = 1024;
++static DisplayState *lds = NULL;
++static uint8_t *old_data = NULL;
++static uint32_t intel_fb_base, intel_mmio_base;
++static uint32_t map_s, map_d, map_size;
++static int refresh;
++
++static void set_data_mappings(void);
++static void unset_data_mappings(int mapping);
++static void set_data_pointer(void);
++static void intel_resize(DisplayState *ds);
++
++static inline unsigned int intel_get_reg(unsigned int reg)
++{
++ return *(unsigned int*)(intel_mmio + reg);
++}
++
++static inline int is_linear(void)
++{
++ unsigned int *dspacntr = (unsigned int *)(intel_mmio + REG_DR_DSPACNTR);
++ if (((*dspacntr) & (1 << 10)) == 0)
++ return 1;
++ else
++ return 0;
++}
++
++static inline unsigned int intel_get_pitch(void)
++{
++ unsigned int *dspastride = (unsigned int *)(intel_mmio + REG_DR_DSPASTRIDE);
++ return *dspastride;
++}
++
++static inline unsigned int intel_get_offset(DisplaySurface *ds, int x, int y)
++{
++ return (y * ds->width + x) * 4;
++}
++
++static void intel_update_linear(DisplaySurface *ds, int x, int y, int w, int h)
++{
++ int i, bpp = ds->pf.depth / 8;
++ unsigned char *s, *d;
++ s = ds->data;
++ d = (unsigned char *)(intel_mem + intel_get_reg(REG_DR_DSPASURF));
++ s += (ds->linesize * y) + bpp * x;
++ d += (ds->linesize * y) + bpp * x;
++ for (i = 0; i < h; i++) {
++ memcpy(d, s, w * bpp);
++ s += ds->linesize;
++ d += ds->linesize;
++ }
++}
++
++static void intel_force_linear(int linesize)
++{
++ unsigned int *dspacntr = (unsigned int *)(intel_mmio + REG_DR_DSPACNTR);
++ unsigned int *pipeaconf = (unsigned int *)(intel_mmio + REG_DR_PIPEACONF);
++ unsigned int *dspasurf = (unsigned int *)(intel_mmio + REG_DR_DSPASURF);
++ unsigned int *dspastride = (unsigned int *)(intel_mmio + REG_DR_DSPASTRIDE);
++
++ unsigned int *dspbcntr = (unsigned int *)(intel_mmio + REG_DR_DSPBCNTR);
++ unsigned int *pipebconf = (unsigned int *)(intel_mmio + REG_DR_PIPEBCONF);
++ unsigned int *dspbsurf = (unsigned int *)(intel_mmio + REG_DR_DSPBSURF);
++ unsigned int *dspbstride = (unsigned int *)(intel_mmio + REG_DR_DSPBSTRIDE);
++
++ unsigned int surfa = 0, surfb = 0, pipea = 0, pipeb = 0;
++ char pipebenabled = !!(*pipebconf & (1 << 30));
++
++
++ INTEL_DEBUG("DSPASURF CTRL: 0x%x\n", intel_get_reg(REG_DR_DSPACNTR));
++
++ /* Disable surface */
++ pipea = *pipeaconf & (0x3 << 18);
++ *pipeaconf &= ~(0x3 << 18);
++ *dspacntr |= (1 << 31);
++ /* Address of the surface to map to */
++ surfa = *dspasurf;
++ *dspasurf = 0x00000000;
++ *dspacntr &= ~(1 << 31);
++ *dspasurf = 0x00000000;
++ *pipeaconf |= pipea;
++
++ if (pipebenabled) {
++ INTEL_DEBUG("PIPEBCONF enabled.\n");
++
++ /* Disable surface */
++ pipeb = *pipebconf & (0x3 << 18);
++ *pipebconf &= ~(0x3 << 18);
++ *dspbcntr |= (1 << 31);
++ /* Address of the surface to map to */
++ surfb = *dspbsurf;
++ *dspbsurf = 0x00000000;
++ *dspbcntr &= ~(1 << 31);
++ *dspbsurf = 0x00000000;
++ *pipebconf |= pipeb;
++ }
++
++ usleep(20000);
++
++ *pipeaconf &= ~(0x3 << 18);
++ /* Enable surface linear mode */
++ *dspacntr &= ~(1 << 10);
++ if (linesize) *dspastride = linesize;
++ *dspasurf = surfa;
++ *dspacntr |= (1 << 31);
++ *pipeaconf |= pipea;
++
++ if (pipebenabled) {
++ *pipebconf &= ~(0x3 << 18);
++ /* Enable surface linear mode */
++ *dspbcntr &= ~(1 << 10);
++ if (linesize) *dspbstride = linesize;
++ *dspbsurf = surfb;
++ *dspbcntr |= (1 << 31);
++ *pipebconf |= pipeb;
++ }
++
++ usleep(20000);
++}
++
++static void intel_update(DisplayState *ds, int x, int y, int w, int h)
++{
++ if (intel_have_focus && !old_data && !map_size)
++ intel_update_linear(ds->surface, x, y, w, h);
++}
++
++static void set_fb_mapping(void)
++{
++ DisplaySurface *surf = lds->surface;
++ int rc;
++ unsigned long nr_pfn;
++
++ unset_vga_acc();
++ fprintf(stderr, "set_fb_mapping: %x %x\n", (intel_fb_base + intel_get_reg(REG_DR_DSPASURF)), guest_framebuffer);
++ nr_pfn = (surf->linesize * surf->height) >> TARGET_PAGE_BITS;
++
++ rc = xc_domain_memory_mapping(xc_handle,
++ domid,
++ (guest_framebuffer >> TARGET_PAGE_BITS),
++ ((intel_fb_base + intel_get_reg(REG_DR_DSPASURF)) >> TARGET_PAGE_BITS),
++ nr_pfn,
++ DPCI_ADD_MAPPING);
++ if (rc) {
++ fprintf(stderr, "xc_domain_memory_mapping failed %d\n", rc);
++ return;
++ }
++ map_s = ((intel_fb_base + intel_get_reg(REG_DR_DSPASURF)) >> TARGET_PAGE_BITS);
++ map_d = (guest_framebuffer >> TARGET_PAGE_BITS);
++ map_size = nr_pfn;
++}
++
++static void unset_fb_mapping(void)
++{
++ int rc;
++
++ fprintf(stderr, "unset_fb_mapping: %x %x\n", map_d, map_s);
++
++ rc = xc_domain_memory_mapping(xc_handle,
++ domid,
++ map_d,
++ map_s,
++ map_size,
++ DPCI_REMOVE_MAPPING);
++ if (rc) {
++ fprintf(stderr, "xc_domain_memory_mapping failed %d\n", rc);
++ return;
++ }
++
++ set_vga_acc();
++ map_s = 0;
++ map_d = 0;
++ map_size = 0;
++}
++
++static void intel_setdata(DisplayState *ds)
++{
++ if (map_size)
++ unset_fb_mapping();
++ set_fb_mapping();
++}
++
++static void intel_resize_shared(DisplayState *ds, int w, int h, int depth, int linesize, void *pixels)
++{
++ DisplaySurface *surf = ds->surface;
++
++ if (!intel_have_focus) {
++ surf->width = w;
++ surf->height = h;
++ intel_resize(ds);
++ return;
++ }
++ if (depth == 32 && w == IntelX && h == IntelY)
++ surf->flags = QEMU_ALLOCATED_FLAG;
++ else
++ surf->flags &= ~QEMU_ALLOCATED_FLAG;
++ if (surf->flags & QEMU_ALLOCATED_FLAG) {
++ surf->width = w;
++ surf->height = h;
++ surf->pf.depth = 32;
++ surf->linesize = linesize;
++ /* adjust linesize */
++ intel_force_linear(linesize);
++ set_data_mappings();
++ if (refresh) {
++ memcpy(surf->data, pixels, surf->linesize * surf->height);
++ refresh = 0;
++ }
++ surf->data = pixels;
++ intel_setdata(ds);
++ } else {
++ surf->width = w;
++ surf->height = h;
++ intel_resize(ds);
++ }
++}
++
++static void intel_resize(DisplayState *ds)
++{
++ DisplaySurface *surf = ds->surface;
++ int old_linesize = surf->linesize;
++
++ if (surf->pf.depth == 32 && surf->width == IntelX && surf->height == IntelY)
++ surf->flags = QEMU_ALLOCATED_FLAG;
++ else
++ surf->flags &= ~QEMU_ALLOCATED_FLAG;
++
++ if (is_buffer_shared(surf))
++ {
++ INTEL_DEBUG("intel_resize_shared: enable shared buffer, linesize %d\n",
++ surf->linesize);
++ intel_force_linear(surf->linesize);
++ set_data_mappings();
++ if (refresh)
++ {
++ // Pixels doesn't exist anymore ??
++ //memcpy(surf->data, pixels, surf->linesize * surf->height);
++ refresh = 0;
++ }
++ intel_setdata(ds);
++ return;
++ }
++
++ INTEL_DEBUG("intel_resize: no shared buffer, linesize=%d\n", surf->linesize);
++ surf->linesize = intel_get_pitch();
++ if (map_size) {
++ unset_fb_mapping();
++ unset_data_mappings(1);
++ }
++ if (intel_have_focus && !is_linear()) {
++ intel_force_linear(0);
++ }
++ surf->flags &= ~QEMU_ALLOCATED_FLAG;
++ if (intel_have_focus && !old_data &&
++ surf->width * surf->height <= IntelX * IntelY)
++ set_data_mappings();
++ else if (intel_have_focus && old_data &&
++ surf->width * surf->height > IntelX * IntelY)
++ unset_data_mappings(0);
++ if (!old_data) {
++ qemu_free(surf->data);
++ surf->data = qemu_mallocz(surf->height * surf->linesize);
++ } else {
++ INTEL_DEBUG("intel_resize: set_data_pointer\n");
++ set_data_pointer();
++ }
++ if (intel_have_focus)
++ memset((unsigned char *)(intel_mem + intel_get_reg(REG_DR_DSPASURF)), 0x0, IntelX * IntelY);
++ if (refresh) {
++ if (old_data) {
++ unsigned char *s, *d;
++ int i;
++ s = old_data;
++ d = surf->data;
++ for (i = 0; i < surf->height; i++) {
++ memcpy(d, s, surf->width * 4);
++ s += old_linesize;
++ d += surf->linesize;
++ }
++ }
++ refresh = 0;
++ }
++}
++
++static void intel_refresh(DisplayState *ds)
++{
++ vga_hw_update();
++}
++
++static void intel_init_mapping(void)
++{
++ struct pci_access *pci_bus;
++ struct pci_dev *pci_dev;
++
++ mmio_fd = open("/dev/mem", O_RDWR);
++ if (mmio_fd == -1)
++ {
++ perror("open");
++ exit(1);
++ }
++ mem_fd = open("/dev/mem", O_RDWR);
++ if (mem_fd == -1)
++ {
++ perror("open");
++ exit(1);
++ }
++
++ pci_bus = pci_alloc();
++ pci_init(pci_bus);
++ pci_dev = pci_get_dev(pci_bus, 0, 0, 2, 0);
++ pci_fill_info(pci_dev, PCI_FILL_BASES);
++ intel_fb_base = pci_dev->base_addr[2] & 0xfffff000;
++ intel_mmio_base = pci_dev->base_addr[0] & 0xfffff000;
++ pci_free_dev(pci_dev);
++ pci_cleanup(pci_bus);
++
++ INTEL_DEBUG("Map intel main mem 0x%x\n", intel_fb_base);
++ intel_mem = mmap(NULL, 0x10000000, PROT_READ | PROT_WRITE, MAP_SHARED,
++ mem_fd, intel_fb_base);
++ if (intel_mem == MAP_FAILED)
++ {
++ perror("mmap");
++ exit(1);
++ }
++
++ INTEL_DEBUG("Map intel mmio 0x%x\n", intel_mmio_base);
++ intel_mmio = mmap(NULL, 4 * 1024 * 1024, PROT_READ | PROT_WRITE, MAP_SHARED,
++ mmio_fd, intel_mmio_base);
++ if (intel_mem == MAP_FAILED)
++ {
++ perror("mmap");
++ exit(1);
++ }
++}
++
++static void set_data_pointer(void)
++{
++ DisplaySurface *surf = lds->surface;
++
++ surf->data = (unsigned char *)(intel_mem + intel_get_reg(REG_DR_DSPASURF));
++ surf->data = surf->data +
++ surf->linesize * ((IntelY - surf->height) / 2) +
++ 4 * ((IntelX - surf->width) / 2);
++}
++
++static void set_data_mappings(void)
++{
++ INTEL_DEBUG("set_data_mappings\n");
++ if (!old_data)
++ old_data = lds->surface->data;
++ set_data_pointer();
++}
++
++static void unset_data_mappings(int mapping)
++{
++ DisplaySurface *surf = lds->surface;
++ if (!old_data)
++ return;
++ if (mapping) {
++ uint8_t * buffer_pointer = surf->data;
++ surf->data = old_data;
++ old_data = NULL;
++ surf->data = realloc(surf->data, surf->linesize * surf->height);
++ memcpy(surf->data,
++ (unsigned char *)(intel_mem + intel_get_reg(REG_DR_DSPASURF)),
++ surf->linesize * surf->height);
++ memcpy(buffer_pointer,
++ surf->data,
++ surf->linesize * surf->height);
++ } else {
++ uint8_t * buffer_pointer = surf->data;
++ surf->data = old_data;
++ old_data = NULL;
++ surf->data = realloc(surf->data, surf->linesize * surf->height);
++ memcpy(surf->data,
++ buffer_pointer,
++ surf->linesize * surf->height);
++ }
++ INTEL_DEBUG("unset_data_mappings %d: success\n", mapping);
++}
++
++static int intel_getfocus(void)
++{
++ return intel_have_focus;
++}
++
++static void intel_focus(int focus)
++{
++ if (intel_have_focus == focus)
++ return;
++
++ INTEL_DEBUG("intel_focus %d\n", focus);
++ intel_have_focus = focus;
++ if (focus) {
++ if (!is_linear()) {
++ IntelPitch = intel_get_reg(REG_DR_DSPASTRIDE);
++ IntelX = ((intel_get_reg(REG_DE_PIPEASRC) >> 16) & 0xfff) + 1;
++ IntelY = (intel_get_reg(REG_DE_PIPEASRC) & 0xfff) + 1;
++ INTEL_DEBUG("Resolution is %dx%d\n", IntelX, IntelY);
++ }
++ refresh = 1;
++ lds->listeners->dpy_resize = intel_resize;
++ lds->listeners->dpy_setdata = intel_setdata;
++ vga_hw_invalidate();
++ } else {
++ if (map_size) {
++ unset_fb_mapping();
++ unset_data_mappings(1);
++ } else if (old_data) {
++ unset_data_mappings(0);
++ }
++ lds->listeners->dpy_resize = NULL;
++ lds->listeners->dpy_setdata = NULL;
++ lds->surface->flags &= ~QEMU_ALLOCATED_FLAG;
++ }
++}
++
++int intel_enter(void)
++{
++ intel_focus(1);
++ return 1;
++}
++
++int intel_leave(void)
++{
++ intel_focus(0);
++ return 1;
++}
++
++void intel_display_init(DisplayState *ds)
++{
++ DisplaySurface *surf = ds->surface;
++
++ INTEL_DEBUG("\n");
++
++ intel_init_mapping();
++
++ INTEL_DEBUG("Frambuffer is at 0x%x\n", intel_get_reg(REG_DR_DSPASURF));
++
++ surf->flags = 0;
++ surf->width = 640;
++ surf->height = 480;
++ surf->pf.depth = 32;
++ intel_resize(ds);
++ lds = ds;
++
++ ds->listeners->dpy_update = intel_update;
++ ds->listeners->dpy_resize = intel_resize;
++ ds->listeners->dpy_refresh = intel_refresh;
++}
diff --git a/vl.c b/vl.c
index 0ffe1ec..d6379a9 100644
--- a/vl.c
direct_pci = optarg;
break;
diff --git a/xen-hooks.mak b/xen-hooks.mak
-index bed869a..d52e99d 100644
+index f243df1..55dd477 100644
--- a/xen-hooks.mak
+++ b/xen-hooks.mak
-@@ -37,6 +37,7 @@ OBJS += helper2.o
- OBJS += battery_mgmt.o
+@@ -39,6 +39,7 @@ OBJS += xen_acpi_wmi.o
+ OBJS += thermal_mgmt.o
OBJS += dom0_driver.o
OBJS += hid-linux.o
+OBJS += intel.o
+diff --git a/hw/acpi-wmi.h b/hw/acpi-wmi.h
+new file mode 100644
+index 0000000..af99c1c
+--- /dev/null
++++ b/hw/acpi-wmi.h
+@@ -0,0 +1,99 @@
++/******************************************************************************
++ * 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.
++ */
++
++/* NOTE: This header is a duplicate of drivers/xen/acpi-wmi/acpi-wmi.h in our
++ * kernel repo. As we don't share headers between kernel and userspace, we have
++ * the same header in two places. It is important to keep the two headers in sync
++ * to avoid incompatibilities.
++ */
++
++#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 */
++
diff --git a/hw/pc.h b/hw/pc.h
index a261c8a..2e3cade 100644
--- a/hw/pc.h
extern int no_hpet;
diff --git a/hw/piix4acpi.c b/hw/piix4acpi.c
-index c218782..3803824 100644
+index c218782..cf214a4 100644
--- a/hw/piix4acpi.c
+++ b/hw/piix4acpi.c
@@ -29,6 +29,7 @@
}
static inline int test_bit(uint8_t *map, int bit)
-@@ -261,6 +264,19 @@ void acpi_lid_state_changed(void)
+@@ -261,6 +262,19 @@ void acpi_lid_state_changed(void)
}
}
#ifdef CONFIG_PASSTHROUGH
static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
+diff --git a/hw/xen_acpi_wmi.c b/hw/xen_acpi_wmi.c
+new file mode 100644
+index 0000000..e759e89
+--- /dev/null
++++ b/hw/xen_acpi_wmi.c
+@@ -0,0 +1,654 @@
++/*
++ * 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"
++#include <sys/ioctl.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;
++
++/* #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(void)
++{
++ 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_features", 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 */
++
+diff --git a/hw/xen_acpi_wmi.h b/hw/xen_acpi_wmi.h
+new file mode 100644
+index 0000000..df289f2
+--- /dev/null
++++ b/hw/xen_acpi_wmi.h
+@@ -0,0 +1,89 @@
++/*
++ * xen_acpi_wmi.h
++ *
++ * 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
++ */
++
++#ifndef _XEN_ACPI_WMI_H
++#define _XEN_ACPI_WMI_H
++
++#ifdef CONFIG_STUBDOM
++#define CONFIG_NO_XEN_ACPI_WMI
++#endif
++
++#include "acpi-wmi.h"
++
++#define XEN_ACPI_WMI_CMD_PORT 0x96
++#define XEN_ACPI_WMI_DATA_PORTB 0x98
++#define XEN_ACPI_WMI_DATA_PORTL 0x9A
++
++/* Values written to WMI command port */
++enum XEN_ACPI_WMI_COMMAND { XEN_ACPI_WMI_CMD_INIT = 100,
++ XEN_ACPI_WMI_CMD_GUID,
++ XEN_ACPI_WMI_CMD_OBJ_INSTANCE,
++ XEN_ACPI_WMI_CMD_METHOD_ID,
++ XEN_ACPI_WMI_CMD_IN_BUFFER,
++ XEN_ACPI_WMI_CMD_IN_BUFFER_SIZE,
++ XEN_ACPI_WMI_CMD_EXECUTE,
++ XEN_ACPI_WMI_CMD_OUT_BUFFER,
++ XEN_ACPI_WMI_CMD_OUT_BUFFER_SIZE,
++ XEN_ACPI_WMI_CMD_EVENT_ID,
++ XEN_ACPI_WMI_CMD_UNDEFINED };
++
++enum XEN_ACPI_WMI_OBJ_INVOCATION_TYPE { XEN_ACPI_WMI_EXEC_METHOD = 1,
++ XEN_ACPI_WMI_QUERY_OBJECT,
++ XEN_ACPI_WMI_SET_OBJECT,
++ XEN_ACPI_WMI_GET_EVENT_DATA,
++ XEN_ACPI_WMI_UNDEFINED };
++
++typedef struct xen_acpi_wmi_cmd_info {
++ enum XEN_ACPI_WMI_COMMAND cmd_type;
++ enum XEN_ACPI_WMI_OBJ_INVOCATION_TYPE invocation_type;
++ xen_wmi_obj_invocation_data_t invocation_data;
++ uint32_t current_index;
++} xen_acpi_wmi_cmd_info_t;
++
++void xen_acpi_wmi_init(PCIDevice *device);
++void xen_acpi_wmi_cleanup(void);
++
++#ifndef CONFIG_NO_XEN_ACPI_WMI
++
++void xen_acpi_wmi_set_guid(uint8_t val);
++void xen_acpi_wmi_set_cmd_instance(uint32_t val);
++void xen_acpi_wmi_set_method_id(uint32_t val);
++xen_wmi_buffer_t *xen_acpi_wmi_get_input_buffer(void);
++void xen_acpi_wmi_set_in_buffer_size(uint32_t val);
++void xen_acpi_wmi_set_in_buffer(uint8_t val);
++xen_wmi_buffer_t *xen_acpi_wmi_get_output_buffer(void);
++void xen_acpi_wmi_allocate_output_buffer(size_t length);
++int xen_acpi_wmi_reallocate_output_buffer(void);
++void xen_acpi_wmi_free_input_buffer(void);
++void xen_acpi_wmi_execute(void);
++void xen_acpi_wmi_set_event_id(uint8_t event_id);
++static uint32_t xen_acpi_wmi_cmd_port_read(void *opaque, uint32_t addr);
++static void xen_acpi_wmi_cmd_port_write(void *opaque, uint32_t addr, uint32_t val);
++static uint32_t xen_acpi_wmi_data_port_readb(void *opaque, uint32_t addr);
++static void xen_acpi_wmi_data_port_writeb(void *opaque, uint32_t addr, uint32_t val);
++static uint32_t xen_acpi_wmi_data_port_readl(void *opaque, uint32_t addr);
++static void xen_acpi_wmi_data_port_writel(void *opaque, uint32_t addr, uint32_t val);
++
++#endif
++
++#endif /* _XEN_ACPI_WMI_H */
++
++
diff --git a/qemu-xen.h b/qemu-xen.h
index 8c1debd..60ee108 100644
--- a/qemu-xen.h
ifdef CONFIG_STUBDOM
CPPFLAGS += $(TARGET_CPPFLAGS) -DNEED_CPU_H \
diff --git a/xenstore.c b/xenstore.c
-index 2ae1763..ebacace 100644
+index 6f5b073..7cd4d54 100644
--- a/xenstore.c
+++ b/xenstore.c
@@ -1011,6 +1011,11 @@ void xenstore_process_event(void *opaque)
if (strncmp(vec[XS_WATCH_TOKEN], "hd", 2) ||
strlen(vec[XS_WATCH_TOKEN]) != 3)
goto out;
-@@ -1552,6 +1557,11 @@ void xenstore_register_for_pm_events(void)
+@@ -1467,6 +1472,11 @@ void xenstore_register_for_pm_events(void)
xs_watch(xsh, "/pm/events/sleepbuttonpressed", "slpbuttonpressedevt");
}
intel
use-vga-cmdline
disable-aio
-#sleep-btn-support
+++ /dev/null
-diff --git a/hw/piix4acpi.c b/hw/piix4acpi.c
-index c6e4c4e..dd7d241 100644
---- a/hw/piix4acpi.c
-+++ b/hw/piix4acpi.c
-@@ -254,6 +254,18 @@ void acpi_sleep_button_pressed(void)
- }
- }
-
-+void acpi_sleep_button_pressed(void)
-+{
-+ GPEState *s = &gpe_state;
-+
-+ if ( !test_bit(&s->gpe0_sts[0], ACPI_SLEEP_BUTTON_BIT) &&
-+ test_bit(&s->gpe0_en[0], ACPI_SLEEP_BUTTON_BIT) ) {
-+ set_bit(&s->gpe0_sts[0], ACPI_SLEEP_BUTTON_BIT);
-+ s->sci_asserted = 1;
-+ qemu_irq_raise(sci_irq);
-+ }
-+}
-+
- void acpi_lid_state_changed(void)
- {
- GPEState *s = &gpe_state;
-diff --git a/xenstore.c b/xenstore.c
-index 244f906..1a2e466 100644
---- a/xenstore.c
-+++ b/xenstore.c
-@@ -1006,6 +1006,10 @@ void xenstore_process_event(void *opaque)
- acpi_sleep_button_pressed();
- }
-
-+ if (!strcmp(vec[XS_WATCH_TOKEN], "slpbuttonpressedevt")) {
-+ acpi_sleep_button_pressed();
-+ }
-+
- if (!strcmp(vec[XS_WATCH_TOKEN], "lidstatechangeevt")) {
- acpi_lid_state_changed();
- goto out;
-diff -Nur a/hw/piix4acpi.c b/hw/piix4acpi.c
---- a/hw/piix4acpi.c 2009-05-13 16:23:59.000000000 -0400
-+++ b/hw/piix4acpi.c 2009-05-13 16:38:20.000000000 -0400
+diff --git a/hw/piix4acpi.c b/hw/piix4acpi.c
+index cf214a4..edede92 100644
+--- a/hw/piix4acpi.c
++++ b/hw/piix4acpi.c
@@ -30,6 +30,7 @@
#include "qemu-xen.h"
#include "battery_mgmt.h"
#include <xen/hvm/ioreq.h>
#include <xen/hvm/params.h>
-@@ -198,6 +199,7 @@
+@@ -198,6 +199,7 @@ static void acpi_map(PCIDevice *pci_dev, int region_num,
battery_mgmt_init(pci_dev);
xen_acpi_wmi_init(pci_dev);
}
static inline int test_bit(uint8_t *map, int bit)
-diff -Nur a/hw/thermal_mgmt.c b/hw/thermal_mgmt.c
---- a/hw/thermal_mgmt.c 1969-12-31 19:00:00.000000000 -0500
-+++ b/hw/thermal_mgmt.c 2009-05-13 16:36:41.000000000 -0400
+diff --git a/hw/thermal_mgmt.c b/hw/thermal_mgmt.c
+new file mode 100644
+index 0000000..649b622
+--- /dev/null
++++ b/hw/thermal_mgmt.c
@@ -0,0 +1,79 @@
+/*
+ * thermal_mgmt.c
+
+#endif
+
-diff -Nur a/hw/thermal_mgmt.h b/hw/thermal_mgmt.h
---- a/hw/thermal_mgmt.h 1969-12-31 19:00:00.000000000 -0500
-+++ b/hw/thermal_mgmt.h 2009-05-13 16:36:42.000000000 -0400
+diff --git a/hw/thermal_mgmt.h b/hw/thermal_mgmt.h
+new file mode 100644
+index 0000000..d83273b
+--- /dev/null
++++ b/hw/thermal_mgmt.h
@@ -0,0 +1,35 @@
+/*
+ * thermal_mgmt.h
+
+#endif
+
-diff -Nur a/qemu-xen.h b/qemu-xen.h
---- a/qemu-xen.h 2009-05-13 16:21:56.000000000 -0400
-+++ b/qemu-xen.h 2009-05-13 16:35:27.000000000 -0400
-@@ -111,9 +111,12 @@
+diff --git a/qemu-xen.h b/qemu-xen.h
+index 60ee108..0cc5dd8 100644
+--- a/qemu-xen.h
++++ b/qemu-xen.h
+@@ -125,9 +125,12 @@ char *xenstore_device_model_read(int domid, const char *key, unsigned int *len);
int xenstore_extended_power_mgmt_read_int(const char *key, int default_value);
char *xenstore_read_battery_data(int battery_status);
int xenstore_refresh_battery_status(void);
void xenstore_register_for_oem_events(void);
int xenstore_pv_driver_build_blacklisted(uint16_t product_number,
uint32_t build_nr);
-diff -Nur a/xen-hooks.mak b/xen-hooks.mak
---- a/xen-hooks.mak 2009-05-13 16:22:31.000000000 -0400
-+++ b/xen-hooks.mak 2009-05-13 16:34:35.000000000 -0400
-@@ -36,6 +36,7 @@
+diff --git a/xen-hooks.mak b/xen-hooks.mak
+index 03d670e..7c94718 100644
+--- a/xen-hooks.mak
++++ b/xen-hooks.mak
+@@ -36,6 +36,7 @@ OBJS += pci_emulation.o
OBJS += helper2.o
OBJS += battery_mgmt.o
OBJS += xen_acpi_wmi.o
ifdef CONFIG_STUBDOM
CPPFLAGS += $(TARGET_CPPFLAGS) -DNEED_CPU_H \
-diff -Nur a/xenstore.c b/xenstore.c
---- a/xenstore.c 2009-05-13 16:21:26.000000000 -0400
-+++ b/xenstore.c 2009-05-13 16:33:22.000000000 -0400
-@@ -1412,6 +1412,11 @@
+diff --git a/xenstore.c b/xenstore.c
+index 7cd4d54..01afcf0 100644
+--- a/xenstore.c
++++ b/xenstore.c
+@@ -1464,6 +1464,11 @@ int xenstore_refresh_battery_status(void)
return xenstore_extended_power_mgmt_event_trigger("refreshbatterystatus", "1");
}
+ return xenstore_extended_power_mgmt_event_trigger("refreshthermalinfo", "1");
+}
+
- /*
- * Create a store entry for a device (e.g., monitor, serial/parallel lines).
- * The entry is <domain-path><storeString>/tty and the value is the name
-@@ -1520,3 +1525,13 @@
+ void xenstore_register_for_pm_events(void)
+ {
+ xs_watch(xsh, "/pm/events/acadapterstatechanged", "acadapterstatechangeevt");
+@@ -1487,6 +1492,16 @@ int xenstore_read_lid_state(void)
return xenstore_extended_power_mgmt_read_int("lid_state", 1);
}
+ return xenstore_extended_power_mgmt_read_int("critical_temperature", 100);
+}
+
+ /*
+ * Create a store entry for a device (e.g., monitor, serial/parallel lines).
+ * The entry is <domain-path><storeString>/tty and the value is the name