From patchwork Sun Mar 3 17:21:26 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Williamson X-Patchwork-Id: 224558 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id E5C2D2C030B for ; Mon, 4 Mar 2013 04:22:00 +1100 (EST) Received: from localhost ([::1]:35034 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UCCbn-0006kS-16 for incoming@patchwork.ozlabs.org; Sun, 03 Mar 2013 12:21:59 -0500 Received: from eggs.gnu.org ([208.118.235.92]:37096) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UCCbK-0006e0-O8 for qemu-devel@nongnu.org; Sun, 03 Mar 2013 12:21:33 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UCCbI-0004Xm-7x for qemu-devel@nongnu.org; Sun, 03 Mar 2013 12:21:30 -0500 Received: from mx1.redhat.com ([209.132.183.28]:64333) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UCCbI-0004XZ-0y for qemu-devel@nongnu.org; Sun, 03 Mar 2013 12:21:28 -0500 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r23HLR2f012426 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Sun, 3 Mar 2013 12:21:27 -0500 Received: from bling.home (ovpn-113-71.phx2.redhat.com [10.3.113.71]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id r23HLQ0Q015207; Sun, 3 Mar 2013 12:21:27 -0500 To: mst@redhat.com From: Alex Williamson Date: Sun, 03 Mar 2013 10:21:26 -0700 Message-ID: <20130303172126.15425.93087.stgit@bling.home> In-Reply-To: <20130303171901.15425.61733.stgit@bling.home> References: <20130303171901.15425.61733.stgit@bling.home> User-Agent: StGit/0.16 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH v4 1/2] pci: Add PCI VGA helpers X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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: Alex Williamson --- hw/pci/pci.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/pci/pci.h | 21 ++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 2f45c8f..ed43111 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -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) diff --git a/hw/pci/pci.h b/hw/pci/pci.h index f340fe5..d837a65 100644 --- a/hw/pci/pci.h +++ b/hw/pci/pci.h @@ -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,