acpi, acpi_piix: factor out GPE logic

factor out ACPI GPE logic. Later it will be used by ICH9 ACPI.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
Isaku Yamahata 2011-03-25 19:54:41 +09:00 committed by Aurelien Jarno
parent be5e7a7601
commit 23910d3f66
3 changed files with 108 additions and 70 deletions

View File

@ -328,3 +328,69 @@ void acpi_pm1_cnt_reset(ACPIPM1CNT *pm1_cnt)
qemu_irq_lower(pm1_cnt->cmos_s3);
}
}
/* ACPI GPE */
void acpi_gpe_init(ACPIGPE *gpe, uint8_t len)
{
gpe->len = len;
gpe->sts = qemu_mallocz(len / 2);
gpe->en = qemu_mallocz(len / 2);
}
void acpi_gpe_blk(ACPIGPE *gpe, uint32_t blk)
{
gpe->blk = blk;
}
void acpi_gpe_reset(ACPIGPE *gpe)
{
memset(gpe->sts, 0, gpe->len / 2);
memset(gpe->en, 0, gpe->len / 2);
}
static uint8_t *acpi_gpe_ioport_get_ptr(ACPIGPE *gpe, uint32_t addr)
{
uint8_t *cur = NULL;
if (addr < gpe->len / 2) {
cur = gpe->sts + addr;
} else if (addr < gpe->len) {
cur = gpe->en + addr;
} else {
abort();
}
return cur;
}
void acpi_gpe_ioport_writeb(ACPIGPE *gpe, uint32_t addr, uint32_t val)
{
uint8_t *cur;
addr -= gpe->blk;
cur = acpi_gpe_ioport_get_ptr(gpe, addr);
if (addr < gpe->len / 2) {
/* GPE_STS */
*cur = (*cur) & ~val;
} else if (addr < gpe->len) {
/* GPE_EN */
*cur = val;
} else {
abort();
}
}
uint32_t acpi_gpe_ioport_readb(ACPIGPE *gpe, uint32_t addr)
{
uint8_t *cur;
uint32_t val;
addr -= gpe->blk;
cur = acpi_gpe_ioport_get_ptr(gpe, addr);
val = 0;
if (cur != NULL) {
val = *cur;
}
return val;
}

View File

@ -126,4 +126,21 @@ void acpi_pm1_cnt_update(ACPIPM1CNT *pm1_cnt,
bool sci_enable, bool sci_disable);
void acpi_pm1_cnt_reset(ACPIPM1CNT *pm1_cnt);
/* GPE0 */
struct ACPIGPE {
uint32_t blk;
uint8_t len;
uint8_t *sts;
uint8_t *en;
};
typedef struct ACPIGPE ACPIGPE;
void acpi_gpe_init(ACPIGPE *gpe, uint8_t len);
void acpi_gpe_blk(ACPIGPE *gpe, uint32_t blk);
void acpi_gpe_reset(ACPIGPE *gpe);
void acpi_gpe_ioport_writeb(ACPIGPE *gpe, uint32_t addr, uint32_t val);
uint32_t acpi_gpe_ioport_readb(ACPIGPE *gpe, uint32_t addr);
#endif /* !QEMU_HW_ACPI_H */

View File

