From patchwork Tue Feb 9 22:01:25 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony Liguori X-Patchwork-Id: 44965 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 30943B7D07 for ; Wed, 10 Feb 2010 09:05:28 +1100 (EST) Received: from localhost ([127.0.0.1]:38898 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NeyCx-0003zA-LE for incoming@patchwork.ozlabs.org; Tue, 09 Feb 2010 17:05:23 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Ney9X-00025k-RO for qemu-devel@nongnu.org; Tue, 09 Feb 2010 17:01:52 -0500 Received: from [199.232.76.173] (port=52469 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Ney9W-00024x-Tj for qemu-devel@nongnu.org; Tue, 09 Feb 2010 17:01:50 -0500 Received: from Debian-exim by monty-python.gnu.org with spam-scanned (Exim 4.60) (envelope-from ) id 1Ney9U-0005mF-0T for qemu-devel@nongnu.org; Tue, 09 Feb 2010 17:01:50 -0500 Received: from e3.ny.us.ibm.com ([32.97.182.143]:48374) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1Ney9T-0005lk-Ip for qemu-devel@nongnu.org; Tue, 09 Feb 2010 17:01:47 -0500 Received: from d01relay07.pok.ibm.com (d01relay07.pok.ibm.com [9.56.227.147]) by e3.ny.us.ibm.com (8.14.3/8.13.1) with ESMTP id o19LpA6Y003507 for ; Tue, 9 Feb 2010 16:51:10 -0500 Received: from d01av01.pok.ibm.com (d01av01.pok.ibm.com [9.56.224.215]) by d01relay07.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id o19M1gO41138754 for ; Tue, 9 Feb 2010 17:01:42 -0500 Received: from d01av01.pok.ibm.com (loopback [127.0.0.1]) by d01av01.pok.ibm.com (8.14.3/8.13.1/NCO v10.0 AVout) with ESMTP id o19M1gF7013584 for ; Tue, 9 Feb 2010 17:01:42 -0500 Received: from localhost.localdomain (sig-9-65-47-242.mts.ibm.com [9.65.47.242]) by d01av01.pok.ibm.com (8.14.3/8.13.1/NCO v10.0 AVin) with ESMTP id o19M1eiB013399; Tue, 9 Feb 2010 17:01:41 -0500 From: Anthony Liguori To: qemu-devel@nongnu.org Date: Tue, 9 Feb 2010 16:01:25 -0600 Message-Id: <1265752899-26980-2-git-send-email-aliguori@us.ibm.com> X-Mailer: git-send-email 1.6.5.2 In-Reply-To: <1265752899-26980-1-git-send-email-aliguori@us.ibm.com> References: <1265752899-26980-1-git-send-email-aliguori@us.ibm.com> X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) Cc: Michael Tsirkin , Anthony Liguori , Alex Graf Subject: [Qemu-devel] [PATCH 01/15] pci: add new bus functions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org - mapping and managing io regions - reading and writing physical memory Signed-off-by: Anthony Liguori --- hw/pci.c | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- hw/pci.h | 18 ++++++- 2 files changed, 181 insertions(+), 9 deletions(-) diff --git a/hw/pci.c b/hw/pci.c index 9ad63dd..5460f27 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -664,6 +664,9 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev) r->addr), r->filtered_size, IO_MEM_UNASSIGNED); + if (!r->map_func && r->read && r->write) { + cpu_unregister_io_memory(r->io_memory_addr); + } } } } @@ -687,16 +690,15 @@ static int pci_unregister_device(DeviceState *dev) return 0; } -void pci_register_bar(PCIDevice *pci_dev, int region_num, - pcibus_t size, int type, - PCIMapIORegionFunc *map_func) +static PCIIORegion *do_pci_register_bar(PCIDevice *pci_dev, int region_num, + pcibus_t size, int type) { PCIIORegion *r; uint32_t addr; pcibus_t wmask; if ((unsigned int)region_num >= PCI_NUM_REGIONS) - return; + return NULL; if (size & (size-1)) { fprintf(stderr, "ERROR: PCI region size must be pow2 " @@ -709,7 +711,6 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num, r->size = size; r->filtered_size = size; r->type = type; - r->map_func = map_func; wmask = ~(size - 1); addr = pci_bar(pci_dev, region_num); @@ -726,6 +727,100 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num, pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff); pci_set_long(pci_dev->cmask + addr, 0xffffffff); } + + return r; +} + +void pci_register_bar(PCIDevice *pci_dev, int region_num, + pcibus_t size, int type, + PCIMapIORegionFunc *map_func) +{ + PCIIORegion *r; + r = do_pci_register_bar(pci_dev, region_num, size, type); + if (r) { + r->map_func = map_func; + } +} + +void pci_memory_read(PCIDevice *pci_dev, pcibus_t addr, void *buf, int len) +{ + cpu_physical_memory_read(addr, buf, len); +} + +void pci_memory_write(PCIDevice *pci_dev, pcibus_t addr, + const void *buf, int len) +{ + cpu_physical_memory_write(addr, buf, len); +} + +static void pci_io_region_writeb(void *opaque, target_phys_addr_t addr, + uint32_t value) +{ + PCIIORegion *r = opaque; + r->write(r->dev, addr, 1, value); +} + +static void pci_io_region_writew(void *opaque, target_phys_addr_t addr, + uint32_t value) +{ + PCIIORegion *r = opaque; + r->write(r->dev, addr, 2, value); +} + +static void pci_io_region_writel(void *opaque, target_phys_addr_t addr, + uint32_t value) +{ + PCIIORegion *r = opaque; + r->write(r->dev, addr, 4, value); +} + +static uint32_t pci_io_region_readb(void *opaque, target_phys_addr_t addr) +{ + PCIIORegion *r = opaque; + return r->read(r->dev, addr, 1); +} + +static uint32_t pci_io_region_readw(void *opaque, target_phys_addr_t addr) +{ + PCIIORegion *r = opaque; + return r->read(r->dev, addr, 2); +} + +static uint32_t pci_io_region_readl(void *opaque, target_phys_addr_t addr) +{ + PCIIORegion *r = opaque; + return r->read(r->dev, addr, 4); +} + +static CPUReadMemoryFunc * const pci_io_region_readfn[3] = { + pci_io_region_readb, + pci_io_region_readw, + pci_io_region_readl, +}; + +static CPUWriteMemoryFunc * const pci_io_region_writefn[3] = { + pci_io_region_writeb, + pci_io_region_writew, + pci_io_region_writel, +}; + +void pci_register_io_region(PCIDevice *d, int region_num, + pcibus_t size, int type, + PCIIOReadFunc *readcb, PCIIOWriteFunc *writecb) +{ + PCIIORegion *r; + r = do_pci_register_bar(d, region_num, size, type); + if (r) { + r->map_func = NULL; + r->dev = d; + r->read = readcb; + r->write = writecb; + if (r->type != PCI_BASE_ADDRESS_SPACE_IO && r->read && r->write) { + r->io_memory_addr = cpu_register_io_memory(pci_io_region_readfn, + pci_io_region_writefn, + r); + } + } } static uint32_t pci_config_get_io_base(PCIDevice *d, @@ -897,6 +992,45 @@ static pcibus_t pci_bar_address(PCIDevice *d, return new_addr; } +static void pci_io_region_ioport_writeb(void *opaque, uint32_t addr, + uint32_t value) +{ + PCIIORegion *r = opaque; + r->write(r->dev, (addr - r->addr), 1, value); +} + +static void pci_io_region_ioport_writew(void *opaque, uint32_t addr, + uint32_t value) +{ + PCIIORegion *r = opaque; + r->write(r->dev, (addr - r->addr), 2, value); +} + +static void pci_io_region_ioport_writel(void *opaque, uint32_t addr, + uint32_t value) +{ + PCIIORegion *r = opaque; + r->write(r->dev, (addr - r->addr), 4, value); +} + +static uint32_t pci_io_region_ioport_readb(void *opaque, uint32_t addr) +{ + PCIIORegion *r = opaque; + return r->read(r->dev, (addr - r->addr), 1); +} + +static uint32_t pci_io_region_ioport_readw(void *opaque, uint32_t addr) +{ + PCIIORegion *r = opaque; + return r->read(r->dev, (addr - r->addr), 2); +} + +static uint32_t pci_io_region_ioport_readl(void *opaque, uint32_t addr) +{ + PCIIORegion *r = opaque; + return r->read(r->dev, (addr - r->addr), 4); +} + static void pci_update_mappings(PCIDevice *d) { PCIIORegion *r; @@ -952,10 +1086,32 @@ static void pci_update_mappings(PCIDevice *d) * addr & (size - 1) != 0. */ if (r->type & PCI_BASE_ADDRESS_SPACE_IO) { - r->map_func(d, i, r->addr, r->filtered_size, r->type); + if (r->map_func) { + r->map_func(d, i, r->addr, r->filtered_size, r->type); + } else { + register_ioport_write(r->addr, r->filtered_size, 1, + pci_io_region_ioport_writeb, r); + register_ioport_write(r->addr, r->filtered_size, 2, + pci_io_region_ioport_writew, r); + register_ioport_write(r->addr, r->filtered_size, 4, + pci_io_region_ioport_writel, r); + register_ioport_read(r->addr, r->filtered_size, 1, + pci_io_region_ioport_readb, r); + register_ioport_read(r->addr, r->filtered_size, 2, + pci_io_region_ioport_readw, r); + register_ioport_read(r->addr, r->filtered_size, 4, + pci_io_region_ioport_readl, r); + } } else { - r->map_func(d, i, pci_to_cpu_addr(d->bus, r->addr), - r->filtered_size, r->type); + if (r->map_func) { + r->map_func(d, i, pci_to_cpu_addr(d->bus, r->addr), + r->filtered_size, r->type); + } else if (r->read && r->write) { + cpu_register_physical_memory(pci_to_cpu_addr(d->bus, + r->addr), + r->filtered_size, + r->io_memory_addr); + } } } } diff --git a/hw/pci.h b/hw/pci.h index 8b511d2..3edf28f 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -81,13 +81,21 @@ typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num, pcibus_t addr, pcibus_t size, int type); typedef int PCIUnregisterFunc(PCIDevice *pci_dev); +typedef uint32_t (PCIIOReadFunc)(PCIDevice *pci_dev, pcibus_t addr, int size); +typedef void (PCIIOWriteFunc)(PCIDevice *pci_dev, pcibus_t addr, int size, + uint32_t value); + typedef struct PCIIORegion { + PCIDevice *dev; pcibus_t addr; /* current PCI mapping address. -1 means not mapped */ #define PCI_BAR_UNMAPPED (~(pcibus_t)0) pcibus_t size; pcibus_t filtered_size; uint8_t type; - PCIMapIORegionFunc *map_func; + PCIMapIORegionFunc *map_func; /* legacy mapping function */ + PCIIOReadFunc *read; + PCIIOWriteFunc *write; + int io_memory_addr; } PCIIORegion; #define PCI_ROM_SLOT 6 @@ -190,6 +198,14 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num, pcibus_t size, int type, PCIMapIORegionFunc *map_func); +void pci_register_io_region(PCIDevice *d, int region_num, + pcibus_t size, int type, + PCIIOReadFunc *readcb, PCIIOWriteFunc *writecb); + +void pci_memory_read(PCIDevice *pci_dev, pcibus_t addr, void *buf, int len); +void pci_memory_write(PCIDevice *pci_dev, pcibus_t addr, + const void *buf, int len); + int pci_add_capability(PCIDevice *pci_dev, uint8_t cap_id, uint8_t cap_size); void pci_del_capability(PCIDevice *pci_dev, uint8_t cap_id, uint8_t cap_size);