]> xenbits.xensource.com Git - xenclient/ioemu.git/commitdiff
sci implementation for ioemu.
authorJean Guyader <jean.guyader@eu.citrix.com>
Wed, 19 Nov 2008 12:24:51 +0000 (12:24 +0000)
committerJean Guyader <jean.guyader@eu.citrix.com>
Wed, 19 Nov 2008 12:24:51 +0000 (12:24 +0000)
hw/battery_mgmt.c
hw/pc.h
hw/piix4acpi.c
qemu-xen.h
xenstore.c

index 0cce054fec984a2e00c09fdf870ca203344bf86c..f974b2ddda0abae41151676e2db34846b51f8cbd 100644 (file)
@@ -230,15 +230,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)
 {
@@ -291,6 +297,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/pc.h b/hw/pc.h
index f57d160400ec05f1dbad7b6f68bfe08e4d1ad348..7628422e8084844285a2a84f55e1f3002eeeaa12 100644 (file)
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -100,6 +100,9 @@ void acpi_bios_init(void);
 
 void acpi_php_add(int);
 void acpi_php_del(int);
+void acpi_ac_adapter_state_changed(void);
+void acpi_power_button_pressed(void);
+void acpi_lid_state_changed(void);
 
 /* pcspk.c */
 void pcspk_init(PITState *);
index 39d564589931b27e3d38fe7d03ae666fb526c374..085188424482ece9b15ce4b748f5f45b5e1f7778 100644 (file)
@@ -53,7 +53,9 @@
 
 /* The bit in GPE0_STS/EN to notify the pci hotplug event */
 #define ACPI_PHP_GPE_BIT 3
-
+#define ACPI_AC_POWER_STATE_BIT 0x1c
+#define ACPI_POWER_BUTTON_BIT 0x1
+#define ACPI_LID_STATE_BIT 0x17 
 #define ACPI_PHP_SLOT_NUM PHP_SLOT_LEN
 
 typedef struct AcpiDeviceState AcpiDeviceState;
@@ -193,8 +195,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)) );
@@ -211,114 +211,40 @@ static inline void clear_bit(uint8_t *map, int bit)
 }
 
 extern FILE *logfile;
-static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
-{
-#if defined(DEBUG)
-    printf("ACPI: DBG: 0x%08x\n", val);
-#endif
-    fprintf(logfile, "ACPI:debug: write addr=0x%x, val=0x%x.\n", addr, val);
-}
-
-/*
- * simple PCI hotplug controller IO 
- * ACPI_PHP_IO_ADDR + :
- * 0 - the hotplug description: slot(|event(remove/add); 
- * 1 - 1st php slot ctr/sts reg
- * 2 - 2nd php slot ctr/sts reg
- * ......
- */
-static uint32_t acpi_php_readb(void *opaque, uint32_t addr)
-{
-    PHPSlots *hotplug_slots = opaque;
-    int num;
-    uint32_t val; 
-
-    switch (addr)
-    {
-    case ACPI_PHP_IO_ADDR:
-        val = hotplug_slots->plug_evt;
-        break;
-    default:
-        num = addr - ACPI_PHP_IO_ADDR - 1;
-        val = hotplug_slots->slot[num].status;
-    }
-
-    fprintf(logfile, "ACPI PCI hotplug: read addr=0x%x, val=0x%x.\n",
-            addr, val);
 
-    return val;
-}
-
-static void acpi_php_writeb(void *opaque, uint32_t addr, uint32_t val)
+void acpi_ac_adapter_state_changed(void)
 {
-    PHPSlots *hotplug_slots = opaque;
-    int php_slot;
-
-    fprintf(logfile, "ACPI PCI hotplug: write addr=0x%x, val=0x%x.\n",
-            addr, val);
-
-    switch (addr)
-    {
-    case ACPI_PHP_IO_ADDR:
-        break;
-    default:
-        php_slot = addr - ACPI_PHP_IO_ADDR - 1;
-        if ( val == 0x1 ) { /* Eject command */
-            /* make _STA of the slot 0 */
-            hotplug_slots->slot[php_slot].status = 0;
-
-            /* clear the hotplug event */
-            hotplug_slots->plug_evt = 0;
-
-            /* power off the slot */
-            power_off_php_slot(php_slot);
-
-            /* signal the CP ACPI hot remove done. */
-            xenstore_record_dm_state("pci-removed");
-        }
+    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);
     }
 }
-
-static void pcislots_save(QEMUFile* f, void* opaque)
+void acpi_power_button_pressed(void)
 {
-    PHPSlots *s = (PHPSlots*)opaque;
-    int i;
-    for ( i = 0; i < ACPI_PHP_SLOT_NUM; i++ ) {
-        qemu_put_8s( f, &s->slot[i].status);
-    }
-    qemu_put_8s(f, &s->plug_evt);
-}
+    GPEState *s = &gpe_state;
 
