/* 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;
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)) );
}
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 */
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 &&
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]);
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) &&
/* 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);
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