diff -urN qemu.orig/Makefile.target qemu/Makefile.target
--- qemu.orig/Makefile.target	2004-06-15 03:02:36.000000000 +0100
+++ qemu/Makefile.target	2004-06-15 03:03:49.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-15 03:02:36.000000000 +0100
+++ qemu/configure	2004-06-15 03:03:49.000000000 +0100
@@ -391,6 +391,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-15 03:02:36.000000000 +0100
+++ qemu/hw/pc.c	2004-06-15 03:03:49.000000000 +0100
@@ -394,6 +394,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-15 03:23:06.000000000 +0100
@@ -0,0 +1,744 @@
+/*
+ * QEMU PCI Host proxy v0.3
+ * 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 Data logging support
+ *  o Support multiple devices fully
+ *  o Consistent error messages
+ *  o Test with PCMCIA
+ *  o AGP support
+*/
+
+static const char copyright[] =
+	"pciproxy.c: v0.3 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
+#include <signal.h>
+
+/* 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 proxyres {
+	uint32_t qemu_map;
+	uint32_t len;
+	uint32_t bar;
+	void *map;
+	int iomem_region;
+	short io_allowed;
+	short rom;
+};
+
+struct pciproxy {
+	struct PCIDevice pcidev;
+	struct proxyres res[PCI_NUM_REGIONS];
+	int fd;
+	int dev, bus, fn;
+};
+
+#if 0
+#define lprintf printf
+#else
+#define lprintf(...)
+#endif
+
+#define PROC_DEVICES "/proc/bus/pci/devices"
+
+static const char sigirq_patch[]="*** WARNING: You will not be able to "
+	"receive IRQs for your pciproxy devices without patching your kernel "
+	"with: http://www.scaramanga.co.uk/stuff/linux-sigirq.diff";
+
+static __inline__ const char *sys_err(void)
+{
+	return strerror(errno);
+}
+
+/* Explode, for parsing proc files */
+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;
+}
+
+/* Whether a config space read/write needs forwarding to device or not */
+static int config_space_forwarded(uint32_t addr, uint32_t len)
+{
+	static const struct {
+		uint32_t begin;
+		uint32_t end;
+	}nofwd[]={
+		{0x10, 0x28}, /* BARs */
+		{0x30, 0x34}, /* ROM Base */
+		{0x3c, 0x3e}, /* IRQ/INT */
+	};
+	size_t num = sizeof(nofwd)/sizeof(*nofwd);
+	uint32_t end = addr + len;
+	int i;
+
+	/* If our request is not totally inside one of our no-forward
+	 * ranges, then by definition we need to forward..
+	 */
+	for(i=0; i < num; i++) {
+		if ( addr >= nofwd[i].begin && end < nofwd[i].end )
+			return 0;
+	}
+
+	return 1;
+}
+
+/* Perform a read from an MMIO region */
+static uint32_t mem_read(struct proxyres *res, target_phys_addr_t addr, int len)
+{
+	uint32_t ret, ofs;
+
+	ofs = addr - res->qemu_map;
+	switch ( len ) {
+	case 1:
+		ret = *(uint8_t *)(res->map + ofs);
+		break;
+	case 2:
+		ret = *(uint16_t *)(res->map + ofs);
+		break;
+	case 4:
+		ret = *(uint32_t *)(res->map + ofs);
+		break;
+	default:
+		return 0xffffffff;
+	}
+
+	printf("mem read: 0x%.8x %u@0x%.4x\n", ret, len, ofs);
+	return ret;
+}
+
+/* Perform a write to a MMIO region */
+static void mem_write(struct proxyres *res, 
+			target_phys_addr_t addr,
+			int len, uint32_t value)
+{
+	uint32_t ofs;
+
+	ofs = addr - res->qemu_map;
+	switch ( len ) {
+	case 1:
+		*(uint8_t *)(res->map + ofs) = value;
+		break;
+	case 2:
+		*(uint16_t *)(res->map + ofs) = value;
+		break;
+	case 4:
+		*(uint32_t *)(res->map + ofs) = value;
+		break;
+	default:
+		return;
+	}
+
+	lprintf("mem write: 0x%.8x %u@0x%.4x\n", value, len, ofs);
+}
+
+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,
+};
+
+/* 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->res[i].len = 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 proxyres *res)
+{
+#if HAVE_IOPL
+	int ret;
+
+	ret = iopl(3);
+	if ( ret == 0 ) {
+		res->io_allowed = 1;
+		return 1;
+	}
+
+	fprintf(stderr, "iopl(): %s\n", 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 proxyres *res, uint32_t bar)
+{
+#if HAVE_IOPERM
+	u_int32_t from, to;
+	int ret;
+
+	from = bar & ~0x3;
+	to = from + res->len;
+
+	ret = ioperm(from, to, 1);
+	if ( ret < 0 )
+		return map_with_iopl(res);
+	res->io_allowed = 1;
+	return 1;
+#else
+	if ( !map_with_iopl(res) ) {
+		fprintf(stderr, "ioperm() slot %i: %s\n", i, sys_err());
+	}
+
+	return 0;
+#endif
+}
+
+/* Check if resource is mapped and accessible */
+static int resource_is_mapped(struct proxyres *res)
+{
+	if ( res->map )
+		return 1;
+	if ( res->io_allowed )
+		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 proxyres *res, int fd)
+{
+	uint32_t base, flags, len, ofs, pgmask, bar;
+	int prot, ioc;
+	void *map;
+
+	len = res->len;
+	bar = res->bar;
+
+	if ( res->rom ) {
+		prot = PROT_READ;
+	}else{
+		prot = PROT_READ|PROT_WRITE;
+	}
+
+	if ( res->rom || !(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(fd, ioc) ) {
+		fprintf(stderr, "ioctl(): %s\n", sys_err());
+		return 0;
+	}
+
+	map = mmap(NULL, len, prot, MAP_SHARED, fd, base);
+	if ( (map == MAP_FAILED) ) {
+		int ret = 0 ;
+
+		if ( !res->rom && (flags & PCI_ADDRESS_SPACE_IO ) )
+			ret = map_with_ioperm(res, bar);
+
+		if ( ret == 0 )
+			fprintf(stderr, "mmap(): %s\n", sys_err());
+
+		return ret;
+	}
+
+	res->map = 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());
+		goto err_close;
+	}
+
+	/* 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->res[0].bar = le32_to_cpu(*(uint32_t *)(pci->pcidev.config + 0x10));
+	pci->res[1].bar = le32_to_cpu(*(uint32_t *)(pci->pcidev.config + 0x14));
+	pci->res[2].bar = le32_to_cpu(*(uint32_t *)(pci->pcidev.config + 0x18));
+	pci->res[3].bar = le32_to_cpu(*(uint32_t *)(pci->pcidev.config + 0x1c));
+	pci->res[4].bar = le32_to_cpu(*(uint32_t *)(pci->pcidev.config + 0x20));
+	pci->res[5].bar = le32_to_cpu(*(uint32_t *)(pci->pcidev.config + 0x24));
+	pci->res[6].bar = le32_to_cpu(*(uint32_t *)(pci->pcidev.config + 0x30));
+	pci->res[6].rom = 1;
+
+	return 1;
+err_close:
+	if ( close(pci->fd) && errno == EINTR )
+		goto err_close;
+	return 0;
+}
+
+/* Perform a write to an I/O mapped region */
+static void iowrite(void *ptr, uint32_t addr, uint32_t data, uint32_t len)
+{
+	struct proxyres *res= (struct proxyres *)ptr;
+	uint32_t ofs;
+		return;
+
+	ofs = addr - res->qemu_map;
+	addr = res->bar & ~0x03;
+
+	if ( res->map ) {
+		switch( len ) {
+		case 1:
+			*(uint8_t *)(res->map + ofs) = data;
+			break;
+		case 2:
+			*(uint16_t *)(res->map + ofs) = data;
+			break;
+		case 4:
+			*(uint32_t *)(res->map + ofs) = data;
+			break;
+		default:
+			return;
+		}
+	}else{
+#if HAVE_SYS_IO_H
+		if ( !res->io_allowed ) {
+			fprintf(stderr, "pciproxy: illegal write on slot\n");
+			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
+	}
+
+	lprintf("io write: 0x%.8x %u@0x%.4x\n", data, len, ofs);
+}
+
+/* Perform a read from an I/O mapped region */
+static uint32_t ioread(void *ptr, uint32_t addr, uint32_t len)
+{
+	struct proxyres *res = (struct proxyres *)ptr;
+	uint32_t ret, ofs;
+
+	ofs = addr - res->qemu_map;
+	addr = res->bar & ~0x03;
+
+	if ( res->map ) {
+		switch( len ) {
+		case 1:
+			ret = *(uint8_t *)(res->map + ofs);
+			break;
+		case 2:
+			ret = *(uint16_t *)(res->map + ofs);
+			break;
+		case 4:
+			ret = *(uint32_t *)(res->map + ofs);
+			break;
+		default:
+			return 0xffffffff;
+		}
+#if HAVE_SYS_IO_H
+	}else{
+		if ( !res->io_allowed ) {
+			fprintf(stderr, "pciproxy: illegal read on slot\n");
+			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
+	}
+
+	lprintf("io read: 0x%.8x %u@0x%.4x\n", ret, len, ofs);
+	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;
+	struct proxyres *res = &pci->res[i];
+
+	if ( type == PCI_ADDRESS_SPACE_IO ) {
+		uint32_t len = res->len;
+
+		if ( !resource_is_mapped(res) &&
+			!map_resource(res, pci->fd) )
+			return;
+
+		res->qemu_map = addr;
+
+		register_ioport_read(addr, len, 4, ioreadl, res);
+		register_ioport_read(addr, len, 2, ioreadw, res);
+		register_ioport_read(addr, len, 1, ioreadb, res);
+		register_ioport_write(addr, len, 4, iowritel, res);
+		register_ioport_write(addr, len, 2, iowritew, res);
+		register_ioport_write(addr, len, 1, iowriteb, res);
+	}else{
+		unsigned long size;
+
+		if ( !resource_is_mapped(res) &&
+			!map_resource(res, pci->fd) )
+			return;
+
+		size = (res->len + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
+
+		if ( res->iomem_region == 0 )
+			res->iomem_region = cpu_register_io_memory(0,
+							cpu_callback_read,
+							cpu_callback_write,
+							res);
+
+		cpu_register_physical_memory(addr, size,
+						res->iomem_region);
+
+		res->qemu_map = addr;
+	}
+}
+
+/* Signal (IRQ) handler */
+static void sighand(int signum, siginfo_t *si, void *ptr)
+{
+	lprintf("pciproxy IRQ\n");
+	pci_set_irq(ptr, 0, 1);
+}
+
+/* Setup irq handling on a PCI device */
+static void receive_irqs(struct pciproxy *pci)
+{
+	struct pci_sigirq si;
+	struct sigaction sa;
+	int signum = SIGRTMIN;
+
+	sa.sa_sigaction = sighand;
+	sigemptyset(&sa.sa_mask);
+	sa.sa_flags = SA_SIGINFO;
+	sigaction(signum, &sa, NULL);
+
+	si.sig = signum;
+	si.ptr = pci;
+
+	if ( ioctl(pci->fd, PCIIOC_SIGIRQ, &si) == 0 )
+		return;
+
+	if ( errno == EINVAL ) {
+		fprintf(stderr, "%s\n", sigirq_patch);
+	}else if ( errno == ESRCH ) {
+		/* No IRQ handler is needed for this device */
+		return;
+	}else if ( errno == EIO ) {
+		fprintf(stderr, "%.2x:%.2x.%x: Host device can't be allowed "
+			"to share an IRQ yet, sorry, interrupts disabled.\n",
+			pci->bus, pci->dev, pci->fn);
+	}else{
+		fprintf(stderr, "%.2x:%.2x.%x: ioctl(SIGIRQ): %s\n",
+			pci->bus, pci->dev, pci->fn, sys_err());
+	}
+}
+
+static uint32_t cread(PCIDevice *pci_dev, uint32_t addr, int len)
+{
+	struct pciproxy *pci = (struct pciproxy *)pci_dev;
+	ssize_t sysret;
+	int ret;
+	int f;
+
+	f = config_space_forwarded(addr, len);
+	if ( !f )
+		goto no_forward;
+
+	sysret = pread(pci->fd, pci_dev->config + addr, len, addr);
+	if ( sysret != (ssize_t)len )
+		fprintf(stderr, "pread() of config space: %s\n", sys_err());
+
+no_forward:
+	ret = pci_default_read_config(pci_dev, addr, len);
+	lprintf("config read: 0x%.8x %u@0x%.2x%s\n",
+			ret, len, addr, f ? " (forwarded)" : "");
+	return ret;
+}
+
+static void cwrite(PCIDevice *pci_dev, uint32_t addr, uint32_t data, int len)
+{
+	struct pciproxy *pci = (struct pciproxy *)pci_dev;
+	ssize_t sysret;
+	int f;
+
+	f = config_space_forwarded(addr, len);
+	pci_default_write_config(pci_dev, addr, data, len);
+
+	lprintf("config write: 0x%.8x %u@0x%.2x%s\n",
+			data, len, addr, f ? " (forwarded)" : "");
+
+	if ( f == 0 )
+		return;
+
+	sysret = pwrite(pci->fd, pci_dev->config + addr, len, addr);
+	if ( sysret != (ssize_t)len )
+		fprintf(stderr, "pwrite() of config space: %s\n", sys_err());
+}
+
+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,
+				cread, cwrite);
+
+	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++) {
+		struct proxyres *res = &pci->res[i];
+		uint32_t type;
+
+		type = (res->bar & PCI_ADDRESS_SPACE_IO) ?
+			PCI_ADDRESS_SPACE_IO :
+			PCI_ADDRESS_SPACE_MEM ;
+
+		if ( res->rom )
+			type = PCI_ADDRESS_SPACE_MEM;
+
+		if ( res->bar )
+			pci_register_io_region((struct PCIDevice *)pci,
+					i, res->len, type, mapfunc);
+	}
+
+	receive_irqs(pci);
+}
diff -urN qemu.orig/vl.c qemu/vl.c
--- qemu.orig/vl.c	2004-06-15 03:02:36.000000000 +0100
+++ qemu/vl.c	2004-06-15 20:33:35.000000000 +0100
@@ -104,6 +104,7 @@
 /* XXX: use a two level table to limit memory usage */
 #define MAX_IOPORTS 65536
 