-static int pcislots_load(QEMUFile* f, void* opaque, int version_id)
-{
-    PHPSlots *s = (PHPSlots*)opaque;
-    int i;
-    if (version_id != 1)
-        return -EINVAL;
-    for ( i = 0; i < ACPI_PHP_SLOT_NUM; i++ ) {
-        qemu_get_8s( f, &s->slot[i].status);
+    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);
     }
-    qemu_get_8s(f, &s->plug_evt);
-    return 0;
 }
 
-static void php_slots_init(void)
+void acpi_lid_state_changed(void)
 {
-    PHPSlots *slots = &php_slots;
-    int i;
-    memset(slots, 0, sizeof(PHPSlots));
+    GPEState *s = &gpe_state;
 
-    /* update the pci slot status */
-    for ( i = 0; i < PHP_SLOT_LEN; i++ ) {
-        if ( test_pci_slot( PHP_TO_PCI_SLOT(i) ) == 1 )
-            slots->slot[i].status = 0xf;
+    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);
     }
-
-
-    /* ACPI PCI hotplug controller */
-    register_ioport_read(ACPI_PHP_IO_ADDR, ACPI_PHP_SLOT_NUM + 1, 1, acpi_php_readb, slots);
-    register_ioport_write(ACPI_PHP_IO_ADDR, ACPI_PHP_SLOT_NUM + 1, 1, acpi_php_writeb, slots);
-    register_savevm("pcislots", 0, 1, pcislots_save, pcislots_load, slots);
 }
 
 /* GPEx_STS occupy 1st half of the block, while GPEx_EN 2nd half */
@@ -364,7 +290,7 @@ static void gpe_en_write(void *opaque, uint32_t addr, uint32_t val)
     fprintf(logfile, "gpe_en_write: addr=0x%x, val=0x%x.\n", addr, val);
     reg_count = addr - (ACPI_GPE0_BLK_ADDRESS + ACPI_GPE0_BLK_LEN / 2);
     s->gpe0_en[reg_count] = val;
