From: Jean Guyader Date: Wed, 19 Nov 2008 12:24:51 +0000 (+0000) Subject: sci implementation for ioemu. X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=f7d0f95ab8d13e4debf174d17dfba68543dc929a;p=xenclient%2Fioemu.git sci implementation for ioemu. --- diff --git a/hw/battery_mgmt.c b/hw/battery_mgmt.c index 0cce054f..f974b2dd 100644 --- a/hw/battery_mgmt.c +++ b/hw/battery_mgmt.c @@ -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 f57d1604..7628422e 100644 --- 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 *); diff --git a/hw/piix4acpi.c b/hw/piix4acpi.c index 39d56458..08518842 100644 --- a/hw/piix4acpi.c +++ b/hw/piix4acpi.c @@ -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 diff --git a/qemu-xen.h b/qemu-xen.h index 081ef31d..7f2683c2 100644 --- a/qemu-xen.h +++ b/qemu-xen.h @@ -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); diff --git a/xenstore.c b/xenstore.c index 2d35e8c5..5b041671 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" @@ -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 /tty and the value is the name