+char *pciproxy_devpath = NULL;
 const char *bios_dir = CONFIG_QEMU_SHAREDIR;
 char phys_ram_file[1024];
 CPUState *global_env;
@@ -1081,7 +1082,7 @@
         return -1;
     }
     memset(&ifr, 0, sizeof(ifr));
-    ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+    ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE;
     pstrcpy(ifr.ifr_name, IFNAMSIZ, "tun%d");
     ret = ioctl(fd, TUNSETIFF, (void *) &ifr);
     if (ret != 0) {
@@ -2052,6 +2053,7 @@
     QEMU_OPTION_L,
     QEMU_OPTION_no_code_copy,
     QEMU_OPTION_pci,
+    QEMU_OPTION_pciproxy,
     QEMU_OPTION_prep,
     QEMU_OPTION_localtime,
     QEMU_OPTION_cirrusvga,
@@ -2102,6 +2104,7 @@
 #ifdef TARGET_PPC
     { "prep", 0, QEMU_OPTION_prep },
 #endif
+    { "pciproxy", HAS_ARG, QEMU_OPTION_pciproxy },
     { "localtime", 0, QEMU_OPTION_localtime },
 
     /* temporary options */
@@ -2389,6 +2392,9 @@
             case QEMU_OPTION_cirrusvga:
                 cirrus_vga_enabled = 1;
                 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-15 03:02:36.000000000 +0100
+++ qemu/vl.h	2004-06-15 03:03:49.000000000 +0100
@@ -515,6 +515,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)
