From: Gianni Tedesco <gianni@scaramanga.co.uk>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH]: PCI Host/Proxy version 2.
Date: Thu, 03 Jun 2004 17:35:11 +0100 [thread overview]
Message-ID: <1086280511.21922.118.camel@sherbert> (raw)
[-- Attachment #1: Type: text/plain, Size: 1088 bytes --]
Hi,
Attached is the latest version of my PCI Host/Proxy patch. It allows you
to use *real* PCI devices in qemu. Improvements over the last version
include:
o Bugfixes
o Support for memory resources
o Support for ROM resources
Still to do:
o Support IRQ delivery (I need to dig up a kernel patch for this and
get everything together).
o Test fully on real hardware
o Documentation (thats already a WIP)
o Logging support
o AGP support
o Support for PCI-DMA with patched guest OS (any win2k hackers out
there wanna help on this?). Until this is done the code won't be
ready for normal users
o Lock the PCI device
Right now this code is able to get my 3Com 905C running under Linux and
win98, the interface can be configured and link status monitered, tho no
tx/rx. You can see in this new screenshot:
http://www.scaramanga.co.uk/stuff/qemu-pciproxy-0.2.png
Happy hacking kids ;)
--
// Gianni Tedesco (gianni at scaramanga dot co dot uk)
lynx --source www.scaramanga.co.uk/scaramanga.asc | gpg --import
8646BE7D: 6D9F 2287 870E A2C9 8F60 3A3C 91B5 7669 8646 BE7D
[-- Attachment #2: qemu-pciproxy-0.2.diff --]
[-- Type: text/x-patch, Size: 18596 bytes --]
diff -urN qemu.orig/Makefile.target qemu/Makefile.target
--- qemu.orig/Makefile.target 2004-06-03 16:30:57.000000000 +0100
+++ qemu/Makefile.target 2004-06-03 16:31:34.000000000 +0100
@@ -232,7 +232,7 @@
endif
# must use static linking to avoid leaving stuff in virtual address space
-VL_OBJS=vl.o osdep.o block.o monitor.o pci.o
+VL_OBJS=vl.o osdep.o block.o monitor.o pci.o pciproxy.o
ifeq ($(TARGET_ARCH), i386)
# Hardware support
diff -urN qemu.orig/configure qemu/configure
--- qemu.orig/configure 2004-06-03 16:30:57.000000000 +0100
+++ qemu/configure 2004-06-03 16:31:13.000000000 +0100
@@ -390,6 +390,11 @@
elif test -f "/usr/include/byteswap.h" ; then
echo "#define HAVE_BYTESWAP_H 1" >> $config_h
fi
+if test -f "/usr/include/sys/io.h"; then
+ echo "#define HAVE_SYS_IO_H 1" >> $config_h
+ echo "#define HAVE_IOPL 1" >> $config_h
+ echo "#define HAVE_IOPERM 1" >> $config_h
+fi
if test "$gdbstub" = "yes" ; then
echo "CONFIG_GDBSTUB=yes" >> $config_mak
echo "#define CONFIG_GDBSTUB 1" >> $config_h
diff -urN qemu.orig/hw/pc.c qemu/hw/pc.c
--- qemu.orig/hw/pc.c 2004-06-03 16:30:57.000000000 +0100
+++ qemu/hw/pc.c 2004-06-03 16:31:42.000000000 +0100
@@ -389,6 +389,8 @@
if (pci_enabled) {
i440fx_init();
piix3_init();
+ if ( pciproxy_devpath )
+ pciproxy_add_device(pciproxy_devpath);
}
/* init basic PC hardware */
diff -urN qemu.orig/hw/pciproxy.c qemu/hw/pciproxy.c
--- qemu.orig/hw/pciproxy.c 1970-01-01 01:00:00.000000000 +0100
+++ qemu/hw/pciproxy.c 2004-06-03 17:23:03.000000000 +0100
@@ -0,0 +1,675 @@
+/*
+ * QEMU PCI Host proxy v0.2
+ * Copyright (c) 2004 Gianni Tedesco
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This code is dedicated towards my muse, my inspiration, Broadcom Corporation.
+ * Without your spite I would not have been compelled to write this code.
+ *
+ * TODO:
+ * o Map IRQs, fixup PCIIOC_SIGIRQ.
+ * o Data logging support
+ * o Test with PCMCIA
+ * o AGP support
+*/
+
+static const char copyright[] =
+ "pciproxy.c: v0.2 Copyright (c) Gianni Tedesco 2004";
+
+#include "vl.h"
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#if HAVE_SYS_IO_H
+#include <sys/io.h>
+#endif
+
+#define PROC_DEVICES "/proc/bus/pci/devices"
+
+/* Ioctls for /proc/bus/pci/X/Y nodes. */
+#define PCIIOC_BASE ('P' << 24 | 'C' << 16 | 'I' << 8)
+/* Get controller for PCI device. */
+#define PCIIOC_CONTROLLER (PCIIOC_BASE | 0x00)
+/* Set mmap state to I/O space. */
+#define PCIIOC_MMAP_IS_IO (PCIIOC_BASE | 0x01)
+/* Set mmap state to MEM space. */
+#define PCIIOC_MMAP_IS_MEM (PCIIOC_BASE | 0x02)
+/* Enable/disable write-combining. */
+#define PCIIOC_WRITE_COMBINE (PCIIOC_BASE | 0x03)
+/* Send user-defined signal for irqs */
+#define PCIIOC_SIGIRQ (PCIIOC_BASE | 0x04)
+struct pci_sigirq {
+ int sig;
+ void *ptr;
+};
+
+struct pciproxy {
+ struct PCIDevice pcidev;
+ uint32_t len[PCI_NUM_REGIONS];
+ uint32_t qemu_map[PCI_NUM_REGIONS];
+ void *map[PCI_NUM_REGIONS];
+ uint32_t io_allowed;
+ uint32_t bar[PCI_NUM_REGIONS];
+ int dev, bus, fn;
+ int fd;
+ int iomem_region;
+};
+
+static __inline__ const char *sys_err(void)
+{
+ return strerror(errno);
+}
+
+static int easy_explode(char *str, char split, char **toks, int max_toks)
+{
+ char *tmp;
+ int tok;
+ int state;
+
+ for(tmp=str,state=tok=0; *tmp && tok < max_toks; tmp++) {
+ if ( state == 0 ) {
+ if ( *tmp == split ) {
+ toks[tok++] = NULL;
+ }else if ( !isspace(*tmp) ) {
+ state = 1;
+ toks[tok++] = tmp;
+ }
+ }else if ( state == 1 ) {
+ if ( *tmp == split || isspace(*tmp) ) {
+ *tmp = '\0';
+ state = 0;
+ }
+ }
+ }
+
+ return tok;
+}
+
+static int resource_lookup(struct pciproxy *pci,
+ target_phys_addr_t begin,
+ target_phys_addr_t end,
+ int type)
+{
+ int i;
+
+ for(i=0; i < PCI_NUM_REGIONS; i++) {
+ target_phys_addr_t b, e;
+
+ if ( pci->bar[i] == 0 )
+ continue;
+ if ( type != PCI_ADDRESS_SPACE_IO ) {
+ if ( i != PCI_ROM_SLOT &&
+ pci->bar[i] & PCI_ADDRESS_SPACE_IO )
+ continue;
+ }else{
+ if ( !(pci->bar[i] & PCI_ADDRESS_SPACE_IO) )
+ continue;
+ }
+
+ b = pci->qemu_map[i];
+ e = b + pci->len[i];
+
+ if ( begin >= b && end <= e ) {
+ return i;
+ }
+ }
+
+ fprintf(stderr, "resource_lookup: %x/%u not found\n", begin, end-begin);
+ return -1;
+}
+
+static uint32_t mem_read(struct pciproxy *pci, target_phys_addr_t addr, int len)
+{
+ uint32_t ret, ofs;
+ int i;
+
+ i = resource_lookup(pci, addr, addr + len, PCI_ADDRESS_SPACE_MEM);
+ if ( i < 0 )
+ return 0xffffffff;
+
+ ofs = addr - pci->qemu_map[i];
+ switch ( len ) {
+ case 1:
+ ret = *(uint8_t *)(pci->map[i] + ofs);
+ break;
+ case 2:
+ ret = *(uint16_t *)(pci->map[i] + ofs);
+ break;
+ case 4:
+ ret = *(uint32_t *)(pci->map[i] + ofs);
+ break;
+ default:
+ return 0xffffffff;
+ }
+
+ return ret;
+}
+
+static void mem_write(struct pciproxy *pci,
+ target_phys_addr_t addr,
+ int len, uint32_t value)
+{
+ uint32_t ofs;
+ int i;
+
+ i = resource_lookup(pci, addr, addr + len, PCI_ADDRESS_SPACE_MEM);
+ if ( i < 0 )
+ return;
+
+ ofs = addr - pci->qemu_map[i];
+ switch ( len ) {
+ case 1:
+ *(uint8_t *)(pci->map[i] + ofs) = value;
+ break;
+ case 2:
+ *(uint16_t *)(pci->map[i] + ofs) = value;
+ break;
+ case 4:
+ *(uint32_t *)(pci->map[i] + ofs) = value;
+ break;
+ default:
+ return;
+ }
+}
+
+static uint32_t mem_readb(void *ptr, target_phys_addr_t addr)
+{
+ return mem_read(ptr, addr, 1);
+}
+static uint32_t mem_readw(void *ptr, target_phys_addr_t addr)
+{
+ return mem_read(ptr, addr, 2);
+}
+static uint32_t mem_readl(void *ptr, target_phys_addr_t addr)
+{
+ return mem_read(ptr, addr, 4);
+}
+static void mem_writeb(void *ptr, target_phys_addr_t addr, uint32_t value)
+{
+ return mem_write(ptr, addr, 1, value);
+}
+static void mem_writew(void *ptr, target_phys_addr_t addr, uint32_t value)
+{
+ return mem_write(ptr, addr, 2, value);
+}
+static void mem_writel(void *ptr, target_phys_addr_t addr, uint32_t value)
+{
+ return mem_write(ptr, addr, 4, value);
+}
+
+static CPUReadMemoryFunc *cpu_callback_read[3]={
+ mem_readb,
+ mem_readw,
+ mem_readl,
+};
+static CPUWriteMemoryFunc *cpu_callback_write[3]={
+ mem_writeb,
+ mem_writew,
+ mem_writel,
+};
+
+static int register_cbmem(struct pciproxy *pci, int i,
+ target_phys_addr_t start_addr)
+{
+ unsigned long size;
+
+ size = (pci->len[i] + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
+
+ if ( pci->iomem_region == 0 )
+ pci->iomem_region = cpu_register_io_memory(0,
+ cpu_callback_read,
+ cpu_callback_write,
+ pci);
+
+ cpu_register_physical_memory(start_addr, size, pci->iomem_region);
+
+ pci->qemu_map[i] = start_addr;
+
+ return 1;
+}
+
+/* Uses /proc/bus/devices to grab the length of the resources on our PCI
+ * device in a platform independant way.
+ */
+static int peek_resources(struct pciproxy *pci)
+{
+ FILE *f;
+ char buf[512];
+ char *tok[18];
+ uint32_t num;
+ int n, i;
+
+ f = fopen(PROC_DEVICES, "r");
+ if ( f == NULL ) {
+ fprintf(stderr, "%s: open(): %s\n", PROC_DEVICES, sys_err());
+ return 0;
+ }
+
+ while ( fgets(buf, sizeof(buf), f) ) {
+ char *ptr;
+
+ ptr = strchr(buf, '\r');
+ if ( ptr == NULL )
+ ptr = strchr(buf, '\n');
+ if ( ptr == NULL )
+ break;
+ *ptr = '\0';
+
+ n = easy_explode(buf, '\0', tok, 18);
+ if ( n < 17 )
+ continue;
+
+ num = strtoul(tok[0], NULL, 16);
+ if ( pci->bus != ((num & 0xff00) >> 8) )
+ continue;
+ if ( pci->dev != ((num & 0x00ff) >> 3) )
+ continue;
+ if ( pci->fn != (num & 0x7) )
+ continue;
+
+ for(i=0; i < PCI_NUM_REGIONS; i++) {
+ num = strtoul(tok[10 + i], NULL, 16);
+ pci->len[i] = num;
+ }
+
+ fclose(f);
+ return 1;
+ }
+
+ fclose(f);
+ return 0;
+}
+
+/* Final fallback path if mmap and ioperm fails, we just use iopl to raise
+ * our I/O priv level so that we can do any I/O we like.
+ */
+static int map_with_iopl(struct pciproxy *pci, int i)
+{
+#if HAVE_IOPL
+ int ret;
+
+ ret = iopl(3);
+ if ( ret == 0 ) {
+ pci->io_allowed |= (1<<i);
+ return 1;
+ }
+
+ fprintf(stderr, "%.2x:%.2x.%x iopl() slot %i: %s\n",
+ pci->bus, pci->dev, pci->fn, i, sys_err());
+#endif
+ return 0;
+}
+
+/* First fallback path if mmap failes, try to use ioperm for granular
+ * permission granting to the I/O ports.
+ */
+static int map_with_ioperm(struct pciproxy *pci, int i, uint32_t bar)
+{
+#if HAVE_IOPERM
+ u_int32_t from, to;
+ int ret;
+
+ from = bar & ~0x3;
+ to = from + pci->len[i];
+
+ ret = ioperm(from, to, 1);
+ if ( ret < 0 )
+ return map_with_iopl(pci, i);
+ pci->io_allowed |= (1<<i);
+ return 1;
+#else
+ if ( !map_with_iopl(pci, i) ) {
+ fprintf(stderr, "%.2x:%.2x.%x ioperm() slot %i: %s\n",
+ pci->bus, pci->dev, pci->fn, i, sys_err());
+ }
+
+ return 0;
+#endif
+}
+
+
+static int resource_is_mapped(struct pciproxy *pci, int i)
+{
+ if ( pci->map[i] )
+ return 1;
+ if ( pci->io_allowed & (1<<i) )
+ return 1;
+ return 0;
+}
+
+/* Try to mmap a given PCI resource from the /proc/bus/pci/XX/YY.Z file */
+static int map_resource(struct pciproxy *pci, int i)
+{
+ uint32_t base, flags, len, ofs, pgmask, bar;
+ int prot, ioc;
+ void *map;
+
+ len = pci->len[i];
+ bar = pci->bar[i];
+
+ if ( i == PCI_ROM_SLOT ) {
+ prot = PROT_READ;
+ }else{
+ prot = PROT_READ|PROT_WRITE;
+ }
+
+ if ( i == PCI_ROM_SLOT || !(bar & PCI_ADDRESS_SPACE_IO) ) {
+ flags = (bar & 0xf);
+ base = (bar & ~0xf);
+ ioc = PCIIOC_MMAP_IS_MEM;
+ }else{
+ flags = (bar & 0x3);
+ base = (bar & ~0x3);
+ ioc = PCIIOC_MMAP_IS_IO;
+ }
+
+ /* Round base address down to the nearest page boundary and length
+ * up to the the nearest page boundary in order that we may mmap
+ * the resource range.
+ *
+ * XXX: Assumes page size is a power of two. (big deal)
+ */
+ pgmask = sysconf(_SC_PAGESIZE) - 1;
+
+ ofs = base & pgmask;
+ base &= ~pgmask;
+ len += pgmask;
+ len &= ~pgmask;
+
+ if ( ioctl(pci->fd, ioc) ) {
+ fprintf(stderr, "%.2x:%.2x.%x ioctl() slot %i: %s\n",
+ pci->bus, pci->dev, pci->fn, i, sys_err());
+ return 0;
+ }
+
+ map = mmap(NULL, len, prot, MAP_SHARED, pci->fd, base);
+ if ( (map == MAP_FAILED) ) {
+ int ret = 0 ;
+
+ if ( i != PCI_ROM_SLOT && (flags & PCI_ADDRESS_SPACE_IO ) )
+ ret = map_with_ioperm(pci, i, bar);
+
+ if ( ret == 0 )
+ fprintf(stderr, "%.2x:%.2x.%x mmap() slot %i: %s\n",
+ pci->bus, pci->dev, pci->fn, i, sys_err());
+
+ return ret;
+ }
+
+ pci->map[i] = map + ofs;
+ return 1;
+}
+
+/* Construct the filename of the /proc/bus/pci/XX/YY.Z file to open for our
+ * device and open it.
+ */
+static int open_proc_bus_pci(struct pciproxy *pci)
+{
+ char path[1024];
+ ssize_t ret;
+
+ snprintf(path, sizeof(path), "/proc/bus/pci/%.2x/%.2x.%x",
+ pci->bus, pci->dev, pci->fn);
+
+ pci->fd = open(path, O_RDWR);
+ if ( pci->fd < 0 ) {
+ fprintf(stderr, "%s: open(): %s\n", path, sys_err());
+ return 0;
+ }
+
+ ret = pread(pci->fd, pci->pcidev.config, sizeof(pci->pcidev.config), 0);
+ if ( ret != (ssize_t)sizeof(pci->pcidev.config) ) {
+ fprintf(stderr, "%s: pread %u bytes of config space: %s\n",
+ path, sizeof(pci->pcidev.config), sys_err());
+intr:
+ if ( close(pci->fd) && errno == EINTR )
+ goto intr;
+ return 0;
+ }
+
+ /* Directly read the bar because on some architectures like PPC, the
+ * kernels mapped base doesn't correspond to the address we need
+ * to mmap on this FD. Also we need this info later on...
+ */
+ pci->bar[0] = le32_to_cpu(*(uint32_t *)(pci->pcidev.config + 0x10));
+ pci->bar[1] = le32_to_cpu(*(uint32_t *)(pci->pcidev.config + 0x14));
+ pci->bar[2] = le32_to_cpu(*(uint32_t *)(pci->pcidev.config + 0x18));
+ pci->bar[3] = le32_to_cpu(*(uint32_t *)(pci->pcidev.config + 0x1c));
+ pci->bar[4] = le32_to_cpu(*(uint32_t *)(pci->pcidev.config + 0x20));
+ pci->bar[5] = le32_to_cpu(*(uint32_t *)(pci->pcidev.config + 0x24));
+ pci->bar[6] = le32_to_cpu(*(uint32_t *)(pci->pcidev.config + 0x30));
+
+ return 1;
+}
+
+static void iowrite(void *ptr, uint32_t addr, uint32_t data, uint32_t len)
+{
+ struct pciproxy *pci = (struct pciproxy *)ptr;
+ uint32_t ofs;
+ int i;
+
+ i = resource_lookup(pci, addr, addr + len, PCI_ADDRESS_SPACE_IO);
+ if ( i < 0 )
+ return;
+
+ ofs = addr - pci->qemu_map[i];
+ addr = pci->bar[i] & ~0x03;
+
+ if ( pci->map[i] ) {
+ switch( len ) {
+ case 1:
+ *(uint8_t *)(pci->map[i] + ofs) = data;
+ break;
+ case 2:
+ *(uint16_t *)(pci->map[i] + ofs) = data;
+ break;
+ case 4:
+ *(uint32_t *)(pci->map[i] + ofs) = data;
+ break;
+ default:
+ return;
+ }
+ }else{
+#if HAVE_SYS_IO_H
+ if ( !(pci->io_allowed & (1<<i)) ) {
+ fprintf(stderr, "pciproxy: illegal write on slot #%i\n",
+ i);
+ return;
+ }
+
+ switch ( len ) {
+ case 1:
+ outb(data, addr + ofs);
+ break;
+ case 2:
+ outw(data, addr + ofs);
+ break;
+ case 4:
+ outl(data, addr + ofs);
+ break;
+ default:
+ return;
+ }
+#endif
+ }
+}
+
+static uint32_t ioread(void *ptr, uint32_t addr, uint32_t len)
+{
+ struct pciproxy *pci = (struct pciproxy *)ptr;
+ uint32_t ret, ofs;
+ int i;
+
+ i = resource_lookup(pci, addr, addr + len, PCI_ADDRESS_SPACE_IO);
+ if ( i < 0 )
+ return 0xffffffff;
+
+ ofs = addr - pci->qemu_map[i];
+ addr = pci->bar[i] & ~0x03;
+
+ if ( pci->map[i] ) {
+ switch( len ) {
+ case 1:
+ ret = *(uint8_t *)(pci->map[i] + ofs);
+ break;
+ case 2:
+ ret = *(uint16_t *)(pci->map[i] + ofs);
+ break;
+ case 4:
+ ret = *(uint32_t *)(pci->map[i] + ofs);
+ break;
+ default:
+ return 0xffffffff;
+ }
+#if HAVE_SYS_IO_H
+ }else{
+ if ( !(pci->io_allowed & (1<<i)) ) {
+ fprintf(stderr, "pciproxy: illegal read on slot #%i\n",
+ i);
+ return 0xffffffff;
+ }
+
+ switch ( len ) {
+ case 1:
+ ret = inb(addr + ofs);
+ break;
+ case 2:
+ ret = inw(addr + ofs);
+ break;
+ case 4:
+ ret = inl(addr + ofs);
+ break;
+ default:
+ return 0xffffffff;
+ }
+#endif
+ }
+
+ return ret;
+}
+
+static void iowritel(void *ptr, uint32_t addr, uint32_t data)
+{
+ iowrite(ptr, addr, data, 4);
+}
+static void iowritew(void *ptr, uint32_t addr, uint32_t data)
+{
+ iowrite(ptr, addr, data, 2);
+}
+static void iowriteb(void *ptr, uint32_t addr, uint32_t data)
+{
+ iowrite(ptr, addr, data, 1);
+}
+static uint32_t ioreadl(void *ptr, uint32_t addr)
+{
+ return ioread(ptr, addr, 4);
+}
+static uint32_t ioreadw(void *ptr, uint32_t addr)
+{
+ return ioread(ptr, addr, 2);
+}
+static uint32_t ioreadb(void *ptr, uint32_t addr)
+{
+ return ioread(ptr, addr, 1);
+}
+
+static void mapfunc(PCIDevice *pci_dev, int i,
+ uint32_t addr, uint32_t size, int type)
+{
+ struct pciproxy *pci = (struct pciproxy *)pci_dev;
+
+ if ( type == PCI_ADDRESS_SPACE_IO ) {
+ uint32_t len = pci->len[i];
+
+ if ( !resource_is_mapped(pci, i) &&
+ !map_resource(pci, i) )
+ return;
+
+ pci->qemu_map[i] = addr;
+
+ register_ioport_read(addr, len, 4, ioreadl, pci);
+ register_ioport_read(addr, len, 2, ioreadw, pci);
+ register_ioport_read(addr, len, 1, ioreadb, pci);
+ register_ioport_write(addr, len, 4, iowritel, pci);
+ register_ioport_write(addr, len, 2, iowritew, pci);
+ register_ioport_write(addr, len, 1, iowriteb, pci);
+
+ printf("Mapped io slot #%i [0x%.8x] 0x%.8x (len=%u)\n",
+ i, pci->bar[i], addr, len);
+ }else{
+ if ( !resource_is_mapped(pci, i) &&
+ !map_resource(pci, i) )
+ return;
+
+ register_cbmem(pci, i, addr);
+
+ printf("Mapped mem slot #%i [0x%.8x] 0x%.8x\n",
+ i, pci->bar[i], pci->qemu_map[i]);
+ }
+}
+
+void pciproxy_add_device(char *devpath)
+{
+ char *tok[3] = {NULL};
+ struct pciproxy *pci;
+ int i;
+
+ easy_explode(devpath, '.', &tok[1], 2);
+ if ( easy_explode(devpath, ':', &tok[0], 2) == 1 ) {
+ tok[1] = tok[0];
+ tok[0] = NULL;
+ }
+ for(i=0; i < 3; i++)
+ if ( tok[i] == NULL )
+ tok[i] = "0";
+
+ pci = (struct pciproxy *)pci_register_device("pciproxy",
+ sizeof(*pci), 0, -1,
+ NULL, NULL);
+
+ if ( pci == NULL ) {
+ fprintf(stderr, "pciproxy: Adding device failed\n");
+ return;
+ }
+
+ pci->bus = strtol(tok[0], NULL, 16);
+ pci->dev = strtol(tok[1], NULL, 16);
+ pci->fn = strtol(tok[2], NULL, 16);
+
+ printf("Adding PCI Host Proxy device: %.2x:%.2x:%x\n",
+ pci->bus, pci->dev, pci->fn);
+
+ peek_resources(pci);
+
+ if ( !open_proc_bus_pci(pci) )
+ return;
+
+ for(i=0; i < PCI_NUM_REGIONS; i++) {
+ uint32_t type;
+
+ type = (pci->bar[i] & PCI_ADDRESS_SPACE_IO) ?
+ PCI_ADDRESS_SPACE_IO :
+ PCI_ADDRESS_SPACE_MEM ;
+
+ if ( i == PCI_ROM_SLOT )
+ type = PCI_ADDRESS_SPACE_MEM;
+
+ if ( pci->bar[i] )
+ pci_register_io_region((struct PCIDevice *)pci,
+ i, pci->len[i], type, mapfunc);
+ }
+
+ /* TODO: Setup sigirg if present, if not, warn */
+}
diff -urN qemu.orig/vl.c qemu/vl.c
--- qemu.orig/vl.c 2004-06-03 16:30:57.000000000 +0100
+++ qemu/vl.c 2004-06-03 17:23:19.000000000 +0100
@@ -130,6 +130,7 @@
int pci_enabled = 0;
int prep_enabled = 0;
int rtc_utc = 1;
+char *pciproxy_devpath = NULL;
/***********************************************************/
/* x86 ISA bus support */
@@ -2018,6 +2019,7 @@
QEMU_OPTION_pci,
QEMU_OPTION_prep,
QEMU_OPTION_localtime,
+ QEMU_OPTION_pciproxy,
};
typedef struct QEMUOption {
@@ -2068,6 +2070,7 @@
#ifdef TARGET_PPC
{ "prep", 0, QEMU_OPTION_prep },
#endif
+ { "pciproxy", HAS_ARG, QEMU_OPTION_pciproxy },
{ "localtime", 0, QEMU_OPTION_localtime },
{ NULL },
};
@@ -2348,6 +2351,9 @@
case QEMU_OPTION_localtime:
rtc_utc = 0;
break;
+ case QEMU_OPTION_pciproxy:
+ pciproxy_devpath = (char *)optarg;
+ break;
}
}
}
diff -urN qemu.orig/vl.h qemu/vl.h
--- qemu.orig/vl.h 2004-06-03 16:30:57.000000000 +0100
+++ qemu/vl.h 2004-06-03 16:31:27.000000000 +0100
@@ -437,6 +437,10 @@
void pci_pmac_init(void);
void pci_ppc_bios_init(void);
+/* pciproxy.c */
+extern char *pciproxy_devpath;
+void pciproxy_add_device(char *devpath);
+
/* vga.c */
#define VGA_RAM_SIZE (4096 * 1024)
next reply other threads:[~2004-06-03 16:36 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-06-03 16:35 Gianni Tedesco [this message]
2004-06-04 4:37 ` [Qemu-devel] [PATCH]: PCI Host/Proxy version 2 Taras
2004-06-04 14:40 ` Gianni Tedesco
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1086280511.21922.118.camel@sherbert \
--to=gianni@scaramanga.co.uk \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).