From: Vincent Hanquez Date: Wed, 20 May 2009 19:48:35 +0000 (+0100) Subject: push 3.4 in master X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=8bf8b994837fcc55ee964993827b288f8f969bb3;p=xenclient%2Fioemu-pq.git push 3.4 in master --- diff --git a/master/battery-management b/master/battery-management new file mode 100644 index 0000000..b5e1a99 --- /dev/null +++ b/master/battery-management @@ -0,0 +1,272 @@ +diff --git a/hw/battery_mgmt.c b/hw/battery_mgmt.c +index 3ddeb09..1c83b80 100644 +--- a/hw/battery_mgmt.c ++++ b/hw/battery_mgmt.c +@@ -29,7 +29,6 @@ + #include "hw.h" + #include "pc.h" + #include "qemu-xen.h" +-#include "qemu-log.h" + #include "isa.h" //register_ioport_read declaration + #include "battery_mgmt.h" + +@@ -59,6 +58,7 @@ + + static enum POWER_MGMT_MODE power_mgmt_mode = PM_MODE_NONE; + static battery_state_info battery_info; ++extern FILE *logfile; + + int is_battery_pt_feasible(void) + { +@@ -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/battery_mgmt.h b/hw/battery_mgmt.h +index 4a4ac8e..19129b8 100644 +--- a/hw/battery_mgmt.h ++++ b/hw/battery_mgmt.h +@@ -42,4 +42,12 @@ typedef struct battery_state_info { + + void battery_mgmt_init(PCIDevice *device); + ++#ifndef CONFIG_NO_BATTERY_MGMT ++int is_battery_pt_feasible(void); ++void battery_mgmt_pt_mode_init(void); ++void get_battery_data_from_xenstore(void); ++void write_battery_data_to_port(void); ++void battery_mgmt_non_pt_mode_init(PCIDevice *device); ++#endif ++ + #endif +diff --git a/hw/pc.h b/hw/pc.h +index 8b71d48..a261c8a 100644 +--- a/hw/pc.h ++++ b/hw/pc.h +@@ -106,6 +106,10 @@ 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_sleep_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..c218782 100644 +--- a/hw/piix4acpi.c ++++ b/hw/piix4acpi.c +@@ -53,6 +53,11 @@ + + /* 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_SLEEP_BUTTON_BIT 0x0 ++#define ACPI_LID_STATE_BIT 0x17 + + typedef struct AcpiDeviceState AcpiDeviceState; + AcpiDeviceState *acpi_device_table; +@@ -192,8 +197,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 +213,56 @@ 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_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; ++ ++ 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) +diff --git a/qemu-xen.h b/qemu-xen.h +index c45bf9f..8c1debd 100644 +--- a/qemu-xen.h ++++ b/qemu-xen.h +@@ -122,8 +122,12 @@ void xenstore_dm_finished_startup(void); + int xenstore_vm_write(int domid, const char *key, const char *val); + 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); ++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_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 99b31fd..6f5b073 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" + +@@ -991,6 +992,25 @@ void xenstore_process_event(void *opaque) + goto out; + } + ++ 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], "slpbuttonpressedevt")) { ++ acpi_sleep_button_pressed(); ++ } ++ ++ if (!strcmp(vec[XS_WATCH_TOKEN], "lidstatechangeevt")) { ++ acpi_lid_state_changed(); ++ goto out; ++ } ++ + if (strncmp(vec[XS_WATCH_TOKEN], "hd", 2) || + strlen(vec[XS_WATCH_TOKEN]) != 3) + goto out; +@@ -1373,6 +1393,20 @@ static char *xenstore_extended_power_mgmt_read(const char *key, unsigned int *le + return value; + } + ++int xenstore_extended_power_mgmt_read_int(const char *key, int default_value) ++{ ++ int value = default_value; ++ char *buffer; ++ ++ buffer = xenstore_extended_power_mgmt_read(key, NULL); ++ if ( buffer == NULL ) ++ return value; ++ ++ value = strtoull(buffer, NULL, 10); ++ free(buffer); ++ return value; ++} ++ + static int xenstore_extended_power_mgmt_write(const char *key, const char *value) + { + int ret; +@@ -1425,6 +1459,24 @@ int xenstore_refresh_battery_status(void) + return xenstore_extended_power_mgmt_event_trigger("refreshbatterystatus", "1"); + } + ++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"); ++ xs_watch(xsh, "/pm/events/sleepbuttonpressed", "slpbuttonpressedevt"); ++} ++ ++int xenstore_read_ac_adapter_state(void) ++{ ++ return xenstore_extended_power_mgmt_read_int("ac_adapter", 1); ++} ++ ++int xenstore_read_lid_state(void) ++{ ++ return xenstore_extended_power_mgmt_read_int("lid_state", 1); ++} ++ + /* + * Create a store entry for a device (e.g., monitor, serial/parallel lines). + * The entry is /tty and the value is the name diff --git a/master/disable-aio b/master/disable-aio new file mode 100644 index 0000000..b6c874e --- /dev/null +++ b/master/disable-aio @@ -0,0 +1,13 @@ +diff --git a/xen-setup b/xen-setup +index 24defda..84f2936 100755 +--- a/xen-setup ++++ b/xen-setup +@@ -9,7 +9,7 @@ rm -f config-host.mak + + if test -f config-host.h; then mv config-host.h config-host.h~; fi + +-./configure --disable-gfx-check --disable-curses --disable-slirp --disable-vnc-tls --disable-sdl "$@" --prefix=/usr ++./configure --disable-gfx-check --disable-curses --disable-slirp --disable-vnc-tls --disable-sdl --disable-aio "$@" --prefix=/usr + + target=i386-dm + diff --git a/master/dm-ready b/master/dm-ready new file mode 100644 index 0000000..2a9fb8c --- /dev/null +++ b/master/dm-ready @@ -0,0 +1,55 @@ +diff --git a/qemu-xen.h b/qemu-xen.h +index 434d7db..3dc4518 100644 +--- a/qemu-xen.h ++++ b/qemu-xen.h +@@ -86,6 +86,7 @@ void xenstore_dom_chmod(int domid, const char *key, const char *perms); + char *xenstore_read(const char *path); + int xenstore_write(const char *path, const char *val); + ++void xenstore_dm_finished_startup(void); + + /* `danger' means that this parameter, variable or function refers to + * an area of xenstore which is writeable by the guest and thus must +diff --git a/vl.c b/vl.c +index 5801e42..c31e0a1 100644 +--- a/vl.c ++++ b/vl.c +@@ -5966,6 +5966,8 @@ int main(int argc, char **argv, char **envp) + close(fd); + } + ++ xenstore_dm_finished_startup(); ++ + main_loop(); + quit_timers(); + net_cleanup(); +diff --git a/xenstore.c b/xenstore.c +index 6448416..6834cce 100644 +--- a/xenstore.c ++++ b/xenstore.c +@@ -1609,3 +1609,25 @@ int xenstore_write(const char *path, const char *val) + } + + ++/* Advertise through xenstore that the device model is up and the ++ domain can be started. */ ++void xenstore_dm_finished_startup(void) ++{ ++ char *path; ++ char *buf = NULL; ++ ++ path = xs_get_domain_path(xsh, domid); ++ if (!path) { ++ fprintf(logfile, "xs_get_domain_path() failed.\n"); ++ goto out; ++ } ++ if (pasprintf(&buf, "%s/device-misc/dm-ready", path) == -1) { ++ fprintf(logfile, "pasprintf failed to get path.\n"); ++ goto out; ++ } ++ if (xs_write(xsh, XBT_NULL, buf, "1", 1) == 0) ++ fprintf(logfile, "xs_write() dm-ready failed\n"); ++ out: ++ free(buf); ++ free(path); ++} diff --git a/master/dom0-driver b/master/dom0-driver new file mode 100644 index 0000000..daaa97c --- /dev/null +++ b/master/dom0-driver @@ -0,0 +1,1415 @@ +diff --git a/console.h b/console.h +index 14b42f3..97214c0 100644 +--- a/console.h ++++ b/console.h +@@ -341,4 +341,19 @@ const char *readline_get_history(unsigned int index); + void readline_start(const char *prompt, int is_password, + ReadLineFunc *readline_func, void *opaque); + ++/* get_time */ ++char *get_time(void); ++ ++/* dom0_driver.c */ ++void dom0_driver_init(const char *position); ++ ++/* hid_linux.c */ ++void hid_linux_init(void); ++int hid_linux_grab_keyboard(int grab); ++int hid_linux_grab_mouse(int grab); ++void hid_linux_secure_keyboard(void (*)(int)); ++void hid_linux_add_binding(const int *, void (*)(void*), void *); ++void hid_linux_reset_keyboard(void); ++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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++++ b/qemu-xen.h +@@ -107,7 +107,13 @@ int xenstore_write(const char *path, const char *val); + + void xenstore_dm_finished_startup(void); + +- /* `danger' means that this parameter, variable or function refers to ++char *xenstore_read_dom0_driver(const char *key); ++int xenstore_write_dom0_driver(const char *key, const char *str); ++int xenstore_watch_dom0_driver(const char *key, xenstore_callback fptr, void *opaque); ++ ++int *xenstore_get_domids(int *len); ++ ++/* `danger' means that this parameter, variable or function refers to + * an area of xenstore which is writeable by the guest and thus must + * not be trusted by qemu code. For variables containing xenstore + * paths, `danger' can mean that both the path refers to a +diff --git a/vl.c b/vl.c +index e519705..0ffe1ec 100644 +--- a/vl.c ++++ b/vl.c +@@ -234,6 +234,7 @@ CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES]; + int win2k_install_hack = 0; + int rtc_td_hack = 0; + int vga_passthrough = 0; ++const char *dom0_input = NULL; + #endif + int usb_enabled = 0; + int smp_cpus = 1; +@@ -278,6 +279,20 @@ uint8_t qemu_uuid[16]; + + #include "xen-vl-extra.c" + ++char *get_time(void) ++{ ++ ++ char buff[128]; ++ char *str; ++ struct timeval tv; ++ ++ gettimeofday(&tv, NULL); ++ str = malloc(256); ++ strftime(buff, 128, "%T", localtime(&tv.tv_sec)); ++ sprintf(str, "%s:%06d", buff, (int)tv.tv_usec); ++ return str; ++} ++ + /***********************************************************/ + /* x86 ISA bus support */ + +@@ -4277,6 +4292,7 @@ enum { + QEMU_OPTION_acpi, + QEMU_OPTION_vcpus, + QEMU_OPTION_vga_passthrough, ++ QEMU_OPTION_dom0_input, + + /* Debug/Expert options: */ + QEMU_OPTION_serial, +@@ -4451,6 +4467,7 @@ static const QEMUOption qemu_options[] = { + { "vncunused", 0, QEMU_OPTION_vncunused }, + { "vcpus", HAS_ARG, QEMU_OPTION_vcpus }, + { "vga-passthrough", 0, QEMU_OPTION_vga_passthrough }, ++ { "dom0-input", 1, QEMU_OPTION_dom0_input }, + #if defined(CONFIG_XEN) && !defined(CONFIG_DM) + { "xen-domid", HAS_ARG, QEMU_OPTION_xen_domid }, + { "xen-create", 0, QEMU_OPTION_xen_create }, +@@ -5287,6 +5304,9 @@ int main(int argc, char **argv, char **envp) + case QEMU_OPTION_vga_passthrough: + vga_passthrough = 1; + break; ++ case QEMU_OPTION_dom0_input: ++ dom0_input = optarg; ++ break; + case QEMU_OPTION_direct_pci: + direct_pci = optarg; + break; +@@ -6053,6 +6073,9 @@ int main(int argc, char **argv, char **envp) + close(fd); + } + ++ if (dom0_input) ++ dom0_driver_init(dom0_input); ++ + xenstore_dm_finished_startup(); + + main_loop(); +diff --git a/xen-hooks.mak b/xen-hooks.mak +index 7c94718..f243df1 100644 +--- a/xen-hooks.mak ++++ b/xen-hooks.mak +@@ -37,6 +37,8 @@ OBJS += helper2.o + OBJS += battery_mgmt.o + OBJS += xen_acpi_wmi.o + OBJS += thermal_mgmt.o ++OBJS += dom0_driver.o ++OBJS += hid-linux.o + + ifdef CONFIG_STUBDOM + CPPFLAGS += $(TARGET_CPPFLAGS) -DNEED_CPU_H \ +diff --git a/xenstore.c b/xenstore.c +index 01afcf0..20ca8cf 100644 +--- a/xenstore.c ++++ b/xenstore.c +@@ -1727,3 +1727,63 @@ void xenstore_dm_finished_startup(void) + free(buf); + free(path); + } ++ ++char *xenstore_read_dom0_driver(const char *key) ++{ ++ const char *path = "/local/domain/0/dom0_driver"; ++ char *buf = NULL; ++ int len = 0; ++ char *val = NULL; ++ ++ if (pasprintf(&buf, "%s/%s", path, key) == -1) ++ return NULL; ++ val = xs_read(xsh, XBT_NULL, buf, &len); ++ free(buf); ++ return val; ++} ++ ++int xenstore_watch_dom0_driver(const char *key, xenstore_callback fptr, void *opaque) ++{ ++ const char *path = "/local/domain/0/dom0_driver"; ++ char *buf = NULL; ++ int ret = 0; ++ ++ if (pasprintf(&buf, "%s/%s", path, key) == -1) ++ return 0; ++ xenstore_watch_new_callback(buf, fptr, opaque); ++ free(buf); ++ return ret; ++} ++ ++int xenstore_write_dom0_driver(const char *key, const char *str) ++{ ++ const char *path = "/local/domain/0/dom0_driver"; ++ char *buf = NULL; ++ int len = 0; ++ int ret = 0; ++ ++ if (pasprintf(&buf, "%s/%s", path, key) == -1) ++ return 0; ++ ret = xs_write(xsh, XBT_NULL, buf, str, strlen(str)); ++ free(buf); ++ return ret; ++} ++ ++int *xenstore_get_domids(int *len) ++{ ++ int *tab = NULL; ++ char **e; ++ ++ e = xs_directory(xsh, XBT_NULL, "/local/domain", len); ++ if (e == NULL) ++ { ++ len = 0; ++ return NULL; ++ } ++ ++ tab = malloc(*len * sizeof (int)); ++ for (int i = 0; i < *len; i++) ++ tab[i] = strtol(e[i], NULL, 10); ++ return tab; ++} ++ diff --git a/master/fix-build-warnings b/master/fix-build-warnings new file mode 100644 index 0000000..9b2d41c --- /dev/null +++ b/master/fix-build-warnings @@ -0,0 +1,19 @@ +diff -Nur a/hw/pci.h b/hw/pci.h +--- a/hw/pci.h 2009-05-13 14:31:58.000000000 -0400 ++++ b/hw/pci.h 2009-05-13 16:51:34.000000000 -0400 +@@ -168,9 +168,13 @@ + #define PCI_STATUS_RESERVED1 0x007 + #define PCI_STATUS_INT_STATUS 0x008 + #define PCI_STATUS_CAPABILITIES 0x010 +-#define PCI_STATUS_66MHZ 0x020 ++#ifndef PCI_STATUS_66MHZ ++#define PCI_STATUS_66MHZ 0x020 ++#endif + #define PCI_STATUS_RESERVED2 0x040 +-#define PCI_STATUS_FAST_BACK 0x080 ++#ifndef PCI_STATUS_FAST_BACK ++#define PCI_STATUS_FAST_BACK 0x080 ++#endif + #define PCI_STATUS_DEVSEL 0x600 + + #define PCI_STATUS_RESERVED_MASK_LO (PCI_STATUS_RESERVED1 | \ diff --git a/master/intel b/master/intel new file mode 100644 index 0000000..3520c50 --- /dev/null +++ b/master/intel @@ -0,0 +1,605 @@ +diff --git a/console.h b/console.h +index 97214c0..4c51c50 100644 +--- a/console.h ++++ b/console.h +@@ -290,6 +290,9 @@ void vga_hw_update(void); + void vga_hw_invalidate(void); + void vga_hw_screen_dump(const char *filename); + ++void unset_vga_acc(void); ++void set_vga_acc(void); ++ + int is_graphic_console(void); + int is_fixedsize_console(void); + CharDriverState *text_console_init(const char *p); +@@ -356,4 +359,8 @@ void hid_linux_add_binding(const int *, void (*)(void*), void *); + void hid_linux_reset_keyboard(void); + void hid_linux_probe(int grab); + ++/* intel.c */ ++int intel_enter(void); ++int intel_leave(void); ++void intel_display_init(DisplayState *ds); + #endif +diff --git a/hw/vga.c b/hw/vga.c +index 90bd544..b0f9f9c 100644 +--- a/hw/vga.c ++++ b/hw/vga.c +@@ -161,6 +161,18 @@ static uint8_t expand4to8[16]; + static void vga_bios_init(VGAState *s); + static void vga_screen_dump(void *opaque, const char *filename); + ++static VGAState *xen_vga_state; ++ ++void set_vga_acc(void) ++{ ++ set_vram_mapping(xen_vga_state, xen_vga_state->lfb_addr, xen_vga_state->lfb_end); ++} ++ ++void unset_vga_acc(void) ++{ ++ unset_vram_mapping(xen_vga_state); ++} ++ + static void vga_dumb_update_retrace_info(VGAState *s) + { + (void) s; +@@ -2473,8 +2485,6 @@ static void vga_bios_init(VGAState *s) + } + + +-static VGAState *xen_vga_state; +- + /* 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++++ b/vl.c +@@ -235,6 +235,7 @@ int win2k_install_hack = 0; + int rtc_td_hack = 0; + int vga_passthrough = 0; + const char *dom0_input = NULL; ++int intel = 0; + #endif + int usb_enabled = 0; + int smp_cpus = 1; +@@ -4293,6 +4294,7 @@ enum { + QEMU_OPTION_vcpus, + QEMU_OPTION_vga_passthrough, + QEMU_OPTION_dom0_input, ++ QEMU_OPTION_intel, + + /* Debug/Expert options: */ + QEMU_OPTION_serial, +@@ -4468,6 +4470,7 @@ static const QEMUOption qemu_options[] = { + { "vcpus", HAS_ARG, QEMU_OPTION_vcpus }, + { "vga-passthrough", 0, QEMU_OPTION_vga_passthrough }, + { "dom0-input", 1, QEMU_OPTION_dom0_input }, ++ { "intel", 0, QEMU_OPTION_dom0_input }, + #if defined(CONFIG_XEN) && !defined(CONFIG_DM) + { "xen-domid", HAS_ARG, QEMU_OPTION_xen_domid }, + { "xen-create", 0, QEMU_OPTION_xen_create }, +@@ -5307,6 +5310,9 @@ int main(int argc, char **argv, char **envp) + case QEMU_OPTION_dom0_input: + dom0_input = optarg; + break; ++ case QEMU_OPTION_intel: ++ intel = 1; ++ break; + case QEMU_OPTION_direct_pci: + direct_pci = optarg; + break; +diff --git a/xen-hooks.mak b/xen-hooks.mak +index f243df1..55dd477 100644 +--- a/xen-hooks.mak ++++ b/xen-hooks.mak +@@ -39,6 +39,7 @@ OBJS += xen_acpi_wmi.o + OBJS += thermal_mgmt.o + OBJS += dom0_driver.o + OBJS += hid-linux.o ++OBJS += intel.o + + ifdef CONFIG_STUBDOM + CPPFLAGS += $(TARGET_CPPFLAGS) -DNEED_CPU_H \ diff --git a/master/ioemu-compil b/master/ioemu-compil new file mode 100644 index 0000000..477838b --- /dev/null +++ b/master/ioemu-compil @@ -0,0 +1,45 @@ +diff --git a/xen-hooks.mak b/xen-hooks.mak +index c6b4f8c..d2f09fb 100644 +--- a/xen-hooks.mak ++++ b/xen-hooks.mak +@@ -52,7 +52,7 @@ endif + ifdef CONFIG_STUBDOM + CONFIG_PASSTHROUGH=1 + else +- ifeq (,$(wildcard /usr/include/pci)) ++ ifeq (,$(wildcard $(PCI_PREFIX_DIR)/usr/include/pci)) + $(warning === pciutils-dev package not found - missing /usr/include/pci) + $(warning === PCI passthrough capability has been disabled) + else +@@ -62,6 +62,9 @@ endif + + ifdef CONFIG_PASSTHROUGH + OBJS+= pass-through.o pt-msi.o ++ifdef PCI_PREFIX_DIR ++LIBS += -L$(PCI_PREFIX_DIR)/usr/lib ++endif + LIBS += -lpci + CFLAGS += -DCONFIG_PASSTHROUGH + $(info === PCI passthrough capability has been enabled ===) +diff --git a/xen-setup b/xen-setup +index 8ca0019..24defda 100755 +--- a/xen-setup ++++ b/xen-setup +@@ -9,7 +9,7 @@ rm -f config-host.mak + + if test -f config-host.h; then mv config-host.h config-host.h~; fi + +-./configure --disable-gfx-check --disable-curses --disable-slirp "$@" --prefix=/usr ++./configure --disable-gfx-check --disable-curses --disable-slirp --disable-vnc-tls --disable-sdl "$@" --prefix=/usr + + target=i386-dm + +@@ -17,6 +17,8 @@ if [ "x$XEN_ROOT" != x ]; then + echo "XEN_ROOT=$XEN_ROOT" >>config-host.mak + fi + ++echo "PCI_PREFIX_DIR=${STAGING_ROOT}" >>config-host.mak ++ + ln -sf ../Makefile.target $target/Makefile + ln -sf ../xen-config.mak $target/config.mak + cat xen-config-host.mak >>config-host.mak diff --git a/master/oem-features b/master/oem-features new file mode 100644 index 0000000..7110652 --- /dev/null +++ b/master/oem-features @@ -0,0 +1,973 @@ +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 ++++ b/hw/pc.h +@@ -111,6 +111,8 @@ void acpi_power_button_pressed(void); + void acpi_sleep_button_pressed(void); + void acpi_lid_state_changed(void); + ++void acpi_oem_event(void); ++ + /* hpet.c */ + extern int no_hpet; + +diff --git a/hw/piix4acpi.c b/hw/piix4acpi.c +index c218782..cf214a4 100644 +--- a/hw/piix4acpi.c ++++ b/hw/piix4acpi.c +@@ -29,6 +29,7 @@ + #include "sysemu.h" + #include "qemu-xen.h" + #include "battery_mgmt.h" ++#include "xen_acpi_wmi.h" + + #include + #include +@@ -58,6 +59,7 @@ + #define ACPI_POWER_BUTTON_BIT 0x1 + #define ACPI_SLEEP_BUTTON_BIT 0x0 + #define ACPI_LID_STATE_BIT 0x17 ++#define ACPI_OEM_EVENT_BIT 0x18 + + typedef struct AcpiDeviceState AcpiDeviceState; + AcpiDeviceState *acpi_device_table; +@@ -195,6 +197,7 @@ static void acpi_map(PCIDevice *pci_dev, int region_num, + register_ioport_read(addr + 4, 2, 2, acpiPm1Control_readw, d); + + battery_mgmt_init(pci_dev); ++ xen_acpi_wmi_init(pci_dev); + } + + static inline int test_bit(uint8_t *map, int bit) +@@ -261,6 +262,19 @@ void acpi_lid_state_changed(void) + } + } + ++void acpi_oem_event(void) ++{ ++ GPEState *s = &gpe_state; ++ ++ if ( !test_bit(&s->gpe0_sts[0], ACPI_OEM_EVENT_BIT) && ++ test_bit(&s->gpe0_en[0], ACPI_OEM_EVENT_BIT) ) { ++ set_bit(&s->gpe0_sts[0], ACPI_OEM_EVENT_BIT); ++ s->sci_asserted = 1; ++ fprintf(logfile, "Raising oem event irq\n"); ++ qemu_irq_raise(sci_irq); ++ } ++} ++ + #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 ++ ++#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 ++++ b/qemu-xen.h +@@ -128,6 +128,7 @@ 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); ++void xenstore_register_for_oem_events(void); + int xenstore_pv_driver_build_blacklisted(uint16_t product_number, + uint32_t build_nr); + +diff --git a/xen-hooks.mak b/xen-hooks.mak +index d2f09fb..03d670e 100644 +--- a/xen-hooks.mak ++++ b/xen-hooks.mak +@@ -35,6 +35,7 @@ OBJS += exec-dm.o + 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 --git a/xenstore.c b/xenstore.c +index 6f5b073..7cd4d54 100644 +--- a/xenstore.c ++++ b/xenstore.c +@@ -1011,6 +1011,11 @@ void xenstore_process_event(void *opaque) + goto out; + } + ++ if (!strcmp(vec[XS_WATCH_TOKEN], "oemevt")) { ++ acpi_oem_event(); ++ goto out; ++ } ++ + if (strncmp(vec[XS_WATCH_TOKEN], "hd", 2) || + strlen(vec[XS_WATCH_TOKEN]) != 3) + goto out; +@@ -1467,6 +1472,11 @@ void xenstore_register_for_pm_events(void) + xs_watch(xsh, "/pm/events/sleepbuttonpressed", "slpbuttonpressedevt"); + } + ++void xenstore_register_for_oem_events(void) ++{ ++ xs_watch(xsh, "/oem/event", "oemevt"); ++} ++ + int xenstore_read_ac_adapter_state(void) + { + return xenstore_extended_power_mgmt_read_int("ac_adapter", 1); diff --git a/master/series b/master/series new file mode 100644 index 0000000..5f501b9 --- /dev/null +++ b/master/series @@ -0,0 +1,15 @@ +ioemu-compil +xenstore-watch-callbacks +dm-ready + +battery-management +oem-features +thermal-management +fix-build-warnings + + +vga-passthrough +dom0-driver +intel +use-vga-cmdline +disable-aio diff --git a/master/status b/master/status new file mode 100644 index 0000000..e69de29 diff --git a/master/thermal-management b/master/thermal-management new file mode 100644 index 0000000..47e74bc --- /dev/null +++ b/master/thermal-management @@ -0,0 +1,208 @@ +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_acpi_wmi.h" ++#include "thermal_mgmt.h" + + #include + #include +@@ -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); ++ thermal_mgmt_init(pci_dev); + } + + static inline int test_bit(uint8_t *map, int bit) +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 ++ * ++ * 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 ++ */ ++ ++/* Implementation Notes: Following provides a minimal thermal zone implementation for ++ * HVM guest. The vACPI layer exposes a single thermal zone with critical and current ++ * temperature objects which when invoked relies on the below to return back the critical ++ * and current temperature provided by the underlying firmware. ++ */ ++ ++#include "hw.h" ++#include "pc.h" ++#include "qemu-xen.h" ++#include "isa.h" ++#include "thermal_mgmt.h" ++ ++#ifndef CONFIG_NO_THERMAL_MGMT ++ ++/* #define THERMAL_MGMT_DBG */ ++ ++extern FILE *logfile; ++ ++static uint32_t thermal_port_1_readw(void *opaque, uint32_t addr) ++{ ++ int current_temp; ++ ++ xenstore_refresh_thermal_info(); ++ current_temp = xenstore_read_current_temperature(); ++#ifdef THERMAL_MGMT_DBG ++ fprintf(logfile, "Current temperature - %d\n", current_temp); ++#endif ++ return current_temp; ++} ++ ++static uint32_t thermal_port_2_readw(void *opaque, uint32_t addr) ++{ ++ int critical_temp; ++ ++ xenstore_refresh_thermal_info(); ++ critical_temp = xenstore_read_critical_temperature(); ++#ifdef THERMAL_MGMT_DBG ++ fprintf(logfile, "Critical trip point temperature - %d\n", critical_temp); ++#endif ++ return critical_temp; ++} ++ ++void thermal_mgmt_init(PCIDevice *device) ++{ ++#ifdef THERMAL_MGMT_DBG ++ fprintf(logfile, "In thermal management init\n"); ++#endif ++ ++ register_ioport_read(THERMAL_PORT_1, 1, 2, thermal_port_1_readw, device); ++ register_ioport_read(THERMAL_PORT_2, 1, 2, thermal_port_2_readw, device); ++} ++ ++#else ++ ++void thermal_mgmt_init(PCIDevice *device) { } ++ ++#endif ++ +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 ++ * ++ * 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 _THERMAL_MGMT_H ++#define _THERMAL_MGMT_H ++ ++#ifdef CONFIG_STUBDOM ++#define CONFIG_NO_THERMAL_MGMT ++#endif ++ ++#define THERMAL_PORT_1 0x90 ++#define THERMAL_PORT_2 0x92 ++ ++void thermal_mgmt_init(PCIDevice *device); ++ ++#endif ++ +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); ++int xenstore_refresh_thermal_info(void); + void xenstore_register_for_pm_events(void); + int xenstore_read_ac_adapter_state(void); + int xenstore_read_lid_state(void); ++int xenstore_read_current_temperature(void); ++int xenstore_read_critical_temperature(void); + void xenstore_register_for_oem_events(void); + int xenstore_pv_driver_build_blacklisted(uint16_t product_number, + uint32_t build_nr); +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 ++OBJS += thermal_mgmt.o + + ifdef CONFIG_STUBDOM + CPPFLAGS += $(TARGET_CPPFLAGS) -DNEED_CPU_H \ +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"); + } + ++int xenstore_refresh_thermal_info(void) ++{ ++ return xenstore_extended_power_mgmt_event_trigger("refreshthermalinfo", "1"); ++} ++ + 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); + } + ++int xenstore_read_current_temperature(void) ++{ ++ return xenstore_extended_power_mgmt_read_int("current_temperature", 0); ++} ++ ++int xenstore_read_critical_temperature(void) ++{ ++ 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 /tty and the value is the name diff --git a/master/use-vga-cmdline b/master/use-vga-cmdline new file mode 100644 index 0000000..4006998 --- /dev/null +++ b/master/use-vga-cmdline @@ -0,0 +1,49 @@ +diff --git a/vl.c b/vl.c +index ae32f82..05d12ae 100644 +--- a/vl.c ++++ b/vl.c +@@ -4598,24 +4598,20 @@ static void select_soundhw (const char *optarg) + static void select_vgahw (const char *p) + { + const char *opts; ++ std_vga_enabled = 0; ++ cirrus_vga_enabled = 0; ++ vmsvga_enabled = 0; + +- if (strstart(p, "std", &opts)) { ++ if (strstart(p, "std", &opts)) + std_vga_enabled = 1; +- cirrus_vga_enabled = 0; +- vmsvga_enabled = 0; +- } else if (strstart(p, "cirrus", &opts)) { ++ else if (strstart(p, "cirrus", &opts)) + cirrus_vga_enabled = 1; +- std_vga_enabled = 0; +- vmsvga_enabled = 0; +- } else if (strstart(p, "vmware", &opts)) { +- cirrus_vga_enabled = 0; +- std_vga_enabled = 0; ++ else if (strstart(p, "vmware", &opts)) + vmsvga_enabled = 1; +- } else if (strstart(p, "none", &opts)) { +- cirrus_vga_enabled = 0; +- std_vga_enabled = 0; +- vmsvga_enabled = 0; +- } else { ++ else if (strstart(p, "passthrough", &opts)) ++ vga_passthrough = 1; ++ else if (!strstart(p, "none", &opts)) ++ { + invalid_vga: + fprintf(stderr, "Unknown vga type: %s\n", p); + exit(1); +@@ -5272,6 +5268,9 @@ int main(int argc, char **argv, char **envp) + break; + case QEMU_OPTION_vga_passthrough: + vga_passthrough = 1; ++ std_vga_enabled = 0; ++ cirrus_vga_enabled = 0; ++ vmsvga_enabled = 0; + break; + case QEMU_OPTION_dom0_input: + dom0_input = optarg; diff --git a/master/vga-passthrough b/master/vga-passthrough new file mode 100644 index 0000000..d2adba9 --- /dev/null +++ b/master/vga-passthrough @@ -0,0 +1,235 @@ +diff --git a/hw/pass-through.c b/hw/pass-through.c +index 6a53137..3420e95 100644 +--- a/hw/pass-through.c ++++ b/hw/pass-through.c +@@ -90,6 +90,8 @@ + #include "qemu-xen.h" + #include + ++extern int vga_passthrough; ++ + struct php_dev { + struct pt_dev *pt_dev; + uint8_t valid; +@@ -1573,10 +1575,11 @@ static int pt_dev_is_virtfn(struct pci_dev *dev) + + static int pt_register_regions(struct pt_dev *assigned_device) + { +- int i = 0; ++ int i = 0, ret = 0; + uint32_t bar_data = 0; + struct pci_dev *pci_dev = assigned_device->pci_dev; + PCIDevice *d = &assigned_device->dev; ++ uint16_t vendor_id, class; + + /* Register PIO/MMIO BARs */ + for ( i = 0; i < PCI_BAR_ENTRIES; i++ ) +@@ -1632,6 +1635,28 @@ static int pt_register_regions(struct pt_dev *assigned_device) + (uint32_t)(pci_dev->rom_size), (uint32_t)(pci_dev->rom_base_addr)); + } + ++ /* Map legacy ioport and iomem, for specific devices */ ++ vendor_id = pci_read_word(pci_dev, 0x00); ++ class = pci_read_word(pci_dev, 0x0a); ++ ++ PT_LOG("Real device vendor_id=0x%x class=0x%x\n", vendor_id, class); ++ if ( vga_passthrough && class == 0x0300 ) ++ { ++ PT_LOG("add an intel graphic card\n"); ++ ++ ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3B0, 0x3B0, 0xb, ++ DPCI_ADD_MAPPING); ++ ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3C0, 0x3C0, 32, ++ DPCI_ADD_MAPPING); ++ ret |= xc_domain_memory_mapping(xc_handle, domid, 0xa0, 0xa0, 32, ++ DPCI_ADD_MAPPING); ++ if ( ret != 0 ) ++ { ++ PT_LOG("legacy mapping failed !\n"); ++ return ret; ++ } ++ } ++ + return 0; + } + +@@ -1640,6 +1665,7 @@ static void pt_unregister_regions(struct pt_dev *assigned_device) + int i, type, ret; + uint32_t e_size; + PCIDevice *d = (PCIDevice*)assigned_device; ++ uint16_t class, vendor_id; + + for ( i = 0; i < PCI_NUM_REGIONS; i++ ) + { +@@ -1681,6 +1707,26 @@ static void pt_unregister_regions(struct pt_dev *assigned_device) + + } + ++ /* unmap legacy ioport and iomem, for specific devices */ ++ vendor_id = pci_read_word(assigned_device->pci_dev, 0x00); ++ class = pci_read_word(assigned_device->pci_dev, 0x0a); ++ ++ PT_LOG("Real device vendor_id=0x%x class=0x%x\n", vendor_id, class); ++ if ( vga_passthrough && class == 0x0300 ) ++ { ++ PT_LOG("remove an intel graphic card\n"); ++ ++ ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3B0, 0x3B0, 0xb, ++ DPCI_REMOVE_MAPPING); ++ ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3C0, 0x3C0, 32, ++ DPCI_REMOVE_MAPPING); ++ ret |= xc_domain_memory_mapping(xc_handle, domid, 0xa0, 0xa0, 32, ++ DPCI_REMOVE_MAPPING); ++ if ( ret != 0 ) ++ { ++ PT_LOG("legacy unmapping failed !\n"); ++ } ++ } + } + + static uint8_t find_cap_offset(struct pci_dev *pci_dev, uint8_t cap) +@@ -4084,3 +4130,41 @@ err: + return status; + } + ++u8 pt_pci_host_read_byte(int bus, int dev, int fn, u32 addr) ++{ ++ struct pci_dev* pci_dev; ++ u8 val; ++ ++ pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn); ++ if (!pci_dev) ++ return 0; ++ val = pci_read_byte(pci_dev, addr); ++ pci_free_dev(pci_dev); ++ return val; ++} ++ ++u16 pt_pci_host_read_word(int bus, int dev, int fn, u32 addr) ++{ ++ struct pci_dev* pci_dev; ++ u16 val; ++ ++ pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn); ++ if (!pci_dev) ++ return 0; ++ val = pci_read_word(pci_dev, addr); ++ pci_free_dev(pci_dev); ++ return val; ++} ++ ++u32 pt_pci_host_read_long(int bus, int dev, int fn, u32 addr) ++{ ++ struct pci_dev* pci_dev; ++ u32 val; ++ ++ pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn); ++ if (!pci_dev) ++ return 0; ++ val = pci_read_long(pci_dev, addr); ++ pci_free_dev(pci_dev); ++ return val; ++} +diff --git a/hw/pass-through.h b/hw/pass-through.h +index a503e80..1752e8d 100644 +--- a/hw/pass-through.h ++++ b/hw/pass-through.h +@@ -392,5 +392,9 @@ static inline pciaddr_t pt_pci_base_addr(pciaddr_t base) + return base & PCI_ADDR_MEM_MASK; + } + ++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); ++ + #endif /* __PASSTHROUGH_H__ */ + +diff --git a/hw/pci.c b/hw/pci.c +index d7c516e..b2f4d43 100644 +--- a/hw/pci.c ++++ b/hw/pci.c +@@ -28,11 +28,14 @@ + #include "virtio-net.h" + #include "sysemu.h" + ++#include "pass-through.h" + #include "exec-all.h" + #include "qemu-xen.h" + + //#define DEBUG_PCI + ++extern int vga_passthrough; ++ + struct PCIBus { + int bus_num; + int devfn_min; +@@ -611,7 +614,30 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len) + goto the_end; + } + config_addr = addr & 0xff; +- val = pci_dev->config_read(pci_dev, config_addr, len); ++ if (vga_passthrough && pci_dev->devfn == 0x00) //Host Bridge ++ { ++ val = pci_dev->config_read(pci_dev, config_addr, len); ++ ++ if (config_addr == 0x52) // GMCH ++ val = pt_pci_host_read_word(0, 0, 0, 0x52); ++ if (config_addr == 0x02) // Device ID ++ { ++ if (len == 2) ++ val = pt_pci_host_read_word(0, 0, 0, 0x02); ++ } ++ if (config_addr == 0x0) ++ { ++ if (len == 2) ++ val = pt_pci_host_read_word(0, 0, 0, 0x00); ++ else if (len == 4) ++ val = pt_pci_host_read_long(0, 0, 0, 0x00); ++ } ++ } ++ else if (vga_passthrough && pci_dev->devfn == 0x10 && // intel graphic card ++ config_addr == 0xfc) // OpRegion address ++ val = 0; // force to fall back to SMI mode ++ else ++ val = pci_dev->config_read(pci_dev, config_addr, len); + #if defined(DEBUG_PCI) + printf("pci_config_read: %s: addr=%02x val=%08x len=%d\n", + pci_dev->name, config_addr, val, len); +diff --git a/vl.c b/vl.c +index b273c75..e519705 100644 +--- a/vl.c ++++ b/vl.c +@@ -233,6 +233,7 @@ CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES]; + #ifdef TARGET_I386 + int win2k_install_hack = 0; + int rtc_td_hack = 0; ++int vga_passthrough = 0; + #endif + int usb_enabled = 0; + int smp_cpus = 1; +@@ -4275,6 +4276,7 @@ enum { + QEMU_OPTION_domainname, + QEMU_OPTION_acpi, + QEMU_OPTION_vcpus, ++ QEMU_OPTION_vga_passthrough, + + /* Debug/Expert options: */ + QEMU_OPTION_serial, +@@ -4448,6 +4450,7 @@ static const QEMUOption qemu_options[] = { + { "pciemulation", HAS_ARG, QEMU_OPTION_pci_emulation }, + { "vncunused", 0, QEMU_OPTION_vncunused }, + { "vcpus", HAS_ARG, QEMU_OPTION_vcpus }, ++ { "vga-passthrough", 0, QEMU_OPTION_vga_passthrough }, + #if defined(CONFIG_XEN) && !defined(CONFIG_DM) + { "xen-domid", HAS_ARG, QEMU_OPTION_xen_domid }, + { "xen-create", 0, QEMU_OPTION_xen_create }, +@@ -5281,6 +5284,9 @@ int main(int argc, char **argv, char **envp) + case QEMU_OPTION_disable_opengl: + opengl_enabled = 0; + break; ++ case QEMU_OPTION_vga_passthrough: ++ vga_passthrough = 1; ++ break; + case QEMU_OPTION_direct_pci: + direct_pci = optarg; + break; diff --git a/master/xenstore-watch-callbacks b/master/xenstore-watch-callbacks new file mode 100644 index 0000000..916f5f4 --- /dev/null +++ b/master/xenstore-watch-callbacks @@ -0,0 +1,244 @@ +Improved the way to do xenstore watchs. + +diff --git a/qemu-xen.h b/qemu-xen.h +index ec4cd94..9f7feda 100644 +--- a/qemu-xen.h ++++ b/qemu-xen.h +@@ -78,6 +78,19 @@ int xenstore_unsubscribe_from_hotplug_status(struct xs_handle *handle, + const char *inst, + const char *token); + ++typedef void (*xenstore_callback) (const char *path, void *opaque); ++int xenstore_watch_screenshot_node(DisplayState *ds); ++int xenstore_watch_new_callback(const char *path, xenstore_callback fptr, void *opaque); ++ ++char *xenstore_dom_read(int domid, const char *key, unsigned int *len); ++int xenstore_dom_write(int domid, const char *key, const char *value); ++void xenstore_dom_watch(int domid, const char *key, xenstore_callback ftp, void *opaque); ++void xenstore_dom_chmod(int domid, const char *key, const char *perms); ++ ++char *xenstore_read(const char *path); ++int xenstore_write(const char *path, const char *val); ++ ++ + /* `danger' means that this parameter, variable or function refers to + * an area of xenstore which is writeable by the guest and thus must + * not be trusted by qemu code. For variables containing xenstore +@@ -92,7 +105,7 @@ int xenstore_unsubscribe_from_hotplug_status(struct xs_handle *handle, + + int xenstore_vm_write(int domid, const char *key, const char *val); + char *xenstore_vm_read(int domid, const char *key, unsigned int *len); +-char *xenstore_device_model_read(int domid, 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); + int xenstore_pv_driver_build_blacklisted(uint16_t product_number, +diff --git a/xenstore.c b/xenstore.c +index ef7b5f3..ea39dce 100644 +--- a/xenstore.c ++++ b/xenstore.c +@@ -37,6 +37,52 @@ static QEMUTimer *insert_timer = NULL; + #define UWAIT_MAX (30*1000000) /* thirty seconds */ + #define UWAIT (100000) /* 1/10th second */ + ++struct xenstore_watch_cb_t ++{ ++ char *path; ++ xenstore_callback cb; ++ void *opaque; ++}; ++ ++static struct xenstore_watch_cb_t *xenstore_watch_callbacks = NULL; ++ ++int xenstore_watch_new_callback(const char *path, ++ xenstore_callback fptr, ++ void *opaque) ++{ ++ int i = 0, ret = 0; ++ ++ ret = xs_watch(xsh, path, path); ++ if (ret == 0) ++ return 0; ++ ++ if (!xenstore_watch_callbacks) ++ { ++ xenstore_watch_callbacks = malloc(sizeof (struct xenstore_watch_cb_t)); ++ xenstore_watch_callbacks[0].path = NULL; ++ } ++ ++ while (xenstore_watch_callbacks[i].path) ++ { ++ if (!strcmp(xenstore_watch_callbacks[i].path, path)) ++ { ++ xenstore_watch_callbacks[i].cb = fptr; ++ xenstore_watch_callbacks[i].opaque = opaque; ++ return ret; ++ } ++ i++; ++ } ++ ++ xenstore_watch_callbacks = realloc(xenstore_watch_callbacks, ++ (i + 2) * sizeof (struct xenstore_watch_cb_t)); ++ xenstore_watch_callbacks[i].path = strdup(path); ++ xenstore_watch_callbacks[i].cb = fptr; ++ xenstore_watch_callbacks[i].opaque = opaque; ++ xenstore_watch_callbacks[i + 1].path = NULL; ++ return ret; ++} ++ ++ + static int pasprintf(char **buf, const char *fmt, ...) + { + va_list ap; +@@ -904,12 +950,18 @@ void xenstore_record_dm_state(const char *state) + void xenstore_process_event(void *opaque) + { + char **vec, *offset, *bpath = NULL, *buf = NULL, *drv = NULL, *image = NULL; +- unsigned int len, num, hd_index; ++ unsigned int len, num, hd_index, i; + + vec = xs_read_watch(xsh, &num); + if (!vec) + return; + ++ for (i = 0; xenstore_watch_callbacks && xenstore_watch_callbacks[i].path; i++) ++ if (xenstore_watch_callbacks[i].cb && ++ !strcmp(vec[XS_WATCH_TOKEN], xenstore_watch_callbacks[i].path)) ++ xenstore_watch_callbacks[i].cb(vec[XS_WATCH_TOKEN], ++ xenstore_watch_callbacks[i].opaque); ++ + if (!strcmp(vec[XS_WATCH_TOKEN], "logdirty")) { + xenstore_process_logdirty_event(); + goto out; +@@ -1272,7 +1324,7 @@ int xenstore_vm_write(int domid, const char *key, const char *value) + return rc; + } + +-char *xenstore_device_model_read(int domid, char *key, unsigned int *len) ++char *xenstore_device_model_read(int domid, const char *key, unsigned int *len) + { + char *path = NULL, *value = NULL; + +@@ -1438,3 +1490,122 @@ void xenstore_store_serial_port_info(int i, CharDriverState *chr, + if (i == 0) /* serial 0 is also called the console */ + store_dev_info(devname, domid, chr, "/console"); + } ++ ++char *xenstore_dom_read(int domid, const char *key, unsigned int *len) ++{ ++ char *buf = NULL, *path = NULL, *value = NULL; ++ ++ if (xsh == NULL) ++ goto out; ++ ++ path = xs_get_domain_path(xsh, domid); ++ if (path == NULL) { ++ fprintf(logfile, "xs_get_domain_path(%d): error\n", domid); ++ goto out; ++ } ++ ++ pasprintf(&buf, "%s/%s", path, key); ++ value = xs_read(xsh, XBT_NULL, buf, len); ++ if (value == NULL) { ++ fprintf(logfile, "xs_read(%s): read error\n", buf); ++ goto out; ++ } ++ ++ out: ++ free(path); ++ free(buf); ++ return value; ++} ++ ++void xenstore_dom_watch(int domid, const char *key, xenstore_callback fptr, void *opaque) ++{ ++ char *buf = NULL, *path = NULL; ++ int rc = -1; ++ ++ if (xsh == NULL) ++ goto out; ++ ++ path = xs_get_domain_path(xsh, domid); ++ if (path == NULL) { ++ fprintf(logfile, "xs_get_domain_path: error\n"); ++ goto out; ++ } ++ ++ pasprintf(&buf, "%s/%s", path, key); ++ xenstore_watch_new_callback(buf, fptr, opaque); ++ ++ out: ++ free(path); ++ free(buf); ++} ++ ++void xenstore_dom_chmod(int domid, const char *key, const char *perms) ++{ ++ char *buf = NULL, *path = NULL; ++ int rc = -1; ++ struct xs_permissions p; ++ ++ if (xsh == NULL) ++ goto out; ++ ++ path = xs_get_domain_path(xsh, domid); ++ if (path == NULL) { ++ fprintf(logfile, "xs_get_domain_path: error\n"); ++ goto out; ++ } ++ ++ pasprintf(&buf, "%s/%s", path, key); ++ ++ xs_strings_to_perms(&p, 1, perms); ++ xs_set_permissions(xsh, XBT_NULL, buf, &p, 1); ++ ++ out: ++ free(path); ++ free(buf); ++} ++ ++int xenstore_dom_write(int domid, const char *key, const char *value) ++{ ++ char *buf = NULL, *path = NULL; ++ int rc = -1; ++ ++ if (xsh == NULL) ++ goto out; ++ ++ path = xs_get_domain_path(xsh, domid); ++ if (path == NULL) { ++ fprintf(logfile, "xs_get_domain_path: error\n"); ++ goto out; ++ } ++ ++ pasprintf(&buf, "%s/%s", path, key); ++ rc = xs_write(xsh, XBT_NULL, buf, value, strlen(value)); ++ if (rc == 0) { ++ fprintf(logfile, "xs_write(%s, %s): write error\n", buf, key); ++ goto out; ++ } ++ ++ out: ++ free(path); ++ free(buf); ++ return rc; ++} ++ ++char *xenstore_read(const char *path) ++{ ++ char *value = NULL; ++ unsigned int len; ++ ++ if (xsh == NULL) ++ return NULL; ++ return xs_read(xsh, XBT_NULL, path, &len); ++} ++ ++int xenstore_write(const char *path, const char *val) ++{ ++ if (xsh == NULL) ++ return 1; ++ return xs_write(xsh, XBT_NULL, path, val, strlen(val)); ++} ++ ++ diff --git a/xen-3.4/battery-management b/xen-3.4/battery-management deleted file mode 100644 index b5e1a99..0000000 --- a/xen-3.4/battery-management +++ /dev/null @@ -1,272 +0,0 @@ -diff --git a/hw/battery_mgmt.c b/hw/battery_mgmt.c -index 3ddeb09..1c83b80 100644 ---- a/hw/battery_mgmt.c -+++ b/hw/battery_mgmt.c -@@ -29,7 +29,6 @@ - #include "hw.h" - #include "pc.h" - #include "qemu-xen.h" --#include "qemu-log.h" - #include "isa.h" //register_ioport_read declaration - #include "battery_mgmt.h" - -@@ -59,6 +58,7 @@ - - static enum POWER_MGMT_MODE power_mgmt_mode = PM_MODE_NONE; - static battery_state_info battery_info; -+extern FILE *logfile; - - int is_battery_pt_feasible(void) - { -@@ -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/battery_mgmt.h b/hw/battery_mgmt.h -index 4a4ac8e..19129b8 100644 ---- a/hw/battery_mgmt.h -+++ b/hw/battery_mgmt.h -@@ -42,4 +42,12 @@ typedef struct battery_state_info { - - void battery_mgmt_init(PCIDevice *device); - -+#ifndef CONFIG_NO_BATTERY_MGMT -+int is_battery_pt_feasible(void); -+void battery_mgmt_pt_mode_init(void); -+void get_battery_data_from_xenstore(void); -+void write_battery_data_to_port(void); -+void battery_mgmt_non_pt_mode_init(PCIDevice *device); -+#endif -+ - #endif -diff --git a/hw/pc.h b/hw/pc.h -index 8b71d48..a261c8a 100644 ---- a/hw/pc.h -+++ b/hw/pc.h -@@ -106,6 +106,10 @@ 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_sleep_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..c218782 100644 ---- a/hw/piix4acpi.c -+++ b/hw/piix4acpi.c -@@ -53,6 +53,11 @@ - - /* 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_SLEEP_BUTTON_BIT 0x0 -+#define ACPI_LID_STATE_BIT 0x17 - - typedef struct AcpiDeviceState AcpiDeviceState; - AcpiDeviceState *acpi_device_table; -@@ -192,8 +197,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 +213,56 @@ 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_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; -+ -+ 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) -diff --git a/qemu-xen.h b/qemu-xen.h -index c45bf9f..8c1debd 100644 ---- a/qemu-xen.h -+++ b/qemu-xen.h -@@ -122,8 +122,12 @@ void xenstore_dm_finished_startup(void); - int xenstore_vm_write(int domid, const char *key, const char *val); - 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); -+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_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 99b31fd..6f5b073 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" - -@@ -991,6 +992,25 @@ void xenstore_process_event(void *opaque) - goto out; - } - -+ 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], "slpbuttonpressedevt")) { -+ acpi_sleep_button_pressed(); -+ } -+ -+ if (!strcmp(vec[XS_WATCH_TOKEN], "lidstatechangeevt")) { -+ acpi_lid_state_changed(); -+ goto out; -+ } -+ - if (strncmp(vec[XS_WATCH_TOKEN], "hd", 2) || - strlen(vec[XS_WATCH_TOKEN]) != 3) - goto out; -@@ -1373,6 +1393,20 @@ static char *xenstore_extended_power_mgmt_read(const char *key, unsigned int *le - return value; - } - -+int xenstore_extended_power_mgmt_read_int(const char *key, int default_value) -+{ -+ int value = default_value; -+ char *buffer; -+ -+ buffer = xenstore_extended_power_mgmt_read(key, NULL); -+ if ( buffer == NULL ) -+ return value; -+ -+ value = strtoull(buffer, NULL, 10); -+ free(buffer); -+ return value; -+} -+ - static int xenstore_extended_power_mgmt_write(const char *key, const char *value) - { - int ret; -@@ -1425,6 +1459,24 @@ int xenstore_refresh_battery_status(void) - return xenstore_extended_power_mgmt_event_trigger("refreshbatterystatus", "1"); - } - -+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"); -+ xs_watch(xsh, "/pm/events/sleepbuttonpressed", "slpbuttonpressedevt"); -+} -+ -+int xenstore_read_ac_adapter_state(void) -+{ -+ return xenstore_extended_power_mgmt_read_int("ac_adapter", 1); -+} -+ -+int xenstore_read_lid_state(void) -+{ -+ return xenstore_extended_power_mgmt_read_int("lid_state", 1); -+} -+ - /* - * Create a store entry for a device (e.g., monitor, serial/parallel lines). - * The entry is /tty and the value is the name diff --git a/xen-3.4/disable-aio b/xen-3.4/disable-aio deleted file mode 100644 index b6c874e..0000000 --- a/xen-3.4/disable-aio +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/xen-setup b/xen-setup -index 24defda..84f2936 100755 ---- a/xen-setup -+++ b/xen-setup -@@ -9,7 +9,7 @@ rm -f config-host.mak - - if test -f config-host.h; then mv config-host.h config-host.h~; fi - --./configure --disable-gfx-check --disable-curses --disable-slirp --disable-vnc-tls --disable-sdl "$@" --prefix=/usr -+./configure --disable-gfx-check --disable-curses --disable-slirp --disable-vnc-tls --disable-sdl --disable-aio "$@" --prefix=/usr - - target=i386-dm - diff --git a/xen-3.4/dm-ready b/xen-3.4/dm-ready deleted file mode 100644 index 2a9fb8c..0000000 --- a/xen-3.4/dm-ready +++ /dev/null @@ -1,55 +0,0 @@ -diff --git a/qemu-xen.h b/qemu-xen.h -index 434d7db..3dc4518 100644 ---- a/qemu-xen.h -+++ b/qemu-xen.h -@@ -86,6 +86,7 @@ void xenstore_dom_chmod(int domid, const char *key, const char *perms); - char *xenstore_read(const char *path); - int xenstore_write(const char *path, const char *val); - -+void xenstore_dm_finished_startup(void); - - /* `danger' means that this parameter, variable or function refers to - * an area of xenstore which is writeable by the guest and thus must -diff --git a/vl.c b/vl.c -index 5801e42..c31e0a1 100644 ---- a/vl.c -+++ b/vl.c -@@ -5966,6 +5966,8 @@ int main(int argc, char **argv, char **envp) - close(fd); - } - -+ xenstore_dm_finished_startup(); -+ - main_loop(); - quit_timers(); - net_cleanup(); -diff --git a/xenstore.c b/xenstore.c -index 6448416..6834cce 100644 ---- a/xenstore.c -+++ b/xenstore.c -@@ -1609,3 +1609,25 @@ int xenstore_write(const char *path, const char *val) - } - - -+/* Advertise through xenstore that the device model is up and the -+ domain can be started. */ -+void xenstore_dm_finished_startup(void) -+{ -+ char *path; -+ char *buf = NULL; -+ -+ path = xs_get_domain_path(xsh, domid); -+ if (!path) { -+ fprintf(logfile, "xs_get_domain_path() failed.\n"); -+ goto out; -+ } -+ if (pasprintf(&buf, "%s/device-misc/dm-ready", path) == -1) { -+ fprintf(logfile, "pasprintf failed to get path.\n"); -+ goto out; -+ } -+ if (xs_write(xsh, XBT_NULL, buf, "1", 1) == 0) -+ fprintf(logfile, "xs_write() dm-ready failed\n"); -+ out: -+ free(buf); -+ free(path); -+} diff --git a/xen-3.4/dom0-driver b/xen-3.4/dom0-driver deleted file mode 100644 index daaa97c..0000000 --- a/xen-3.4/dom0-driver +++ /dev/null @@ -1,1415 +0,0 @@ -diff --git a/console.h b/console.h -index 14b42f3..97214c0 100644 ---- a/console.h -+++ b/console.h -@@ -341,4 +341,19 @@ const char *readline_get_history(unsigned int index); - void readline_start(const char *prompt, int is_password, - ReadLineFunc *readline_func, void *opaque); - -+/* get_time */ -+char *get_time(void); -+ -+/* dom0_driver.c */ -+void dom0_driver_init(const char *position); -+ -+/* hid_linux.c */ -+void hid_linux_init(void); -+int hid_linux_grab_keyboard(int grab); -+int hid_linux_grab_mouse(int grab); -+void hid_linux_secure_keyboard(void (*)(int)); -+void hid_linux_add_binding(const int *, void (*)(void*), void *); -+void hid_linux_reset_keyboard(void); -+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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 -+++ b/qemu-xen.h -@@ -107,7 +107,13 @@ int xenstore_write(const char *path, const char *val); - - void xenstore_dm_finished_startup(void); - -- /* `danger' means that this parameter, variable or function refers to -+char *xenstore_read_dom0_driver(const char *key); -+int xenstore_write_dom0_driver(const char *key, const char *str); -+int xenstore_watch_dom0_driver(const char *key, xenstore_callback fptr, void *opaque); -+ -+int *xenstore_get_domids(int *len); -+ -+/* `danger' means that this parameter, variable or function refers to - * an area of xenstore which is writeable by the guest and thus must - * not be trusted by qemu code. For variables containing xenstore - * paths, `danger' can mean that both the path refers to a -diff --git a/vl.c b/vl.c -index e519705..0ffe1ec 100644 ---- a/vl.c -+++ b/vl.c -@@ -234,6 +234,7 @@ CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES]; - int win2k_install_hack = 0; - int rtc_td_hack = 0; - int vga_passthrough = 0; -+const char *dom0_input = NULL; - #endif - int usb_enabled = 0; - int smp_cpus = 1; -@@ -278,6 +279,20 @@ uint8_t qemu_uuid[16]; - - #include "xen-vl-extra.c" - -+char *get_time(void) -+{ -+ -+ char buff[128]; -+ char *str; -+ struct timeval tv; -+ -+ gettimeofday(&tv, NULL); -+ str = malloc(256); -+ strftime(buff, 128, "%T", localtime(&tv.tv_sec)); -+ sprintf(str, "%s:%06d", buff, (int)tv.tv_usec); -+ return str; -+} -+ - /***********************************************************/ - /* x86 ISA bus support */ - -@@ -4277,6 +4292,7 @@ enum { - QEMU_OPTION_acpi, - QEMU_OPTION_vcpus, - QEMU_OPTION_vga_passthrough, -+ QEMU_OPTION_dom0_input, - - /* Debug/Expert options: */ - QEMU_OPTION_serial, -@@ -4451,6 +4467,7 @@ static const QEMUOption qemu_options[] = { - { "vncunused", 0, QEMU_OPTION_vncunused }, - { "vcpus", HAS_ARG, QEMU_OPTION_vcpus }, - { "vga-passthrough", 0, QEMU_OPTION_vga_passthrough }, -+ { "dom0-input", 1, QEMU_OPTION_dom0_input }, - #if defined(CONFIG_XEN) && !defined(CONFIG_DM) - { "xen-domid", HAS_ARG, QEMU_OPTION_xen_domid }, - { "xen-create", 0, QEMU_OPTION_xen_create }, -@@ -5287,6 +5304,9 @@ int main(int argc, char **argv, char **envp) - case QEMU_OPTION_vga_passthrough: - vga_passthrough = 1; - break; -+ case QEMU_OPTION_dom0_input: -+ dom0_input = optarg; -+ break; - case QEMU_OPTION_direct_pci: - direct_pci = optarg; - break; -@@ -6053,6 +6073,9 @@ int main(int argc, char **argv, char **envp) - close(fd); - } - -+ if (dom0_input) -+ dom0_driver_init(dom0_input); -+ - xenstore_dm_finished_startup(); - - main_loop(); -diff --git a/xen-hooks.mak b/xen-hooks.mak -index 7c94718..f243df1 100644 ---- a/xen-hooks.mak -+++ b/xen-hooks.mak -@@ -37,6 +37,8 @@ OBJS += helper2.o - OBJS += battery_mgmt.o - OBJS += xen_acpi_wmi.o - OBJS += thermal_mgmt.o -+OBJS += dom0_driver.o -+OBJS += hid-linux.o - - ifdef CONFIG_STUBDOM - CPPFLAGS += $(TARGET_CPPFLAGS) -DNEED_CPU_H \ -diff --git a/xenstore.c b/xenstore.c -index 01afcf0..20ca8cf 100644 ---- a/xenstore.c -+++ b/xenstore.c -@@ -1727,3 +1727,63 @@ void xenstore_dm_finished_startup(void) - free(buf); - free(path); - } -+ -+char *xenstore_read_dom0_driver(const char *key) -+{ -+ const char *path = "/local/domain/0/dom0_driver"; -+ char *buf = NULL; -+ int len = 0; -+ char *val = NULL; -+ -+ if (pasprintf(&buf, "%s/%s", path, key) == -1) -+ return NULL; -+ val = xs_read(xsh, XBT_NULL, buf, &len); -+ free(buf); -+ return val; -+} -+ -+int xenstore_watch_dom0_driver(const char *key, xenstore_callback fptr, void *opaque) -+{ -+ const char *path = "/local/domain/0/dom0_driver"; -+ char *buf = NULL; -+ int ret = 0; -+ -+ if (pasprintf(&buf, "%s/%s", path, key) == -1) -+ return 0; -+ xenstore_watch_new_callback(buf, fptr, opaque); -+ free(buf); -+ return ret; -+} -+ -+int xenstore_write_dom0_driver(const char *key, const char *str) -+{ -+ const char *path = "/local/domain/0/dom0_driver"; -+ char *buf = NULL; -+ int len = 0; -+ int ret = 0; -+ -+ if (pasprintf(&buf, "%s/%s", path, key) == -1) -+ return 0; -+ ret = xs_write(xsh, XBT_NULL, buf, str, strlen(str)); -+ free(buf); -+ return ret; -+} -+ -+int *xenstore_get_domids(int *len) -+{ -+ int *tab = NULL; -+ char **e; -+ -+ e = xs_directory(xsh, XBT_NULL, "/local/domain", len); -+ if (e == NULL) -+ { -+ len = 0; -+ return NULL; -+ } -+ -+ tab = malloc(*len * sizeof (int)); -+ for (int i = 0; i < *len; i++) -+ tab[i] = strtol(e[i], NULL, 10); -+ return tab; -+} -+ diff --git a/xen-3.4/fix-build-warnings b/xen-3.4/fix-build-warnings deleted file mode 100644 index 9b2d41c..0000000 --- a/xen-3.4/fix-build-warnings +++ /dev/null @@ -1,19 +0,0 @@ -diff -Nur a/hw/pci.h b/hw/pci.h ---- a/hw/pci.h 2009-05-13 14:31:58.000000000 -0400 -+++ b/hw/pci.h 2009-05-13 16:51:34.000000000 -0400 -@@ -168,9 +168,13 @@ - #define PCI_STATUS_RESERVED1 0x007 - #define PCI_STATUS_INT_STATUS 0x008 - #define PCI_STATUS_CAPABILITIES 0x010 --#define PCI_STATUS_66MHZ 0x020 -+#ifndef PCI_STATUS_66MHZ -+#define PCI_STATUS_66MHZ 0x020 -+#endif - #define PCI_STATUS_RESERVED2 0x040 --#define PCI_STATUS_FAST_BACK 0x080 -+#ifndef PCI_STATUS_FAST_BACK -+#define PCI_STATUS_FAST_BACK 0x080 -+#endif - #define PCI_STATUS_DEVSEL 0x600 - - #define PCI_STATUS_RESERVED_MASK_LO (PCI_STATUS_RESERVED1 | \ diff --git a/xen-3.4/intel b/xen-3.4/intel deleted file mode 100644 index 3520c50..0000000 --- a/xen-3.4/intel +++ /dev/null @@ -1,605 +0,0 @@ -diff --git a/console.h b/console.h -index 97214c0..4c51c50 100644 ---- a/console.h -+++ b/console.h -@@ -290,6 +290,9 @@ void vga_hw_update(void); - void vga_hw_invalidate(void); - void vga_hw_screen_dump(const char *filename); - -+void unset_vga_acc(void); -+void set_vga_acc(void); -+ - int is_graphic_console(void); - int is_fixedsize_console(void); - CharDriverState *text_console_init(const char *p); -@@ -356,4 +359,8 @@ void hid_linux_add_binding(const int *, void (*)(void*), void *); - void hid_linux_reset_keyboard(void); - void hid_linux_probe(int grab); - -+/* intel.c */ -+int intel_enter(void); -+int intel_leave(void); -+void intel_display_init(DisplayState *ds); - #endif -diff --git a/hw/vga.c b/hw/vga.c -index 90bd544..b0f9f9c 100644 ---- a/hw/vga.c -+++ b/hw/vga.c -@@ -161,6 +161,18 @@ static uint8_t expand4to8[16]; - static void vga_bios_init(VGAState *s); - static void vga_screen_dump(void *opaque, const char *filename); - -+static VGAState *xen_vga_state; -+ -+void set_vga_acc(void) -+{ -+ set_vram_mapping(xen_vga_state, xen_vga_state->lfb_addr, xen_vga_state->lfb_end); -+} -+ -+void unset_vga_acc(void) -+{ -+ unset_vram_mapping(xen_vga_state); -+} -+ - static void vga_dumb_update_retrace_info(VGAState *s) - { - (void) s; -@@ -2473,8 +2485,6 @@ static void vga_bios_init(VGAState *s) - } - - --static VGAState *xen_vga_state; -- - /* 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 -+++ b/vl.c -@@ -235,6 +235,7 @@ int win2k_install_hack = 0; - int rtc_td_hack = 0; - int vga_passthrough = 0; - const char *dom0_input = NULL; -+int intel = 0; - #endif - int usb_enabled = 0; - int smp_cpus = 1; -@@ -4293,6 +4294,7 @@ enum { - QEMU_OPTION_vcpus, - QEMU_OPTION_vga_passthrough, - QEMU_OPTION_dom0_input, -+ QEMU_OPTION_intel, - - /* Debug/Expert options: */ - QEMU_OPTION_serial, -@@ -4468,6 +4470,7 @@ static const QEMUOption qemu_options[] = { - { "vcpus", HAS_ARG, QEMU_OPTION_vcpus }, - { "vga-passthrough", 0, QEMU_OPTION_vga_passthrough }, - { "dom0-input", 1, QEMU_OPTION_dom0_input }, -+ { "intel", 0, QEMU_OPTION_dom0_input }, - #if defined(CONFIG_XEN) && !defined(CONFIG_DM) - { "xen-domid", HAS_ARG, QEMU_OPTION_xen_domid }, - { "xen-create", 0, QEMU_OPTION_xen_create }, -@@ -5307,6 +5310,9 @@ int main(int argc, char **argv, char **envp) - case QEMU_OPTION_dom0_input: - dom0_input = optarg; - break; -+ case QEMU_OPTION_intel: -+ intel = 1; -+ break; - case QEMU_OPTION_direct_pci: - direct_pci = optarg; - break; -diff --git a/xen-hooks.mak b/xen-hooks.mak -index f243df1..55dd477 100644 ---- a/xen-hooks.mak -+++ b/xen-hooks.mak -@@ -39,6 +39,7 @@ OBJS += xen_acpi_wmi.o - OBJS += thermal_mgmt.o - OBJS += dom0_driver.o - OBJS += hid-linux.o -+OBJS += intel.o - - ifdef CONFIG_STUBDOM - CPPFLAGS += $(TARGET_CPPFLAGS) -DNEED_CPU_H \ diff --git a/xen-3.4/ioemu-compil b/xen-3.4/ioemu-compil deleted file mode 100644 index 477838b..0000000 --- a/xen-3.4/ioemu-compil +++ /dev/null @@ -1,45 +0,0 @@ -diff --git a/xen-hooks.mak b/xen-hooks.mak -index c6b4f8c..d2f09fb 100644 ---- a/xen-hooks.mak -+++ b/xen-hooks.mak -@@ -52,7 +52,7 @@ endif - ifdef CONFIG_STUBDOM - CONFIG_PASSTHROUGH=1 - else -- ifeq (,$(wildcard /usr/include/pci)) -+ ifeq (,$(wildcard $(PCI_PREFIX_DIR)/usr/include/pci)) - $(warning === pciutils-dev package not found - missing /usr/include/pci) - $(warning === PCI passthrough capability has been disabled) - else -@@ -62,6 +62,9 @@ endif - - ifdef CONFIG_PASSTHROUGH - OBJS+= pass-through.o pt-msi.o -+ifdef PCI_PREFIX_DIR -+LIBS += -L$(PCI_PREFIX_DIR)/usr/lib -+endif - LIBS += -lpci - CFLAGS += -DCONFIG_PASSTHROUGH - $(info === PCI passthrough capability has been enabled ===) -diff --git a/xen-setup b/xen-setup -index 8ca0019..24defda 100755 ---- a/xen-setup -+++ b/xen-setup -@@ -9,7 +9,7 @@ rm -f config-host.mak - - if test -f config-host.h; then mv config-host.h config-host.h~; fi - --./configure --disable-gfx-check --disable-curses --disable-slirp "$@" --prefix=/usr -+./configure --disable-gfx-check --disable-curses --disable-slirp --disable-vnc-tls --disable-sdl "$@" --prefix=/usr - - target=i386-dm - -@@ -17,6 +17,8 @@ if [ "x$XEN_ROOT" != x ]; then - echo "XEN_ROOT=$XEN_ROOT" >>config-host.mak - fi - -+echo "PCI_PREFIX_DIR=${STAGING_ROOT}" >>config-host.mak -+ - ln -sf ../Makefile.target $target/Makefile - ln -sf ../xen-config.mak $target/config.mak - cat xen-config-host.mak >>config-host.mak diff --git a/xen-3.4/oem-features b/xen-3.4/oem-features deleted file mode 100644 index 7110652..0000000 --- a/xen-3.4/oem-features +++ /dev/null @@ -1,973 +0,0 @@ -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 -+++ b/hw/pc.h -@@ -111,6 +111,8 @@ void acpi_power_button_pressed(void); - void acpi_sleep_button_pressed(void); - void acpi_lid_state_changed(void); - -+void acpi_oem_event(void); -+ - /* hpet.c */ - extern int no_hpet; - -diff --git a/hw/piix4acpi.c b/hw/piix4acpi.c -index c218782..cf214a4 100644 ---- a/hw/piix4acpi.c -+++ b/hw/piix4acpi.c -@@ -29,6 +29,7 @@ - #include "sysemu.h" - #include "qemu-xen.h" - #include "battery_mgmt.h" -+#include "xen_acpi_wmi.h" - - #include - #include -@@ -58,6 +59,7 @@ - #define ACPI_POWER_BUTTON_BIT 0x1 - #define ACPI_SLEEP_BUTTON_BIT 0x0 - #define ACPI_LID_STATE_BIT 0x17 -+#define ACPI_OEM_EVENT_BIT 0x18 - - typedef struct AcpiDeviceState AcpiDeviceState; - AcpiDeviceState *acpi_device_table; -@@ -195,6 +197,7 @@ static void acpi_map(PCIDevice *pci_dev, int region_num, - register_ioport_read(addr + 4, 2, 2, acpiPm1Control_readw, d); - - battery_mgmt_init(pci_dev); -+ xen_acpi_wmi_init(pci_dev); - } - - static inline int test_bit(uint8_t *map, int bit) -@@ -261,6 +262,19 @@ void acpi_lid_state_changed(void) - } - } - -+void acpi_oem_event(void) -+{ -+ GPEState *s = &gpe_state; -+ -+ if ( !test_bit(&s->gpe0_sts[0], ACPI_OEM_EVENT_BIT) && -+ test_bit(&s->gpe0_en[0], ACPI_OEM_EVENT_BIT) ) { -+ set_bit(&s->gpe0_sts[0], ACPI_OEM_EVENT_BIT); -+ s->sci_asserted = 1; -+ fprintf(logfile, "Raising oem event irq\n"); -+ qemu_irq_raise(sci_irq); -+ } -+} -+ - #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 -+ -+#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 -+++ b/qemu-xen.h -@@ -128,6 +128,7 @@ 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); -+void xenstore_register_for_oem_events(void); - int xenstore_pv_driver_build_blacklisted(uint16_t product_number, - uint32_t build_nr); - -diff --git a/xen-hooks.mak b/xen-hooks.mak -index d2f09fb..03d670e 100644 ---- a/xen-hooks.mak -+++ b/xen-hooks.mak -@@ -35,6 +35,7 @@ OBJS += exec-dm.o - 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 --git a/xenstore.c b/xenstore.c -index 6f5b073..7cd4d54 100644 ---- a/xenstore.c -+++ b/xenstore.c -@@ -1011,6 +1011,11 @@ void xenstore_process_event(void *opaque) - goto out; - } - -+ if (!strcmp(vec[XS_WATCH_TOKEN], "oemevt")) { -+ acpi_oem_event(); -+ goto out; -+ } -+ - if (strncmp(vec[XS_WATCH_TOKEN], "hd", 2) || - strlen(vec[XS_WATCH_TOKEN]) != 3) - goto out; -@@ -1467,6 +1472,11 @@ void xenstore_register_for_pm_events(void) - xs_watch(xsh, "/pm/events/sleepbuttonpressed", "slpbuttonpressedevt"); - } - -+void xenstore_register_for_oem_events(void) -+{ -+ xs_watch(xsh, "/oem/event", "oemevt"); -+} -+ - int xenstore_read_ac_adapter_state(void) - { - return xenstore_extended_power_mgmt_read_int("ac_adapter", 1); diff --git a/xen-3.4/series b/xen-3.4/series deleted file mode 100644 index 5f501b9..0000000 --- a/xen-3.4/series +++ /dev/null @@ -1,15 +0,0 @@ -ioemu-compil -xenstore-watch-callbacks -dm-ready - -battery-management -oem-features -thermal-management -fix-build-warnings - - -vga-passthrough -dom0-driver -intel -use-vga-cmdline -disable-aio diff --git a/xen-3.4/status b/xen-3.4/status deleted file mode 100644 index e69de29..0000000 diff --git a/xen-3.4/thermal-management b/xen-3.4/thermal-management deleted file mode 100644 index 47e74bc..0000000 --- a/xen-3.4/thermal-management +++ /dev/null @@ -1,208 +0,0 @@ -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_acpi_wmi.h" -+#include "thermal_mgmt.h" - - #include - #include -@@ -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); -+ thermal_mgmt_init(pci_dev); - } - - static inline int test_bit(uint8_t *map, int bit) -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 -+ * -+ * 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 -+ */ -+ -+/* Implementation Notes: Following provides a minimal thermal zone implementation for -+ * HVM guest. The vACPI layer exposes a single thermal zone with critical and current -+ * temperature objects which when invoked relies on the below to return back the critical -+ * and current temperature provided by the underlying firmware. -+ */ -+ -+#include "hw.h" -+#include "pc.h" -+#include "qemu-xen.h" -+#include "isa.h" -+#include "thermal_mgmt.h" -+ -+#ifndef CONFIG_NO_THERMAL_MGMT -+ -+/* #define THERMAL_MGMT_DBG */ -+ -+extern FILE *logfile; -+ -+static uint32_t thermal_port_1_readw(void *opaque, uint32_t addr) -+{ -+ int current_temp; -+ -+ xenstore_refresh_thermal_info(); -+ current_temp = xenstore_read_current_temperature(); -+#ifdef THERMAL_MGMT_DBG -+ fprintf(logfile, "Current temperature - %d\n", current_temp); -+#endif -+ return current_temp; -+} -+ -+static uint32_t thermal_port_2_readw(void *opaque, uint32_t addr) -+{ -+ int critical_temp; -+ -+ xenstore_refresh_thermal_info(); -+ critical_temp = xenstore_read_critical_temperature(); -+#ifdef THERMAL_MGMT_DBG -+ fprintf(logfile, "Critical trip point temperature - %d\n", critical_temp); -+#endif -+ return critical_temp; -+} -+ -+void thermal_mgmt_init(PCIDevice *device) -+{ -+#ifdef THERMAL_MGMT_DBG -+ fprintf(logfile, "In thermal management init\n"); -+#endif -+ -+ register_ioport_read(THERMAL_PORT_1, 1, 2, thermal_port_1_readw, device); -+ register_ioport_read(THERMAL_PORT_2, 1, 2, thermal_port_2_readw, device); -+} -+ -+#else -+ -+void thermal_mgmt_init(PCIDevice *device) { } -+ -+#endif -+ -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 -+ * -+ * 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 _THERMAL_MGMT_H -+#define _THERMAL_MGMT_H -+ -+#ifdef CONFIG_STUBDOM -+#define CONFIG_NO_THERMAL_MGMT -+#endif -+ -+#define THERMAL_PORT_1 0x90 -+#define THERMAL_PORT_2 0x92 -+ -+void thermal_mgmt_init(PCIDevice *device); -+ -+#endif -+ -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); -+int xenstore_refresh_thermal_info(void); - void xenstore_register_for_pm_events(void); - int xenstore_read_ac_adapter_state(void); - int xenstore_read_lid_state(void); -+int xenstore_read_current_temperature(void); -+int xenstore_read_critical_temperature(void); - void xenstore_register_for_oem_events(void); - int xenstore_pv_driver_build_blacklisted(uint16_t product_number, - uint32_t build_nr); -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 -+OBJS += thermal_mgmt.o - - ifdef CONFIG_STUBDOM - CPPFLAGS += $(TARGET_CPPFLAGS) -DNEED_CPU_H \ -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"); - } - -+int xenstore_refresh_thermal_info(void) -+{ -+ return xenstore_extended_power_mgmt_event_trigger("refreshthermalinfo", "1"); -+} -+ - 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); - } - -+int xenstore_read_current_temperature(void) -+{ -+ return xenstore_extended_power_mgmt_read_int("current_temperature", 0); -+} -+ -+int xenstore_read_critical_temperature(void) -+{ -+ 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 /tty and the value is the name diff --git a/xen-3.4/use-vga-cmdline b/xen-3.4/use-vga-cmdline deleted file mode 100644 index 4006998..0000000 --- a/xen-3.4/use-vga-cmdline +++ /dev/null @@ -1,49 +0,0 @@ -diff --git a/vl.c b/vl.c -index ae32f82..05d12ae 100644 ---- a/vl.c -+++ b/vl.c -@@ -4598,24 +4598,20 @@ static void select_soundhw (const char *optarg) - static void select_vgahw (const char *p) - { - const char *opts; -+ std_vga_enabled = 0; -+ cirrus_vga_enabled = 0; -+ vmsvga_enabled = 0; - -- if (strstart(p, "std", &opts)) { -+ if (strstart(p, "std", &opts)) - std_vga_enabled = 1; -- cirrus_vga_enabled = 0; -- vmsvga_enabled = 0; -- } else if (strstart(p, "cirrus", &opts)) { -+ else if (strstart(p, "cirrus", &opts)) - cirrus_vga_enabled = 1; -- std_vga_enabled = 0; -- vmsvga_enabled = 0; -- } else if (strstart(p, "vmware", &opts)) { -- cirrus_vga_enabled = 0; -- std_vga_enabled = 0; -+ else if (strstart(p, "vmware", &opts)) - vmsvga_enabled = 1; -- } else if (strstart(p, "none", &opts)) { -- cirrus_vga_enabled = 0; -- std_vga_enabled = 0; -- vmsvga_enabled = 0; -- } else { -+ else if (strstart(p, "passthrough", &opts)) -+ vga_passthrough = 1; -+ else if (!strstart(p, "none", &opts)) -+ { - invalid_vga: - fprintf(stderr, "Unknown vga type: %s\n", p); - exit(1); -@@ -5272,6 +5268,9 @@ int main(int argc, char **argv, char **envp) - break; - case QEMU_OPTION_vga_passthrough: - vga_passthrough = 1; -+ std_vga_enabled = 0; -+ cirrus_vga_enabled = 0; -+ vmsvga_enabled = 0; - break; - case QEMU_OPTION_dom0_input: - dom0_input = optarg; diff --git a/xen-3.4/vga-passthrough b/xen-3.4/vga-passthrough deleted file mode 100644 index d2adba9..0000000 --- a/xen-3.4/vga-passthrough +++ /dev/null @@ -1,235 +0,0 @@ -diff --git a/hw/pass-through.c b/hw/pass-through.c -index 6a53137..3420e95 100644 ---- a/hw/pass-through.c -+++ b/hw/pass-through.c -@@ -90,6 +90,8 @@ - #include "qemu-xen.h" - #include - -+extern int vga_passthrough; -+ - struct php_dev { - struct pt_dev *pt_dev; - uint8_t valid; -@@ -1573,10 +1575,11 @@ static int pt_dev_is_virtfn(struct pci_dev *dev) - - static int pt_register_regions(struct pt_dev *assigned_device) - { -- int i = 0; -+ int i = 0, ret = 0; - uint32_t bar_data = 0; - struct pci_dev *pci_dev = assigned_device->pci_dev; - PCIDevice *d = &assigned_device->dev; -+ uint16_t vendor_id, class; - - /* Register PIO/MMIO BARs */ - for ( i = 0; i < PCI_BAR_ENTRIES; i++ ) -@@ -1632,6 +1635,28 @@ static int pt_register_regions(struct pt_dev *assigned_device) - (uint32_t)(pci_dev->rom_size), (uint32_t)(pci_dev->rom_base_addr)); - } - -+ /* Map legacy ioport and iomem, for specific devices */ -+ vendor_id = pci_read_word(pci_dev, 0x00); -+ class = pci_read_word(pci_dev, 0x0a); -+ -+ PT_LOG("Real device vendor_id=0x%x class=0x%x\n", vendor_id, class); -+ if ( vga_passthrough && class == 0x0300 ) -+ { -+ PT_LOG("add an intel graphic card\n"); -+ -+ ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3B0, 0x3B0, 0xb, -+ DPCI_ADD_MAPPING); -+ ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3C0, 0x3C0, 32, -+ DPCI_ADD_MAPPING); -+ ret |= xc_domain_memory_mapping(xc_handle, domid, 0xa0, 0xa0, 32, -+ DPCI_ADD_MAPPING); -+ if ( ret != 0 ) -+ { -+ PT_LOG("legacy mapping failed !\n"); -+ return ret; -+ } -+ } -+ - return 0; - } - -@@ -1640,6 +1665,7 @@ static void pt_unregister_regions(struct pt_dev *assigned_device) - int i, type, ret; - uint32_t e_size; - PCIDevice *d = (PCIDevice*)assigned_device; -+ uint16_t class, vendor_id; - - for ( i = 0; i < PCI_NUM_REGIONS; i++ ) - { -@@ -1681,6 +1707,26 @@ static void pt_unregister_regions(struct pt_dev *assigned_device) - - } - -+ /* unmap legacy ioport and iomem, for specific devices */ -+ vendor_id = pci_read_word(assigned_device->pci_dev, 0x00); -+ class = pci_read_word(assigned_device->pci_dev, 0x0a); -+ -+ PT_LOG("Real device vendor_id=0x%x class=0x%x\n", vendor_id, class); -+ if ( vga_passthrough && class == 0x0300 ) -+ { -+ PT_LOG("remove an intel graphic card\n"); -+ -+ ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3B0, 0x3B0, 0xb, -+ DPCI_REMOVE_MAPPING); -+ ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3C0, 0x3C0, 32, -+ DPCI_REMOVE_MAPPING); -+ ret |= xc_domain_memory_mapping(xc_handle, domid, 0xa0, 0xa0, 32, -+ DPCI_REMOVE_MAPPING); -+ if ( ret != 0 ) -+ { -+ PT_LOG("legacy unmapping failed !\n"); -+ } -+ } - } - - static uint8_t find_cap_offset(struct pci_dev *pci_dev, uint8_t cap) -@@ -4084,3 +4130,41 @@ err: - return status; - } - -+u8 pt_pci_host_read_byte(int bus, int dev, int fn, u32 addr) -+{ -+ struct pci_dev* pci_dev; -+ u8 val; -+ -+ pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn); -+ if (!pci_dev) -+ return 0; -+ val = pci_read_byte(pci_dev, addr); -+ pci_free_dev(pci_dev); -+ return val; -+} -+ -+u16 pt_pci_host_read_word(int bus, int dev, int fn, u32 addr) -+{ -+ struct pci_dev* pci_dev; -+ u16 val; -+ -+ pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn); -+ if (!pci_dev) -+ return 0; -+ val = pci_read_word(pci_dev, addr); -+ pci_free_dev(pci_dev); -+ return val; -+} -+ -+u32 pt_pci_host_read_long(int bus, int dev, int fn, u32 addr) -+{ -+ struct pci_dev* pci_dev; -+ u32 val; -+ -+ pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn); -+ if (!pci_dev) -+ return 0; -+ val = pci_read_long(pci_dev, addr); -+ pci_free_dev(pci_dev); -+ return val; -+} -diff --git a/hw/pass-through.h b/hw/pass-through.h -index a503e80..1752e8d 100644 ---- a/hw/pass-through.h -+++ b/hw/pass-through.h -@@ -392,5 +392,9 @@ static inline pciaddr_t pt_pci_base_addr(pciaddr_t base) - return base & PCI_ADDR_MEM_MASK; - } - -+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); -+ - #endif /* __PASSTHROUGH_H__ */ - -diff --git a/hw/pci.c b/hw/pci.c -index d7c516e..b2f4d43 100644 ---- a/hw/pci.c -+++ b/hw/pci.c -@@ -28,11 +28,14 @@ - #include "virtio-net.h" - #include "sysemu.h" - -+#include "pass-through.h" - #include "exec-all.h" - #include "qemu-xen.h" - - //#define DEBUG_PCI - -+extern int vga_passthrough; -+ - struct PCIBus { - int bus_num; - int devfn_min; -@@ -611,7 +614,30 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len) - goto the_end; - } - config_addr = addr & 0xff; -- val = pci_dev->config_read(pci_dev, config_addr, len); -+ if (vga_passthrough && pci_dev->devfn == 0x00) //Host Bridge -+ { -+ val = pci_dev->config_read(pci_dev, config_addr, len); -+ -+ if (config_addr == 0x52) // GMCH -+ val = pt_pci_host_read_word(0, 0, 0, 0x52); -+ if (config_addr == 0x02) // Device ID -+ { -+ if (len == 2) -+ val = pt_pci_host_read_word(0, 0, 0, 0x02); -+ } -+ if (config_addr == 0x0) -+ { -+ if (len == 2) -+ val = pt_pci_host_read_word(0, 0, 0, 0x00); -+ else if (len == 4) -+ val = pt_pci_host_read_long(0, 0, 0, 0x00); -+ } -+ } -+ else if (vga_passthrough && pci_dev->devfn == 0x10 && // intel graphic card -+ config_addr == 0xfc) // OpRegion address -+ val = 0; // force to fall back to SMI mode -+ else -+ val = pci_dev->config_read(pci_dev, config_addr, len); - #if defined(DEBUG_PCI) - printf("pci_config_read: %s: addr=%02x val=%08x len=%d\n", - pci_dev->name, config_addr, val, len); -diff --git a/vl.c b/vl.c -index b273c75..e519705 100644 ---- a/vl.c -+++ b/vl.c -@@ -233,6 +233,7 @@ CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES]; - #ifdef TARGET_I386 - int win2k_install_hack = 0; - int rtc_td_hack = 0; -+int vga_passthrough = 0; - #endif - int usb_enabled = 0; - int smp_cpus = 1; -@@ -4275,6 +4276,7 @@ enum { - QEMU_OPTION_domainname, - QEMU_OPTION_acpi, - QEMU_OPTION_vcpus, -+ QEMU_OPTION_vga_passthrough, - - /* Debug/Expert options: */ - QEMU_OPTION_serial, -@@ -4448,6 +4450,7 @@ static const QEMUOption qemu_options[] = { - { "pciemulation", HAS_ARG, QEMU_OPTION_pci_emulation }, - { "vncunused", 0, QEMU_OPTION_vncunused }, - { "vcpus", HAS_ARG, QEMU_OPTION_vcpus }, -+ { "vga-passthrough", 0, QEMU_OPTION_vga_passthrough }, - #if defined(CONFIG_XEN) && !defined(CONFIG_DM) - { "xen-domid", HAS_ARG, QEMU_OPTION_xen_domid }, - { "xen-create", 0, QEMU_OPTION_xen_create }, -@@ -5281,6 +5284,9 @@ int main(int argc, char **argv, char **envp) - case QEMU_OPTION_disable_opengl: - opengl_enabled = 0; - break; -+ case QEMU_OPTION_vga_passthrough: -+ vga_passthrough = 1; -+ break; - case QEMU_OPTION_direct_pci: - direct_pci = optarg; - break; diff --git a/xen-3.4/xenstore-watch-callbacks b/xen-3.4/xenstore-watch-callbacks deleted file mode 100644 index 916f5f4..0000000 --- a/xen-3.4/xenstore-watch-callbacks +++ /dev/null @@ -1,244 +0,0 @@ -Improved the way to do xenstore watchs. - -diff --git a/qemu-xen.h b/qemu-xen.h -index ec4cd94..9f7feda 100644 ---- a/qemu-xen.h -+++ b/qemu-xen.h -@@ -78,6 +78,19 @@ int xenstore_unsubscribe_from_hotplug_status(struct xs_handle *handle, - const char *inst, - const char *token); - -+typedef void (*xenstore_callback) (const char *path, void *opaque); -+int xenstore_watch_screenshot_node(DisplayState *ds); -+int xenstore_watch_new_callback(const char *path, xenstore_callback fptr, void *opaque); -+ -+char *xenstore_dom_read(int domid, const char *key, unsigned int *len); -+int xenstore_dom_write(int domid, const char *key, const char *value); -+void xenstore_dom_watch(int domid, const char *key, xenstore_callback ftp, void *opaque); -+void xenstore_dom_chmod(int domid, const char *key, const char *perms); -+ -+char *xenstore_read(const char *path); -+int xenstore_write(const char *path, const char *val); -+ -+ - /* `danger' means that this parameter, variable or function refers to - * an area of xenstore which is writeable by the guest and thus must - * not be trusted by qemu code. For variables containing xenstore -@@ -92,7 +105,7 @@ int xenstore_unsubscribe_from_hotplug_status(struct xs_handle *handle, - - int xenstore_vm_write(int domid, const char *key, const char *val); - char *xenstore_vm_read(int domid, const char *key, unsigned int *len); --char *xenstore_device_model_read(int domid, 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); - int xenstore_pv_driver_build_blacklisted(uint16_t product_number, -diff --git a/xenstore.c b/xenstore.c -index ef7b5f3..ea39dce 100644 ---- a/xenstore.c -+++ b/xenstore.c -@@ -37,6 +37,52 @@ static QEMUTimer *insert_timer = NULL; - #define UWAIT_MAX (30*1000000) /* thirty seconds */ - #define UWAIT (100000) /* 1/10th second */ - -+struct xenstore_watch_cb_t -+{ -+ char *path; -+ xenstore_callback cb; -+ void *opaque; -+}; -+ -+static struct xenstore_watch_cb_t *xenstore_watch_callbacks = NULL; -+ -+int xenstore_watch_new_callback(const char *path, -+ xenstore_callback fptr, -+ void *opaque) -+{ -+ int i = 0, ret = 0; -+ -+ ret = xs_watch(xsh, path, path); -+ if (ret == 0) -+ return 0; -+ -+ if (!xenstore_watch_callbacks) -+ { -+ xenstore_watch_callbacks = malloc(sizeof (struct xenstore_watch_cb_t)); -+ xenstore_watch_callbacks[0].path = NULL; -+ } -+ -+ while (xenstore_watch_callbacks[i].path) -+ { -+ if (!strcmp(xenstore_watch_callbacks[i].path, path)) -+ { -+ xenstore_watch_callbacks[i].cb = fptr; -+ xenstore_watch_callbacks[i].opaque = opaque; -+ return ret; -+ } -+ i++; -+ } -+ -+ xenstore_watch_callbacks = realloc(xenstore_watch_callbacks, -+ (i + 2) * sizeof (struct xenstore_watch_cb_t)); -+ xenstore_watch_callbacks[i].path = strdup(path); -+ xenstore_watch_callbacks[i].cb = fptr; -+ xenstore_watch_callbacks[i].opaque = opaque; -+ xenstore_watch_callbacks[i + 1].path = NULL; -+ return ret; -+} -+ -+ - static int pasprintf(char **buf, const char *fmt, ...) - { - va_list ap; -@@ -904,12 +950,18 @@ void xenstore_record_dm_state(const char *state) - void xenstore_process_event(void *opaque) - { - char **vec, *offset, *bpath = NULL, *buf = NULL, *drv = NULL, *image = NULL; -- unsigned int len, num, hd_index; -+ unsigned int len, num, hd_index, i; - - vec = xs_read_watch(xsh, &num); - if (!vec) - return; - -+ for (i = 0; xenstore_watch_callbacks && xenstore_watch_callbacks[i].path; i++) -+ if (xenstore_watch_callbacks[i].cb && -+ !strcmp(vec[XS_WATCH_TOKEN], xenstore_watch_callbacks[i].path)) -+ xenstore_watch_callbacks[i].cb(vec[XS_WATCH_TOKEN], -+ xenstore_watch_callbacks[i].opaque); -+ - if (!strcmp(vec[XS_WATCH_TOKEN], "logdirty")) { - xenstore_process_logdirty_event(); - goto out; -@@ -1272,7 +1324,7 @@ int xenstore_vm_write(int domid, const char *key, const char *value) - return rc; - } - --char *xenstore_device_model_read(int domid, char *key, unsigned int *len) -+char *xenstore_device_model_read(int domid, const char *key, unsigned int *len) - { - char *path = NULL, *value = NULL; - -@@ -1438,3 +1490,122 @@ void xenstore_store_serial_port_info(int i, CharDriverState *chr, - if (i == 0) /* serial 0 is also called the console */ - store_dev_info(devname, domid, chr, "/console"); - } -+ -+char *xenstore_dom_read(int domid, const char *key, unsigned int *len) -+{ -+ char *buf = NULL, *path = NULL, *value = NULL; -+ -+ if (xsh == NULL) -+ goto out; -+ -+ path = xs_get_domain_path(xsh, domid); -+ if (path == NULL) { -+ fprintf(logfile, "xs_get_domain_path(%d): error\n", domid); -+ goto out; -+ } -+ -+ pasprintf(&buf, "%s/%s", path, key); -+ value = xs_read(xsh, XBT_NULL, buf, len); -+ if (value == NULL) { -+ fprintf(logfile, "xs_read(%s): read error\n", buf); -+ goto out; -+ } -+ -+ out: -+ free(path); -+ free(buf); -+ return value; -+} -+ -+void xenstore_dom_watch(int domid, const char *key, xenstore_callback fptr, void *opaque) -+{ -+ char *buf = NULL, *path = NULL; -+ int rc = -1; -+ -+ if (xsh == NULL) -+ goto out; -+ -+ path = xs_get_domain_path(xsh, domid); -+ if (path == NULL) { -+ fprintf(logfile, "xs_get_domain_path: error\n"); -+ goto out; -+ } -+ -+ pasprintf(&buf, "%s/%s", path, key); -+ xenstore_watch_new_callback(buf, fptr, opaque); -+ -+ out: -+ free(path); -+ free(buf); -+} -+ -+void xenstore_dom_chmod(int domid, const char *key, const char *perms) -+{ -+ char *buf = NULL, *path = NULL; -+ int rc = -1; -+ struct xs_permissions p; -+ -+ if (xsh == NULL) -+ goto out; -+ -+ path = xs_get_domain_path(xsh, domid); -+ if (path == NULL) { -+ fprintf(logfile, "xs_get_domain_path: error\n"); -+ goto out; -+ } -+ -+ pasprintf(&buf, "%s/%s", path, key); -+ -+ xs_strings_to_perms(&p, 1, perms); -+ xs_set_permissions(xsh, XBT_NULL, buf, &p, 1); -+ -+ out: -+ free(path); -+ free(buf); -+} -+ -+int xenstore_dom_write(int domid, const char *key, const char *value) -+{ -+ char *buf = NULL, *path = NULL; -+ int rc = -1; -+ -+ if (xsh == NULL) -+ goto out; -+ -+ path = xs_get_domain_path(xsh, domid); -+ if (path == NULL) { -+ fprintf(logfile, "xs_get_domain_path: error\n"); -+ goto out; -+ } -+ -+ pasprintf(&buf, "%s/%s", path, key); -+ rc = xs_write(xsh, XBT_NULL, buf, value, strlen(value)); -+ if (rc == 0) { -+ fprintf(logfile, "xs_write(%s, %s): write error\n", buf, key); -+ goto out; -+ } -+ -+ out: -+ free(path); -+ free(buf); -+ return rc; -+} -+ -+char *xenstore_read(const char *path) -+{ -+ char *value = NULL; -+ unsigned int len; -+ -+ if (xsh == NULL) -+ return NULL; -+ return xs_read(xsh, XBT_NULL, path, &len); -+} -+ -+int xenstore_write(const char *path, const char *val) -+{ -+ if (xsh == NULL) -+ return 1; -+ return xs_write(xsh, XBT_NULL, path, val, strlen(val)); -+} -+ -+