--- /dev/null
+diff --git a/hw/acpi-video.h b/hw/acpi-video.h
+new file mode 100644
+index 0000000..3763241
+--- /dev/null
++++ b/hw/acpi-video.h
+@@ -0,0 +1,59 @@
++/******************************************************************************
++ * acpi-video.h
++ *
++ * Interface to /proc/misc/xen-acpi-video
++ *
++ * Copyright (c) 2009 Kamala Narasimhan
++ * Copyright (c) 2009 Citrix Systems, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++
++#ifndef _XEN_ACPI_VIDEO
++#define _XEN_ACPI_VIDEO
++
++/*
++ * Userspace Interface
++ */
++
++#define XEN_VIDEO_DEVICE_NAME "xen-acpi-video"
++#define XEN_VIDEO_GUID_SIZE 16
++
++#define XEN_VIDEO_SUCCESS 0
++#define XEN_VIDEO_EFAULT -14
++#define XEN_VIDEO_NOT_ENOUGH_MEMORY -12
++#define XEN_VIDEO_ENOIOCTLCMD -515
++
++#define XEN_VIDEO_IOCTL_NUM_BRIGHTNESS_LEVELS 100
++#define XEN_VIDEO_IOCTL_BRIGHTNESS_LEVELS 101
++
++typedef struct xen_video_data {
++ uint buffer_size;
++ uint *out_buf;
++} xen_video_data_t;
++
++#endif /* _XEN_ACPI_VIDEO */
++
+diff --git a/hw/piix4acpi.c b/hw/piix4acpi.c
+index 3e48413..87fb2b3 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 "xen_acpi_video.h"
+ #include "thermal_mgmt.h"
+
+ #include "switcher.h"
+@@ -213,6 +214,7 @@ static void acpi_map(PCIDevice *pci_dev, int region_num,
+
+ battery_mgmt_init(pci_dev);
+ xen_acpi_wmi_init(pci_dev);
++ xen_acpi_video_init(pci_dev);
+ thermal_mgmt_init(pci_dev);
+ }
+
+diff --git a/hw/xen_acpi_video.c b/hw/xen_acpi_video.c
+new file mode 100644
+index 0000000..ccef147
+--- /dev/null
++++ b/hw/xen_acpi_video.c
+@@ -0,0 +1,247 @@
++/*
++ * xen_acpi_video.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
++ */
++
++/* When well known output device object methods in virtual ACPI space are called,
++ * the guest delegate those requests to qemu and the below implementation in qemu
++ * talks to the actual firmware through dom0 kernel xen/acpi driver implementation
++ * to cater to those guest level acpi requests.
++ */
++
++#include "hw.h"
++#include "pc.h"
++#include "qemu-xen.h"
++#include "isa.h"
++#include "xen_acpi_video.h"
++#include <sys/ioctl.h>
++
++#ifndef CONFIG_NO_XEN_ACPI_VIDEO
++
++static int xen_video_device = -ENODEV;
++extern FILE *logfile;
++
++static enum XEN_ACPI_VIDEO_COMMAND video_cmd_type = XEN_ACPI_VIDEO_CMD_NONE;
++static unsigned int num_brightness_levels = 0;
++static unsigned int *brightness_levels = NULL;
++static unsigned int current_index = 0;
++
++/* #define XEN_ACPI_VIDEO_DEBUG */
++
++/*
++ * xen_acpi_video_get_num_brightness_levels
++ */
++unsigned int xen_acpi_video_get_num_brightness_levels(void)
++{
++ /* Our virtual acpi layer can only accomodate a package of 11 elements
++ * at this point which appear to be enough with the firmwares we have
++ * checked so far. If that should change it is easy enough to
++ * accomodate more and if such change become common place, we can then
++ * make asl package creation dynamic too.
++ */
++
++ if ( num_brightness_levels > 11 )
++ {
++ fprintf(logfile, "Truncating brightness levels to 11\n");
++ return 11;
++ }
++
++#ifdef XEN_ACPI_VIDEO_DEBUG
++ fprintf(logfile, "XEN VIDEO: Number of brightness levels - %d\n", num_brightness_levels);
++#endif
++
++ return num_brightness_levels;
++}
++
++/*
++ * xen_acpi_video_get_next_brightness_level
++ */
++unsigned int xen_acpi_video_get_next_brightness_level(void)
++{
++ if ( brightness_levels == NULL )
++ {
++ fprintf(logfile, "XEN VIDEO: Brightness levels array empty!\n");
++ return 0;
++ }
++
++ if ( current_index >= num_brightness_levels )
++ {
++ fprintf(logfile, "XEN VIDEO: Index overflow!\n");
++ return 0;
++ }
++
++#ifdef XEN_ACPI_VIDEO_DEBUG
++ fprintf(logfile, "XEN VIDEO: Level - %d\n", brightness_levels[current_index]);
++#endif
++
++ return brightness_levels[current_index++];
++}
++
++/*
++ * xen_acpi_video_port_readb
++ */
++static uint32_t xen_acpi_video_port_readb(void *opaque, uint32_t addr)
++{
++#ifdef XEN_ACPI_VIDEO_DEBUG
++ fprintf(logfile, "XEN VIDEO: In video port read\n");
++#endif
++
++ switch ( video_cmd_type )
++ {
++ case XEN_ACPI_VIDEO_GET_NUM_LEVELS:
++ return xen_acpi_video_get_num_brightness_levels();
++ case XEN_ACPI_VIDEO_GET_LEVLES:
++ return xen_acpi_video_get_next_brightness_level();
++ case XEN_ACPI_VIDEO_CMD_NONE:
++ default:
++ fprintf(logfile, "XEN VIDEO: Unknown request - %d\n",
++ video_cmd_type);
++ break;
++ }
++
++ return 0;
++}
++
++/*
++ * xen_acpi_video_port_writeb
++ */
++static void xen_acpi_video_port_writeb(void *opaque, uint32_t addr, uint32_t val)
++{
++ video_cmd_type = val;
++ if ( val == XEN_ACPI_VIDEO_CMD_NONE )
++ current_index = 0;
++
++#ifdef XEN_ACPI_VIDEO_DEBUG
++ fprintf(logfile, "XEN VIDEO: In video port write, command - %d\n", video_cmd_type);
++#endif
++}
++
++/*
++ * xen_acpi_video_initialize_brightness_info
++ */
++void xen_acpi_video_initialize_brightness_info(void)
++{
++ int ret;
++ xen_video_data_t video_data;
++
++#ifdef XEN_ACPI_VIDEO_DEBUG
++ unsigned int count;
++#endif
++
++ video_data.buffer_size = sizeof(uint);
++ video_data.out_buf = malloc(video_data.buffer_size);
++ if (video_data.out_buf == NULL )
++ {
++ fprintf(logfile, "XEN VIDEO: Allocation failure!\n");
++ return;
++ }
++
++ ret = ioctl(xen_video_device, XEN_ACPI_VIDEO_GET_NUM_LEVELS, &video_data);
++ if ( ret != XEN_VIDEO_SUCCESS || video_data.out_buf == NULL )
++ {
++ fprintf(logfile, "XEN VIDEO: Unable to get number of brightness levels - %d\n",
++ ret);
++ free(video_data.out_buf);
++ video_data.out_buf = NULL;
++ return;
++ }
++
++ num_brightness_levels = *video_data.out_buf;
++ free(video_data.out_buf);
++
++ video_data.buffer_size = num_brightness_levels * sizeof(uint);
++ video_data.out_buf = malloc(video_data.buffer_size);
++ if ( video_data.out_buf == NULL )
++ {
++ num_brightness_levels = 0;
++ fprintf(logfile, "XEN VIDEO: Allocation failure!\n");
++ return;
++ }
++
++ memset(video_data.out_buf, 0, video_data.buffer_size);
++ ret = ioctl(xen_video_device, XEN_ACPI_VIDEO_GET_LEVLES, &video_data);
++ if (ret != XEN_VIDEO_SUCCESS )
++ {
++ num_brightness_levels = 0;
++ free(video_data.out_buf);
++ video_data.out_buf = NULL;
++ fprintf(logfile, "XEN VIDEO: Unable to get brigtness levels - %d\n");
++ return;
++ }
++
++ brightness_levels = video_data.out_buf;
++
++#ifdef XEN_ACPI_VIDEO_DEBUG
++ fprintf(logfile, "XEN VIDEO: Initialize brightness info succeeded!\n");
++ fprintf(logfile, "XEN VIDEO: Number of brightness levels - %d\n", num_brightness_levels);
++ fprintf(logfile, "XEN VIDEO: Brightness levels -");
++ for (count = 0; count < num_brightness_levels; count++)
++ fprintf(logfile, " %d", brightness_levels[count]);
++ fprintf(logfile, "\n");
++#endif
++}
++
++/*
++ * xen_acpi_video_init
++ */
++void xen_acpi_video_init(PCIDevice *device)
++{
++ char dev_name[64];
++
++ sprintf(dev_name, "/dev/%s", XEN_VIDEO_DEVICE_NAME);
++ xen_video_device = open(dev_name, 0);
++ if ( xen_video_device < 0 )
++ {
++ fprintf(logfile, "XEN VIDEO: Unable to open device - %s\n", XEN_VIDEO_DEVICE_NAME);
++ return;
++ }
++
++ register_ioport_read(XEN_ACPI_VIDEO_PORTB, 1, 1, xen_acpi_video_port_readb, device);
++ register_ioport_write(XEN_ACPI_VIDEO_PORTB, 1, 1, xen_acpi_video_port_writeb, device);
++
++ xen_acpi_video_initialize_brightness_info();
++
++#ifdef XEN_ACPI_VIDEO_DEBUG
++ fprintf(logfile, "XEN VIDEO: Xen acpi video registration succeeded!!!\n");
++#endif
++}
++
++/*
++ * xen_acpi_video_cleanup(void)
++ */
++void xen_acpi_video_cleanup(void)
++{
++ if ( xen_video_device > 0 )
++ close(xen_video_device);
++
++ num_brightness_levels = 0;
++ if ( brightness_levels != NULL )
++ {
++ free(brightness_levels);
++ brightness_levels = NULL;
++ }
++}
++
++#else
++
++void xen_acpi_video_init(PCIDevice *device) { }
++void xen_acpi_video_cleanup(void) { }
++
++#endif /* CONFIG_NO_XEN_ACPI_VIDEO */
++
+diff --git a/hw/xen_acpi_video.h b/hw/xen_acpi_video.h
+new file mode 100644
+index 0000000..fd77443
+--- /dev/null
++++ b/hw/xen_acpi_video.h
+@@ -0,0 +1,50 @@
++/*
++ * xen_acpi_video.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_VIDEO_H
++#define _XEN_ACPI_VIDEO_H
++
++#ifdef CONFIG_STUBDOM
++#define CONFIG_NO_XEN_ACPI_VIDEO
++#endif
++
++#include "acpi-video.h"
++
++#define XEN_ACPI_VIDEO_PORTB 0x94
++
++/* Values written to VIDEO command port */
++enum XEN_ACPI_VIDEO_COMMAND
++{
++ XEN_ACPI_VIDEO_GET_NUM_LEVELS = 100,
++ XEN_ACPI_VIDEO_GET_LEVLES,
++ XEN_ACPI_VIDEO_CMD_NONE,
++};
++
++void xen_acpi_video_init(PCIDevice *device);
++void xen_acpi_video_cleanup(void);
++
++#ifndef CONFIG_NO_XEN_ACPI_VIDEO
++ void xen_acpi_video_initialize_brightness_info(void);
++ unsigned int xen_acpi_video_get_num_brightness_levels(void);
++ unsigned int xen_acpi_video_get_next_brightness_level(void);
++#endif
++
++#endif /* _XEN_ACPI_VIDEO_H */
+diff --git a/xen-hooks.mak b/xen-hooks.mak
+index 88aff50..546d37f 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 += xen_acpi_video.o
+ OBJS += thermal_mgmt.o
+ OBJS += switcher.o
+ OBJS += intel.o