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 | 579 | static struct gpe_regs gpe; |
| 580 | 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 | 589 | static uint32_t gpe_readb(void *opaque, uint32_t addr) |
| 583 | 590 | { |
| 584 | 591 | uint32_t val = 0; |
| 585 | 592 | struct gpe_regs *g = opaque; |
| 586 | 593 | switch (addr) { |
| 587 | 594 | case GPE_BASE: |
| 588 | - val = g->sts & 0xFF; | |
| 589 | - break; | |
| 590 | 595 | case GPE_BASE + 1: |
| 591 | - val = (g->sts >> 8) & 0xFF; | |
| 596 | + val = gpe_read_val(g->sts, addr); | |
| 592 | 597 | break; |
| 593 | 598 | case GPE_BASE + 2: |
| 594 | - val = g->en & 0xFF; | |
| 595 | - break; | |
| 596 | 599 | case GPE_BASE + 3: |
| 597 | - val = (g->en >> 8) & 0xFF; | |
| 600 | + val = gpe_read_val(g->en, addr); | |
| 598 | 601 | break; |
| 599 | 602 | default: |
| 600 | 603 | break; |
| ... | ... | @@ -606,21 +609,37 @@ static uint32_t gpe_readb(void *opaque, uint32_t addr) |
| 606 | 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 | 632 | static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val) |
| 610 | 633 | { |
| 611 | 634 | struct gpe_regs *g = opaque; |
| 612 | 635 | switch (addr) { |
| 613 | 636 | case GPE_BASE: |
| 614 | - g->sts = (g->sts & ~0xFFFF) | (val & 0xFFFF); | |
| 615 | - break; | |
| 616 | 637 | case GPE_BASE + 1: |
| 617 | - g->sts = (g->sts & 0xFFFF) | (val << 8); | |
| 638 | + gpe_reset_val(&g->sts, addr, val); | |
| 618 | 639 | break; |
| 619 | 640 | case GPE_BASE + 2: |
| 620 | - g->en = (g->en & ~0xFFFF) | (val & 0xFFFF); | |
| 621 | - break; | |
| 622 | 641 | case GPE_BASE + 3: |
| 623 | - g->en = (g->en & 0xFFFF) | (val << 8); | |
| 642 | + gpe_write_val(&g->en, addr, val); | |
| 624 | 643 | break; |
| 625 | 644 | default: |
| 626 | 645 | break; | ... | ... |