提交 e01fd687 编写于 作者: A Alex Williamson 提交者: Michael S. Tsirkin

pci: Add PCI VGA helpers

Allow devices to register VGA memory regions for handling PCI spec
defined VGA I/O port and MMIO areas.  PCI will attach these to the
bus address spaces and enable them according to the device command
register value.
Signed-off-by: NAlex Williamson <alex.williamson@redhat.com>
Signed-off-by: NMichael S. Tsirkin <mst@redhat.com>
上级 a38b2c49
......@@ -875,6 +875,8 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev)
continue;
memory_region_del_subregion(r->address_space, r->memory);
}
pci_unregister_vga(pci_dev);
}
static int pci_unregister_device(DeviceState *dev)
......@@ -937,6 +939,63 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
: pci_dev->bus->address_space_mem;
}
static void pci_update_vga(PCIDevice *pci_dev)
{
uint16_t cmd;
if (!pci_dev->has_vga) {
return;
}
cmd = pci_get_word(pci_dev->config + PCI_COMMAND);
memory_region_set_enabled(pci_dev->vga_regions[QEMU_PCI_VGA_MEM],
cmd & PCI_COMMAND_MEMORY);
memory_region_set_enabled(pci_dev->vga_regions[QEMU_PCI_VGA_IO_LO],
cmd & PCI_COMMAND_IO);
memory_region_set_enabled(pci_dev->vga_regions[QEMU_PCI_VGA_IO_HI],
cmd & PCI_COMMAND_IO);
}
void pci_register_vga(PCIDevice *pci_dev, MemoryRegion *mem,
MemoryRegion *io_lo, MemoryRegion *io_hi)
{
assert(!pci_dev->has_vga);
assert(memory_region_size(mem) == QEMU_PCI_VGA_MEM_SIZE);
pci_dev->vga_regions[QEMU_PCI_VGA_MEM] = mem;
memory_region_add_subregion_overlap(pci_dev->bus->address_space_mem,
QEMU_PCI_VGA_MEM_BASE, mem, 1);
assert(memory_region_size(io_lo) == QEMU_PCI_VGA_IO_LO_SIZE);
pci_dev->vga_regions[QEMU_PCI_VGA_IO_LO] = io_lo;
memory_region_add_subregion_overlap(pci_dev->bus->address_space_io,
QEMU_PCI_VGA_IO_LO_BASE, io_lo, 1);
assert(memory_region_size(io_hi) == QEMU_PCI_VGA_IO_HI_SIZE);
pci_dev->vga_regions[QEMU_PCI_VGA_IO_HI] = io_hi;
memory_region_add_subregion_overlap(pci_dev->bus->address_space_io,
QEMU_PCI_VGA_IO_HI_BASE, io_hi, 1);
pci_dev->has_vga = true;
pci_update_vga(pci_dev);
}
void pci_unregister_vga(PCIDevice *pci_dev)
{
if (!pci_dev->has_vga) {
return;
}
memory_region_del_subregion(pci_dev->bus->address_space_mem,
pci_dev->vga_regions[QEMU_PCI_VGA_MEM]);
memory_region_del_subregion(pci_dev->bus->address_space_io,
pci_dev->vga_regions[QEMU_PCI_VGA_IO_LO]);
memory_region_del_subregion(pci_dev->bus->address_space_io,
pci_dev->vga_regions[QEMU_PCI_VGA_IO_HI]);
pci_dev->has_vga = false;
}
pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num)
{
return pci_dev->io_regions[region_num].addr;
......@@ -1036,6 +1095,8 @@ static void pci_update_mappings(PCIDevice *d)
r->addr, r->memory, 1);
}
}
pci_update_vga(d);
}
static inline int pci_irq_disabled(PCIDevice *d)
......
......@@ -108,6 +108,20 @@ typedef struct PCIIORegion {
#define PCI_ROM_SLOT 6
#define PCI_NUM_REGIONS 7
enum {
QEMU_PCI_VGA_MEM,
QEMU_PCI_VGA_IO_LO,
QEMU_PCI_VGA_IO_HI,
QEMU_PCI_VGA_NUM_REGIONS,
};
#define QEMU_PCI_VGA_MEM_BASE 0xa0000
#define QEMU_PCI_VGA_MEM_SIZE 0x20000
#define QEMU_PCI_VGA_IO_LO_BASE 0x3b0
#define QEMU_PCI_VGA_IO_LO_SIZE 0xc
#define QEMU_PCI_VGA_IO_HI_BASE 0x3c0
#define QEMU_PCI_VGA_IO_HI_SIZE 0x20
#include "hw/pci/pci_regs.h"
/* PCI HEADER_TYPE */
......@@ -234,6 +248,10 @@ struct PCIDevice {
/* IRQ objects for the INTA-INTD pins. */
qemu_irq *irq;
/* Legacy PCI VGA regions */
MemoryRegion *vga_regions[QEMU_PCI_VGA_NUM_REGIONS];
bool has_vga;
/* Current IRQ levels. Used internally by the generic PCI code. */
uint8_t irq_state;
......@@ -287,6 +305,9 @@ struct PCIDevice {
void pci_register_bar(PCIDevice *pci_dev, int region_num,
uint8_t attr, MemoryRegion *memory);
void pci_register_vga(PCIDevice *pci_dev, MemoryRegion *mem,
MemoryRegion *io_lo, MemoryRegion *io_hi);
void pci_unregister_vga(PCIDevice *pci_dev);
pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num);
int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册