-    /* If disable GPE bit right after generating SCI on it, 
+    /* If disable GPE bit right after generating SCI on it,
      * need deassert the intr to avoid redundant intrs
      */
     if ( s->sci_asserted &&
@@ -399,7 +325,7 @@ static int gpe_load(QEMUFile* f, void* opaque, int version_id)
     int i;
     if (version_id != 1)
         return -EINVAL;
-
+    
     for ( i = 0; i < ACPI_GPE0_BLK_LEN / 2; i++ ) {
         qemu_get_8s(f, &s->gpe0_sts[i]);
         qemu_get_8s(f, &s->gpe0_en[i]);
@@ -439,6 +365,116 @@ static void gpe_acpi_init(void)
     register_savevm("gpe", 0, 1, gpe_save, gpe_load, s);
 }
 
+#ifdef CONFIG_PASSTHROUGH
+
+static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
+{
+#if defined(DEBUG)
+    printf("ACPI: DBG: 0x%08x\n", val);
+#endif
+    fprintf(logfile, "ACPI:debug: write addr=0x%x, val=0x%x.\n", addr, val);
+}
+
+/*
+ * simple PCI hotplug controller IO 
+ * ACPI_PHP_IO_ADDR + :
+ * 0 - the hotplug description: slot(|event(remove/add); 
+ * 1 - 1st php slot ctr/sts reg
+ * 2 - 2nd php slot ctr/sts reg
+ * ......
+ */
+static uint32_t acpi_php_readb(void *opaque, uint32_t addr)
+{
+    PHPSlots *hotplug_slots = opaque;
+    int num;
+    uint32_t val; 
+
+    switch (addr)
+    {
+    case ACPI_PHP_IO_ADDR:
+        val = hotplug_slots->plug_evt;
+        break;
+    default:
+        num = addr - ACPI_PHP_IO_ADDR - 1;
+        val = hotplug_slots->slot[num].status;
+    }
+
+    fprintf(logfile, "ACPI PCI hotplug: read addr=0x%x, val=0x%x.\n",
+            addr, val);
+
+    return val;
+}
+
+static void acpi_php_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+    PHPSlots *hotplug_slots = opaque;
+    int php_slot;
+
+    fprintf(logfile, "ACPI PCI hotplug: write addr=0x%x, val=0x%x.\n",
+            addr, val);
+
+    switch (addr)
+    {
+    case ACPI_PHP_IO_ADDR:
+        break;
+    default:
+        php_slot = addr - ACPI_PHP_IO_ADDR - 1;
+        if ( val == 0x1 ) { /* Eject command */
+            /* make _STA of the slot 0 */
+            hotplug_slots->slot[php_slot].status = 0;
+
+            /* clear the hotplug event */
+            hotplug_slots->plug_evt = 0;
+            /* power off the slot */
+            power_off_php_slot(php_slot);
+            /* signal the CP ACPI hot remove done. */
+            xenstore_record_dm_state("pci-removed");
+        }
+    }
+}
+
+static void pcislots_save(QEMUFile* f, void* opaque)
+{
+    PHPSlots *s = (PHPSlots*)opaque;
+    int i;
+    for ( i = 0; i < ACPI_PHP_SLOT_NUM; i++ ) {
+        qemu_put_8s( f, &s->slot[i].status);
+    }
+    qemu_put_8s(f, &s->plug_evt);
+}
+
+static int pcislots_load(QEMUFile* f, void* opaque, int version_id)
+{
+    PHPSlots *s = (PHPSlots*)opaque;
+    int i;
+    if (version_id != 1)
+        return -EINVAL;
+    for ( i = 0; i < ACPI_PHP_SLOT_NUM; i++ ) {
+        qemu_get_8s( f, &s->slot[i].status);
+    }
+    qemu_get_8s(f, &s->plug_evt);
+    return 0;
+}
+
+static void php_slots_init(void)
+{
+    PHPSlots *slots = &php_slots;
+    int i;
+    memset(slots, 0, sizeof(PHPSlots));
+
+    /* update the pci slot status */
+    for ( i = 0; i < PHP_SLOT_LEN; i++ ) {
+        if ( test_pci_slot( PHP_TO_PCI_SLOT(i) ) == 1 )
+            slots->slot[i].status = 0xf;
+    }
+
+
+    /* ACPI PCI hotplug controller */
+    register_ioport_read(ACPI_PHP_IO_ADDR, ACPI_PHP_SLOT_NUM + 1, 1, acpi_php_readb, slots);
+    register_ioport_write(ACPI_PHP_IO_ADDR, ACPI_PHP_SLOT_NUM + 1, 1, acpi_php_writeb, slots);
+    register_savevm("pcislots", 0, 1, pcislots_save, pcislots_load, slots);
+}
+
 static void acpi_sci_intr(GPEState *s)
 {
     if ( !test_bit(&s->gpe0_sts[0], ACPI_PHP_GPE_BIT) &&
@@ -496,10 +532,8 @@ void acpi_php_add(int pci_slot)
 
     /* update the slot status as present */
     hotplug_slots->slot[php_slot].status = 0xf;
-
     /* power on the slot */
     power_on_php_slot(php_slot);
-
     /* tell Control panel which slot for the new pass-throgh dev */
     sprintf(ret_str, "0x%x", pci_slot);
     xenstore_record_dm("parameter", ret_str);
@@ -556,9 +590,9 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
     d->pm1_control = SCI_EN;
 
     acpi_map((PCIDevice *)d, 0, 0x1f40, 0x10, PCI_ADDRESS_SPACE_IO);
+    gpe_acpi_init();
 
 #ifdef CONFIG_PASSTHROUGH
-    gpe_acpi_init();
     php_slots_init();
     register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, d);
 #endif
index 081ef31d1ff080f6d7b24754323105ffd0af0a6d..7f2683c2992e23e46b5c8ab9e813dd102e0d1704 100644 (file)
@@ -91,6 +91,9 @@ char *xenstore_vm_read(int domid, char *key, unsigned int *len);
 char *xenstore_device_model_read(int domid, char *key, unsigned int *len);
 char *xenstore_read_battery_data(int battery_status);
 int xenstore_refresh_battery_status(void);
+void xenstore_register_for_pm_events(void);
+int xenstore_read_ac_adapter_state(void);
+int xenstore_read_lid_state(void);
 
 /* xenfbfront.c */
 int xenfb_pv_display_init(DisplayState *ds);
index 2d35e8c5dbb98201dcde1a612ce24f067749ca05..5b04167155116aee8f0b67222ddb4e4bb5d7a923 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "hw.h"
 #include "pci.h"
+#include "pc.h"
 #include "qemu-timer.h"
 #include "qemu-xen.h"
 
@@ -813,6 +814,21 @@ 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], "lidstatechangeevt")) {
+        acpi_lid_state_changed();
+        goto out;
+    }
+
     if (strncmp(vec[XS_WATCH_TOKEN], "hd", 2) ||
         strlen(vec[XS_WATCH_TOKEN]) != 3)
         goto out;
@@ -1227,6 +1243,41 @@ 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");
+}
+
+int xenstore_read_ac_adapter_state(void)
+{
+    int ac_state = 1;
+    char *buffer;
+
+    buffer = xenstore_extended_power_mgmt_read("ac_adapter", NULL);
+    if ( buffer == NULL )
+        return ac_state;
+
+    ac_state = strtoull(buffer, NULL, 10);
+    free(buffer);
+    return ac_state;
+}
+
+int xenstore_read_lid_state(void)
+{
+    int lid_state = 1;
+    char * buffer;
+
+    buffer = xenstore_extended_power_mgmt_read("lid_state", NULL);
+    if ( buffer == NULL )
+        return lid_state;
+
+    lid_state = strtoull(buffer, NULL, 10);
+    free(buffer);
+    return lid_state;
+}
+
 /*
  * Create a store entry for a device (e.g., monitor, serial/parallel lines).
  * The entry is <domain-path><storeString>/tty and the value is the name