@ -35,17 +35,13 @@
#define ACPI_DBG_IO_ADDR 0xb044
#define GPE_BASE 0xafe0
#define GPE_LEN 4
#define PCI_BASE 0xae00
#define PCI_EJ_BASE 0xae08
#define PCI_RMV_BASE 0xae0c
#define PIIX4_PCI_HOTPLUG_STATUS 2
struct gpe_regs {
uint16_t sts; /* status */
uint16_t en; /* enabled */
};
struct pci_status {
uint32_t up;
uint32_t down;
@ -69,7 +65,7 @@ typedef struct PIIX4PMState {
int kvm_enabled;
/* for pci hotplug */
struct gpe_regs gpe;
ACPIGPE gpe;
struct pci_status pci0_status;
uint32_t pci0_hotplug_enable;
} PIIX4PMState;
@ -89,7 +85,7 @@ static void pm_update_sci(PIIX4PMState *s)
ACPI_BITMASK_POWER_BUTTON_ENABLE |
ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
ACPI_BITMASK_TIMER_ENABLE)) != 0) ||
(((s->gpe.sts & s->gpe.en) & PIIX4_PCI_HOTPLUG_STATUS) != 0);
(((s->gpe.sts[0] & s->gpe.en[0]) & PIIX4_PCI_HOTPLUG_STATUS) != 0);
qemu_set_irq(s->irq, sci_level);
/* schedule a timer interruption if needed */
@ -214,14 +210,25 @@ static int vmstate_acpi_post_load(void *opaque, int version_id)
return 0;
}
#define VMSTATE_GPE_ARRAY(_field, _state) \
{ \
.name = (stringify(_field)), \
.version_id = 0, \
.num = GPE_LEN, \
.info = &vmstate_info_uint16, \
.size = sizeof(uint16_t), \
.flags = VMS_ARRAY | VMS_POINTER, \
.offset = vmstate_offset_pointer(_state, _field, uint8_t), \
}
static const VMStateDescription vmstate_gpe = {
.name = "gpe",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField []) {
VMSTATE_UINT16(sts, struct gpe_regs),
VMSTATE_UINT16(en, struct gpe_regs),
VMSTATE_GPE_ARRAY(sts, ACPIGPE),
VMSTATE_GPE_ARRAY(en, ACPIGPE),
VMSTATE_END_OF_LIST()
}
};
@ -252,7 +259,7 @@ static const VMStateDescription vmstate_acpi = {
VMSTATE_STRUCT(apm, PIIX4PMState, 0, vmstate_apm, APMState),
VMSTATE_TIMER(tmr.timer, PIIX4PMState),
VMSTATE_INT64(tmr.overflow_time, PIIX4PMState),
VMSTATE_STRUCT(gpe, PIIX4PMState, 2, vmstate_gpe, struct gpe_regs),
VMSTATE_STRUCT(gpe, PIIX4PMState, 2, vmstate_gpe, ACPIGPE),
VMSTATE_STRUCT(pci0_status, PIIX4PMState, 2, vmstate_pci_status,
struct pci_status),
VMSTATE_END_OF_LIST()
@ -346,6 +353,7 @@ static int piix4_pm_initfn(PCIDevice *dev)
register_ioport_read(s->smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
acpi_pm_tmr_init(&s->tmr, pm_tmr_timer);
acpi_gpe_init(&s->gpe, GPE_LEN);
qemu_system_powerdown = *qemu_allocate_irqs(piix4_powerdown, s, 1);
@ -399,74 +407,20 @@ static void piix4_pm_register(void)
device_init(piix4_pm_register);
static uint32_t gpe_read_val(uint16_t val, uint32_t addr)
{
if (addr & 1)
return (val >> 8) & 0xff;
return val & 0xff;
}
static uint32_t gpe_readb(void *opaque, uint32_t addr)
{
uint32_t val = 0;
PIIX4PMState *s = opaque;
struct gpe_regs *g = &s->gpe;
switch (addr) {
case GPE_BASE:
case GPE_BASE + 1:
val = gpe_read_val(g->sts, addr);
break;
case GPE_BASE + 2:
case GPE_BASE + 3:
val = gpe_read_val(g->en, addr);
break;
default:
break;
}
uint32_t val = acpi_gpe_ioport_readb(&s->gpe, addr);
PIIX4_DPRINTF("gpe read %x == %x\n", addr, val);
return val;
}
static void gpe_write_val(uint16_t *cur, int addr, uint32_t val)
{
if (addr & 1)
*cur = (*cur & 0xff) | (val << 8);
else
*cur = (*cur & 0xff00) | (val & 0xff);
}
static void gpe_reset_val(uint16_t *cur, int addr, uint32_t val)
{
uint16_t x1, x0 = val & 0xff;
int shift = (addr & 1) ? 8 : 0;
x1 = (*cur >> shift) & 0xff;
x1 = x1 & ~x0;
*cur = (*cur & (0xff << (8 - shift))) | (x1 << shift);
}
static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
{
PIIX4PMState *s = opaque;
struct gpe_regs *g = &s->gpe;
switch (addr) {
case GPE_BASE:
case GPE_BASE + 1:
gpe_reset_val(&g->sts, addr, val);
break;
case GPE_BASE + 2:
case GPE_BASE + 3:
gpe_write_val(&g->en, addr, val);
break;
default:
break;
}
acpi_gpe_ioport_writeb(&s->gpe, addr, val);
pm_update_sci(s);
PIIX4_DPRINTF("gpe write %x <== %d\n", addr, val);
@ -549,8 +503,9 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
{
struct pci_status *pci0_status = &s->pci0_status;
register_ioport_write(GPE_BASE, 4, 1, gpe_writeb, s);
register_ioport_read(GPE_BASE, 4, 1, gpe_readb, s);
register_ioport_write(GPE_BASE, GPE_LEN, 1, gpe_writeb, s);
register_ioport_read(GPE_BASE, GPE_LEN, 1, gpe_readb, s);
acpi_gpe_blk(&s->gpe, GPE_BASE);
register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, pci0_status);
register_ioport_read(PCI_BASE, 8, 4, pcihotplug_read, pci0_status);
@ -566,13 +521,13 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
static void enable_device(PIIX4PMState *s, int slot)
{
s->gpe.sts |= PIIX4_PCI_HOTPLUG_STATUS;
s->gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
s->pci0_status.up |= (1 << slot);
}
static void disable_device(PIIX4PMState *s, int slot)
{
s->gpe.sts |= PIIX4_PCI_HOTPLUG_STATUS;
s->gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
s->pci0_status.down |= (1 << slot);
}