Commit 6eb011b038ccce4759312c834a3d7129f97bd3f0
1 parent
8ca9217d
Fix GPE registers read/write handling. (Gleb Natapov)
For STS register bit are cleared by writing 1 into it. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6624 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
31 additions
and
12 deletions
hw/acpi.c
| @@ -579,22 +579,25 @@ struct pci_status { | @@ -579,22 +579,25 @@ struct pci_status { | ||
| 579 | static struct gpe_regs gpe; | 579 | static struct gpe_regs gpe; |
| 580 | static struct pci_status pci0_status; | 580 | static struct pci_status pci0_status; |
| 581 | 581 | ||
| 582 | +static uint32_t gpe_read_val(uint16_t val, uint32_t addr) | ||
| 583 | +{ | ||
| 584 | + if (addr & 1) | ||
| 585 | + return (val >> 8) & 0xff; | ||
| 586 | + return val & 0xff; | ||
| 587 | +} | ||
| 588 | + | ||
| 582 | static uint32_t gpe_readb(void *opaque, uint32_t addr) | 589 | static uint32_t gpe_readb(void *opaque, uint32_t addr) |
| 583 | { | 590 | { |
| 584 | uint32_t val = 0; | 591 | uint32_t val = 0; |
| 585 | struct gpe_regs *g = opaque; | 592 | struct gpe_regs *g = opaque; |
| 586 | switch (addr) { | 593 | switch (addr) { |
| 587 | case GPE_BASE: | 594 | case GPE_BASE: |
| 588 | - val = g->sts & 0xFF; | ||
| 589 | - break; | ||
| 590 | case GPE_BASE + 1: | 595 | case GPE_BASE + 1: |
| 591 | - val = (g->sts >> 8) & 0xFF; | 596 | + val = gpe_read_val(g->sts, addr); |
| 592 | break; | 597 | break; |
| 593 | case GPE_BASE + 2: | 598 | case GPE_BASE + 2: |
| 594 | - val = g->en & 0xFF; | ||
| 595 | - break; | ||
| 596 | case GPE_BASE + 3: | 599 | case GPE_BASE + 3: |
| 597 | - val = (g->en >> 8) & 0xFF; | 600 | + val = gpe_read_val(g->en, addr); |
| 598 | break; | 601 | break; |
| 599 | default: | 602 | default: |
| 600 | break; | 603 | break; |
| @@ -606,21 +609,37 @@ static uint32_t gpe_readb(void *opaque, uint32_t addr) | @@ -606,21 +609,37 @@ static uint32_t gpe_readb(void *opaque, uint32_t addr) | ||
| 606 | return val; | 609 | return val; |
| 607 | } | 610 | } |
| 608 | 611 | ||
| 612 | +static void gpe_write_val(uint16_t *cur, int addr, uint32_t val) | ||
| 613 | +{ | ||
| 614 | + if (addr & 1) | ||
| 615 | + *cur = (*cur & 0xff) | (val << 8); | ||
| 616 | + else | ||
| 617 | + *cur = (*cur & 0xff00) | (val & 0xff); | ||
| 618 | +} | ||
| 619 | + | ||
| 620 | +static void gpe_reset_val(uint16_t *cur, int addr, uint32_t val) | ||
| 621 | +{ | ||
| 622 | + uint16_t x1, x0 = val & 0xff; | ||
| 623 | + int shift = (addr & 1) ? 8 : 0; | ||
| 624 | + | ||
| 625 | + x1 = (*cur >> shift) & 0xff; | ||
| 626 | + | ||
| 627 | + x1 = x1 & ~x0; | ||
| 628 | + | ||
| 629 | + *cur = (*cur & (0xff << (8 - shift))) | (x1 << shift); | ||
| 630 | +} | ||
| 631 | + | ||
| 609 | static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val) | 632 | static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val) |
| 610 | { | 633 | { |
| 611 | struct gpe_regs *g = opaque; | 634 | struct gpe_regs *g = opaque; |
| 612 | switch (addr) { | 635 | switch (addr) { |
| 613 | case GPE_BASE: | 636 | case GPE_BASE: |
| 614 | - g->sts = (g->sts & ~0xFFFF) | (val & 0xFFFF); | ||
| 615 | - break; | ||
| 616 | case GPE_BASE + 1: | 637 | case GPE_BASE + 1: |
| 617 | - g->sts = (g->sts & 0xFFFF) | (val << 8); | 638 | + gpe_reset_val(&g->sts, addr, val); |
| 618 | break; | 639 | break; |
| 619 | case GPE_BASE + 2: | 640 | case GPE_BASE + 2: |
| 620 | - g->en = (g->en & ~0xFFFF) | (val & 0xFFFF); | ||
| 621 | - break; | ||
| 622 | case GPE_BASE + 3: | 641 | case GPE_BASE + 3: |
| 623 | - g->en = (g->en & 0xFFFF) | (val << 8); | 642 | + gpe_write_val(&g->en, addr, val); |
| 624 | break; | 643 | break; |
| 625 | default: | 644 | default: |
| 626 | break; | 645 | break; |