Commit ca2c72be18dd8104fa9108ecefcd562e85672360
1 parent
5e3cb534
qemu: pci hotplug GPE support (Marcelo Tosatti)
Enable the corresponding bit on the PCIST region and trigger the SCI and handle the _EJ0 notifications. Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6608 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
95 additions
and
0 deletions
hw/acpi.c
... | ... | @@ -563,13 +563,21 @@ void qemu_system_powerdown(void) |
563 | 563 | #endif |
564 | 564 | |
565 | 565 | #define GPE_BASE 0xafe0 |
566 | +#define PCI_BASE 0xae00 | |
567 | +#define PCI_EJ_BASE 0xae08 | |
566 | 568 | |
567 | 569 | struct gpe_regs { |
568 | 570 | uint16_t sts; /* status */ |
569 | 571 | uint16_t en; /* enabled */ |
570 | 572 | }; |
571 | 573 | |
574 | +struct pci_status { | |
575 | + uint32_t up; | |
576 | + uint32_t down; | |
577 | +}; | |
578 | + | |
572 | 579 | static struct gpe_regs gpe; |
580 | +static struct pci_status pci0_status; | |
573 | 581 | |
574 | 582 | static uint32_t gpe_readb(void *opaque, uint32_t addr) |
575 | 583 | { |
... | ... | @@ -623,9 +631,95 @@ static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val) |
623 | 631 | #endif |
624 | 632 | } |
625 | 633 | |
634 | +static uint32_t pcihotplug_read(void *opaque, uint32_t addr) | |
635 | +{ | |
636 | + uint32_t val = 0; | |
637 | + struct pci_status *g = opaque; | |
638 | + switch (addr) { | |
639 | + case PCI_BASE: | |
640 | + val = g->up; | |
641 | + break; | |
642 | + case PCI_BASE + 4: | |
643 | + val = g->down; | |
644 | + break; | |
645 | + default: | |
646 | + break; | |
647 | + } | |
648 | + | |
649 | +#if defined(DEBUG) | |
650 | + printf("pcihotplug read %lx == %lx\n", addr, val); | |
651 | +#endif | |
652 | + return val; | |
653 | +} | |
654 | + | |
655 | +static void pcihotplug_write(void *opaque, uint32_t addr, uint32_t val) | |
656 | +{ | |
657 | + struct pci_status *g = opaque; | |
658 | + switch (addr) { | |
659 | + case PCI_BASE: | |
660 | + g->up = val; | |
661 | + break; | |
662 | + case PCI_BASE + 4: | |
663 | + g->down = val; | |
664 | + break; | |
665 | + } | |
666 | + | |
667 | +#if defined(DEBUG) | |
668 | + printf("pcihotplug write %lx <== %d\n", addr, val); | |
669 | +#endif | |
670 | +} | |
671 | + | |
672 | +static uint32_t pciej_read(void *opaque, uint32_t addr) | |
673 | +{ | |
674 | +#if defined(DEBUG) | |
675 | + printf("pciej read %lx == %lx\n", addr, val); | |
676 | +#endif | |
677 | + return 0; | |
678 | +} | |
679 | + | |
680 | +static void pciej_write(void *opaque, uint32_t addr, uint32_t val) | |
681 | +{ | |
682 | + int slot = ffs(val) - 1; | |
683 | + | |
684 | +#if defined(DEBUG) | |
685 | + printf("pciej write %lx <== %d\n", addr, val); | |
686 | +#endif | |
687 | +} | |
688 | + | |
626 | 689 | void qemu_system_hot_add_init(void) |
627 | 690 | { |
628 | 691 | register_ioport_write(GPE_BASE, 4, 1, gpe_writeb, &gpe); |
629 | 692 | register_ioport_read(GPE_BASE, 4, 1, gpe_readb, &gpe); |
630 | 693 | |
694 | + register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, &pci0_status); | |
695 | + register_ioport_read(PCI_BASE, 8, 4, pcihotplug_read, &pci0_status); | |
696 | + | |
697 | + register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, NULL); | |
698 | + register_ioport_read(PCI_EJ_BASE, 4, 4, pciej_read, NULL); | |
699 | +} | |
700 | + | |
701 | +static void enable_device(struct pci_status *p, struct gpe_regs *g, int slot) | |
702 | +{ | |
703 | + g->sts |= 2; | |
704 | + g->en |= 2; | |
705 | + p->up |= (1 << slot); | |
706 | +} | |
707 | + | |
708 | +static void disable_device(struct pci_status *p, struct gpe_regs *g, int slot) | |
709 | +{ | |
710 | + g->sts |= 2; | |
711 | + g->en |= 2; | |
712 | + p->down |= (1 << slot); | |
713 | +} | |
714 | + | |
715 | +void qemu_system_device_hot_add(int bus, int slot, int state) | |
716 | +{ | |
717 | + qemu_set_irq(pm_state->irq, 1); | |
718 | + pci0_status.up = 0; | |
719 | + pci0_status.down = 0; | |
720 | + if (state) | |
721 | + enable_device(&pci0_status, &gpe, slot); | |
722 | + else | |
723 | + disable_device(&pci0_status, &gpe, slot); | |
724 | + qemu_set_irq(pm_state->irq, 0); | |
631 | 725 | } | ... | ... |
sysemu.h