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; |