ia64/xen-unstable

changeset 8879:5b433b4fca34

PCI backend and frontend drivers for i386 and x86_64.

Signed-off-by: Ryan Wilson <hap9@epoch.ncsc.mil>
author kaf24@firebug.cl.cam.ac.uk
date Thu Feb 16 23:44:41 2006 +0100 (2006-02-16)
parents 294b3a447dce
children 7c720ccec00a
files linux-2.6-xen-sparse/arch/i386/Kconfig linux-2.6-xen-sparse/arch/i386/pci/Makefile linux-2.6-xen-sparse/arch/i386/pci/pcifront.c linux-2.6-xen-sparse/arch/x86_64/Kconfig linux-2.6-xen-sparse/arch/x86_64/pci/Makefile linux-2.6-xen-sparse/drivers/xen/Kconfig linux-2.6-xen-sparse/drivers/xen/Makefile linux-2.6-xen-sparse/drivers/xen/pciback/Makefile linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.h linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_header.c linux-2.6-xen-sparse/drivers/xen/pciback/passthrough.c linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c linux-2.6-xen-sparse/drivers/xen/pciback/pciback.h linux-2.6-xen-sparse/drivers/xen/pciback/pciback_ops.c linux-2.6-xen-sparse/drivers/xen/pciback/vpci.c linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c linux-2.6-xen-sparse/drivers/xen/pcifront/Makefile linux-2.6-xen-sparse/drivers/xen/pcifront/pci.c linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c linux-2.6-xen-sparse/drivers/xen/pcifront/pcifront.h linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pci.h linux-2.6-xen-sparse/include/xen/pcifront.h xen/include/public/io/pciif.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/i386/Kconfig	Thu Feb 16 23:37:40 2006 +0100
     1.2 +++ b/linux-2.6-xen-sparse/arch/i386/Kconfig	Thu Feb 16 23:44:41 2006 +0100
     1.3 @@ -997,6 +997,13 @@ config PCI_GOMMCONFIG
     1.4  config PCI_GODIRECT
     1.5  	bool "Direct"
     1.6  
     1.7 +config PCI_GOXEN_FE
     1.8 +	bool "Xen PCI Frontend"
     1.9 +	depends on X86_XEN
    1.10 +	help
    1.11 +	  The PCI device frontend driver allows the kernel to import arbitrary
    1.12 +	  PCI devices from a PCI backend to support PCI driver domains.
    1.13 +
    1.14  config PCI_GOANY
    1.15  	bool "Any"
    1.16  
    1.17 @@ -1017,6 +1024,18 @@ config PCI_MMCONFIG
    1.18  	depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
    1.19  	default y
    1.20  
    1.21 +config XEN_PCIDEV_FRONTEND
    1.22 +	bool
    1.23 +	depends on PCI && X86_XEN && (PCI_GOXEN_FE || PCI_GOANY)
    1.24 +	default y
    1.25 +
    1.26 +config XEN_PCIDEV_FE_DEBUG
    1.27 +	bool "Xen PCI Frontend Debugging"
    1.28 +	depends on XEN_PCIDEV_FRONTEND
    1.29 +	default n
    1.30 +	help
    1.31 +	  Enables some debug statements within the PCI Frontend.
    1.32 +
    1.33  source "drivers/pci/pcie/Kconfig"
    1.34  
    1.35  source "drivers/pci/Kconfig"
     2.1 --- a/linux-2.6-xen-sparse/arch/i386/pci/Makefile	Thu Feb 16 23:37:40 2006 +0100
     2.2 +++ b/linux-2.6-xen-sparse/arch/i386/pci/Makefile	Thu Feb 16 23:44:41 2006 +0100
     2.3 @@ -4,6 +4,10 @@ obj-$(CONFIG_PCI_BIOS)		+= pcbios.o
     2.4  obj-$(CONFIG_PCI_MMCONFIG)	+= mmconfig.o direct.o
     2.5  obj-$(CONFIG_PCI_DIRECT)	+= direct.o
     2.6  
     2.7 +# pcifront should be after pcbios.o, mmconfig.o, and direct.o as it should only
     2.8 +# take over if direct access to the PCI bus is unavailable
     2.9 +obj-$(CONFIG_XEN_PCIDEV_FRONTEND)	+= pcifront.o
    2.10 +
    2.11  pci-y				:= fixup.o
    2.12  pci-$(CONFIG_ACPI)		+= acpi.o
    2.13  pci-y				+= legacy.o irq.o
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/linux-2.6-xen-sparse/arch/i386/pci/pcifront.c	Thu Feb 16 23:44:41 2006 +0100
     3.3 @@ -0,0 +1,55 @@
     3.4 +/*
     3.5 + * PCI Frontend Stub - puts some "dummy" functions in to the Linux x86 PCI core
     3.6 + *                     to support the Xen PCI Frontend's operation
     3.7 + *
     3.8 + *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
     3.9 + */
    3.10 +#include <linux/module.h>
    3.11 +#include <linux/init.h>
    3.12 +#include <linux/pci.h>
    3.13 +#include <asm/acpi.h>
    3.14 +#include "pci.h"
    3.15 +
    3.16 +static int pcifront_enable_irq(struct pci_dev *dev)
    3.17 +{
    3.18 +	u8 irq;
    3.19 +	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
    3.20 +	dev->irq = irq;
    3.21 +
    3.22 +	return 0;
    3.23 +}
    3.24 +
    3.25 +extern u8 pci_cache_line_size;
    3.26 +
    3.27 +static int __init pcifront_x86_stub_init(void)
    3.28 +{
    3.29 +	struct cpuinfo_x86 *c = &boot_cpu_data;
    3.30 +
    3.31 +	/* Only install our method if we haven't found real hardware already */
    3.32 +	if (raw_pci_ops)
    3.33 +		return 0;
    3.34 +
    3.35 +	printk(KERN_INFO "PCI: setting up Xen PCI frontend stub\n");
    3.36 +
    3.37 +	/* Copied from arch/i386/pci/common.c */
    3.38 +	pci_cache_line_size = 32 >> 2;
    3.39 +	if (c->x86 >= 6 && c->x86_vendor == X86_VENDOR_AMD)
    3.40 +		pci_cache_line_size = 64 >> 2;	/* K7 & K8 */
    3.41 +	else if (c->x86 > 6 && c->x86_vendor == X86_VENDOR_INTEL)
    3.42 +		pci_cache_line_size = 128 >> 2;	/* P4 */
    3.43 +
    3.44 +	/* On x86, we need to disable the normal IRQ routing table and
    3.45 +	 * just ask the backend
    3.46 +	 */
    3.47 +	pcibios_enable_irq = pcifront_enable_irq;
    3.48 +	pcibios_disable_irq = NULL;
    3.49 +
    3.50 +#ifdef CONFIG_ACPI
    3.51 +	/* Keep ACPI out of the picture */
    3.52 +	acpi_noirq = 1;
    3.53 +#endif
    3.54 +
    3.55 +	return 0;
    3.56 +}
    3.57 +
    3.58 +arch_initcall(pcifront_x86_stub_init);
     4.1 --- a/linux-2.6-xen-sparse/arch/x86_64/Kconfig	Thu Feb 16 23:37:40 2006 +0100
     4.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/Kconfig	Thu Feb 16 23:44:41 2006 +0100
     4.3 @@ -550,6 +550,21 @@ config PCI_MMCONFIG
     4.4  	bool "Support mmconfig PCI config space access"
     4.5  	depends on PCI && ACPI
     4.6  
     4.7 +config XEN_PCIDEV_FRONTEND
     4.8 +	bool "Xen PCI Frontend"
     4.9 +	depends on PCI && X86_64_XEN
    4.10 +	default y
    4.11 +	help
    4.12 +	  The PCI device frontend driver allows the kernel to import arbitrary
    4.13 +	  PCI devices from a PCI backend to support PCI driver domains.
    4.14 +
    4.15 +config XEN_PCIDEV_FE_DEBUG
    4.16 +	bool "Xen PCI Frontend Debugging"
    4.17 +	depends on XEN_PCIDEV_FRONTEND
    4.18 +	default n
    4.19 +	help
    4.20 +	  Enables some debug statements within the PCI Frontend.
    4.21 +
    4.22  config UNORDERED_IO
    4.23         bool "Unordered IO mapping access"
    4.24         depends on EXPERIMENTAL
     5.1 --- a/linux-2.6-xen-sparse/arch/x86_64/pci/Makefile	Thu Feb 16 23:37:40 2006 +0100
     5.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/pci/Makefile	Thu Feb 16 23:44:41 2006 +0100
     5.3 @@ -15,8 +15,13 @@ obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o
     5.4  
     5.5  obj-$(CONFIG_NUMA)	+= k8-bus.o
     5.6  
     5.7 +# pcifront should be after mmconfig.o and direct.o as it should only
     5.8 +# take over if direct access to the PCI bus is unavailable
     5.9 +obj-$(CONFIG_XEN_PCIDEV_FRONTEND)	+= pcifront.o
    5.10 +
    5.11  direct-y += ../../i386/pci/direct.o
    5.12  acpi-y   += ../../i386/pci/acpi.o
    5.13 +pcifront-y += ../../i386/pci/pcifront.o
    5.14  legacy-y += ../../i386/pci/legacy.o
    5.15  irq-y    += ../../i386/pci/irq.o
    5.16  common-y += ../../i386/pci/common.o
    5.17 @@ -25,7 +30,6 @@ i386-y  += ../../i386/pci/i386.o
    5.18  
    5.19  ifdef CONFIG_XEN
    5.20  irq-y		:= ../../i386/pci/irq-xen.o
    5.21 -i386-y		:= ../../i386/pci/i386.o
    5.22  include $(srctree)/scripts/Makefile.xen
    5.23  
    5.24  obj-y := $(call cherrypickxen, $(obj-y))
     6.1 --- a/linux-2.6-xen-sparse/drivers/xen/Kconfig	Thu Feb 16 23:37:40 2006 +0100
     6.2 +++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig	Thu Feb 16 23:44:41 2006 +0100
     6.3 @@ -29,6 +29,44 @@ config XEN_UNPRIVILEGED_GUEST
     6.4  	bool
     6.5  	default !XEN_PRIVILEGED_GUEST
     6.6  
     6.7 +config XEN_PCIDEV_BACKEND
     6.8 +	bool "PCI device backend driver"
     6.9 +	select PCI
    6.10 +	default y if XEN_PRIVILEGED_GUEST
    6.11 +	help
    6.12 +	  The PCI device backend driver allows the kernel to export arbitrary
    6.13 +	  PCI devices to other guests.
    6.14 +
    6.15 +choice
    6.16 +	prompt "PCI Backend Mode"
    6.17 +	depends on XEN_PCIDEV_BACKEND
    6.18 +	default XEN_PCIDEV_BACKEND_VPCI
    6.19 +
    6.20 +config XEN_PCIDEV_BACKEND_VPCI
    6.21 +	bool "Virtual PCI"
    6.22 +	---help---
    6.23 +	  This PCI Backend hides the true PCI topology and makes the frontend
    6.24 +	  think there is a single PCI bus with only the exported devices on it.
    6.25 +	  For example, a device at 03:05.0 will be re-assigned to 00:00.0. A
    6.26 +	  second device at 02:1a.0 will be re-assigned to 00:01.0.
    6.27 +
    6.28 +config XEN_PCIDEV_BACKEND_PASS
    6.29 +	bool "Passthrough"
    6.30 +	---help---
    6.31 +	  This PCI Backend provides a real view of the PCI topology to the
    6.32 +	  frontend (for example, a device at 06:01.b will still appear at
    6.33 +	  06:01.b to the frontend). This is similar to how Xen 2.0.x exposed
    6.34 +	  PCI devices to its driver domains. This may be required for drivers
    6.35 +	  which depend on finding their hardward in certain bus/slot
    6.36 +	  locations.
    6.37 +
    6.38 +endchoice
    6.39 +
    6.40 +config XEN_PCIDEV_BE_DEBUG
    6.41 +	bool "PCI Backend Debugging"
    6.42 +	depends on XEN_PCIDEV_BACKEND
    6.43 +	default n
    6.44 +
    6.45  config XEN_BLKDEV_BACKEND
    6.46  	bool "Block-device backend driver"
    6.47  	default y
     7.1 --- a/linux-2.6-xen-sparse/drivers/xen/Makefile	Thu Feb 16 23:37:40 2006 +0100
     7.2 +++ b/linux-2.6-xen-sparse/drivers/xen/Makefile	Thu Feb 16 23:44:41 2006 +0100
     7.3 @@ -17,4 +17,6 @@ obj-$(CONFIG_XEN_BLKDEV_FRONTEND)	+= blk
     7.4  obj-$(CONFIG_XEN_NETDEV_FRONTEND)	+= netfront/
     7.5  obj-$(CONFIG_XEN_BLKDEV_TAP)    	+= blktap/
     7.6  obj-$(CONFIG_XEN_TPMDEV_FRONTEND)	+= tpmfront/
     7.7 +obj-$(CONFIG_XEN_PCIDEV_BACKEND)	+= pciback/
     7.8 +obj-$(CONFIG_XEN_PCIDEV_FRONTEND)	+= pcifront/
     7.9  
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/Makefile	Thu Feb 16 23:44:41 2006 +0100
     8.3 @@ -0,0 +1,10 @@
     8.4 +obj-y += pciback.o
     8.5 +
     8.6 +pciback-y := pci_stub.o pciback_ops.o xenbus.o
     8.7 +pciback-y += conf_space.o conf_space_header.o
     8.8 +pciback-${CONFIG_XEN_PCIDEV_BACKEND_VPCI} += vpci.o
     8.9 +pciback-${CONFIG_XEN_PCIDEV_BACKEND_PASS} += passthrough.o
    8.10 +
    8.11 +ifeq ($(CONFIG_XEN_PCIDEV_BE_DEBUG),y)
    8.12 +EXTRA_CFLAGS += -DDEBUG
    8.13 +endif
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c	Thu Feb 16 23:44:41 2006 +0100
     9.3 @@ -0,0 +1,324 @@
     9.4 +/*
     9.5 + * PCI Backend - Functions for creating a virtual configuration space for
     9.6 + *               exported PCI Devices.
     9.7 + *               It's dangerous to allow PCI Driver Domains to change their
     9.8 + *               device's resources (memory, i/o ports, interrupts). We need to
     9.9 + *               restrict changes to certain PCI Configuration registers:
    9.10 + *               BARs, INTERRUPT_PIN, most registers in the header...
    9.11 + *
    9.12 + * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
    9.13 + */
    9.14 +
    9.15 +#include <linux/kernel.h>
    9.16 +#include <linux/pci.h>
    9.17 +#include "pciback.h"
    9.18 +#include "conf_space.h"
    9.19 +
    9.20 +#define DEFINE_PCI_CONFIG(op,size,type) 					\
    9.21 +int pciback_##op##_config_##size 							\
    9.22 +(struct pci_dev *dev, int offset, type value, void *data)	\
    9.23 +{															\
    9.24 +	return pci_##op##_config_##size (dev, offset, value);	\
    9.25 +}
    9.26 +
    9.27 +DEFINE_PCI_CONFIG(read, byte, u8 *)
    9.28 +DEFINE_PCI_CONFIG(read, word, u16 *)
    9.29 +DEFINE_PCI_CONFIG(read, dword, u32 *)
    9.30 +
    9.31 +DEFINE_PCI_CONFIG(write, byte, u8)
    9.32 +DEFINE_PCI_CONFIG(write, word, u16)
    9.33 +DEFINE_PCI_CONFIG(write, dword, u32)
    9.34 +
    9.35 +static int conf_space_read(struct pci_dev *dev,
    9.36 +			   struct config_field_entry *entry, int offset,
    9.37 +			   u32 * value)
    9.38 +{
    9.39 +	int ret = 0;
    9.40 +	struct config_field *field = entry->field;
    9.41 +
    9.42 +	*value = 0;
    9.43 +
    9.44 +	switch (field->size) {
    9.45 +	case 1:
    9.46 +		if (field->u.b.read)
    9.47 +			ret = field->u.b.read(dev, offset, (u8 *) value,
    9.48 +					      entry->data);
    9.49 +		break;
    9.50 +	case 2:
    9.51 +		if (field->u.w.read)
    9.52 +			ret = field->u.w.read(dev, offset, (u16 *) value,
    9.53 +					      entry->data);
    9.54 +		break;
    9.55 +	case 4:
    9.56 +		if (field->u.dw.read)
    9.57 +			ret = field->u.dw.read(dev, offset, value, entry->data);
    9.58 +		break;
    9.59 +	}
    9.60 +	return ret;
    9.61 +}
    9.62 +
    9.63 +static int conf_space_write(struct pci_dev *dev,
    9.64 +			    struct config_field_entry *entry, int offset,
    9.65 +			    u32 value)
    9.66 +{
    9.67 +	int ret = 0;
    9.68 +	struct config_field *field = entry->field;
    9.69 +
    9.70 +	switch (field->size) {
    9.71 +	case 1:
    9.72 +		if (field->u.b.write)
    9.73 +			ret = field->u.b.write(dev, offset, (u8) value,
    9.74 +					       entry->data);
    9.75 +		break;
    9.76 +	case 2:
    9.77 +		if (field->u.w.write)
    9.78 +			ret = field->u.w.write(dev, offset, (u16) value,
    9.79 +					       entry->data);
    9.80 +		break;
    9.81 +	case 4:
    9.82 +		if (field->u.dw.write)
    9.83 +			ret = field->u.dw.write(dev, offset, value,
    9.84 +					        entry->data);
    9.85 +		break;
    9.86 +	}
    9.87 +	return ret;
    9.88 +}
    9.89 +
    9.90 +static inline u32 get_mask(int size)
    9.91 +{
    9.92 +	if (size == 1)
    9.93 +		return 0xff;
    9.94 +	else if (size == 2)
    9.95 +		return 0xffff;
    9.96 +	else
    9.97 +		return 0xffffffff;
    9.98 +}
    9.99 +
   9.100 +static inline int valid_request(int offset, int size)
   9.101 +{
   9.102 +	/* Validate request (no un-aligned requests) */
   9.103 +	if ((size == 1 || size == 2 || size == 4) && (offset % size) == 0)
   9.104 +		return 1;
   9.105 +	return 0;
   9.106 +}
   9.107 +
   9.108 +static inline u32 merge_value(u32 val, u32 new_val, u32 new_val_mask,
   9.109 +			      u32 offset)
   9.110 +{
   9.111 +	if (offset >= 0) {
   9.112 +		new_val_mask <<= (offset * 8);
   9.113 +		new_val <<= (offset * 8);
   9.114 +	} else {
   9.115 +		new_val_mask >>= (offset * -8);
   9.116 +		new_val >>= (offset * -8);
   9.117 +	}
   9.118 +	val = (val & ~new_val_mask) | (new_val & new_val_mask);
   9.119 +
   9.120 +	return val;
   9.121 +}
   9.122 +
   9.123 +static int pcibios_err_to_errno(int err)
   9.124 +{
   9.125 +	switch (err) {
   9.126 +	case PCIBIOS_SUCCESSFUL:
   9.127 +		return XEN_PCI_ERR_success;
   9.128 +	case PCIBIOS_DEVICE_NOT_FOUND:
   9.129 +		return XEN_PCI_ERR_dev_not_found;
   9.130 +	case PCIBIOS_BAD_REGISTER_NUMBER:
   9.131 +		return XEN_PCI_ERR_invalid_offset;
   9.132 +	case PCIBIOS_FUNC_NOT_SUPPORTED:
   9.133 +		return XEN_PCI_ERR_not_implemented;
   9.134 +	case PCIBIOS_SET_FAILED:
   9.135 +		return XEN_PCI_ERR_access_denied;
   9.136 +	}
   9.137 +	return err;
   9.138 +}
   9.139 +
   9.140 +int pciback_config_read(struct pci_dev *dev, int offset, int size,
   9.141 +			u32 * ret_val)
   9.142 +{
   9.143 +	int err = 0;
   9.144 +	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
   9.145 +	struct config_field_entry *cfg_entry;
   9.146 +	struct config_field *field;
   9.147 +	int req_start, req_end, field_start, field_end;
   9.148 +	/* if read fails for any reason, return 0 (as if device didn't respond) */
   9.149 +	u32 value = 0, tmp_val;
   9.150 +
   9.151 +	if (unlikely(verbose_request))
   9.152 +		printk(KERN_DEBUG "pciback: %s: read %d bytes at 0x%x\n",
   9.153 +		       pci_name(dev), size, offset);
   9.154 +
   9.155 +	if (!valid_request(offset, size)) {
   9.156 +		err = XEN_PCI_ERR_invalid_offset;
   9.157 +		goto out;
   9.158 +	}
   9.159 +
   9.160 +	/* Get the real value first, then modify as appropriate */
   9.161 +	switch (size) {
   9.162 +	case 1:
   9.163 +		err = pci_read_config_byte(dev, offset, (u8 *) & value);
   9.164 +		break;
   9.165 +	case 2:
   9.166 +		err = pci_read_config_word(dev, offset, (u16 *) & value);
   9.167 +		break;
   9.168 +	case 4:
   9.169 +		err = pci_read_config_dword(dev, offset, &value);
   9.170 +		break;
   9.171 +	}
   9.172 +
   9.173 +	list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
   9.174 +		field = cfg_entry->field;
   9.175 +
   9.176 +		req_start = offset;
   9.177 +		req_end = offset + size;
   9.178 +		field_start = field->offset;
   9.179 +		field_end = field->offset + field->size;
   9.180 +
   9.181 +		if ((req_start >= field_start && req_start < field_end)
   9.182 +		    || (req_end > field_start && req_end <= field_end)) {
   9.183 +			err = conf_space_read(dev, cfg_entry, offset, &tmp_val);
   9.184 +			if (err)
   9.185 +				goto out;
   9.186 +
   9.187 +			value = merge_value(value, tmp_val,
   9.188 +					    get_mask(field->size),
   9.189 +					    field_start - req_start);
   9.190 +		}
   9.191 +	}
   9.192 +
   9.193 +      out:
   9.194 +	if (unlikely(verbose_request))
   9.195 +		printk(KERN_DEBUG "pciback: %s: read %d bytes at 0x%x = %x\n",
   9.196 +		       pci_name(dev), size, offset, value);
   9.197 +
   9.198 +	*ret_val = value;
   9.199 +	return pcibios_err_to_errno(err);
   9.200 +}
   9.201 +
   9.202 +int pciback_config_write(struct pci_dev *dev, int offset, int size, u32 value)
   9.203 +{
   9.204 +	int err = 0;
   9.205 +	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
   9.206 +	struct config_field_entry *cfg_entry;
   9.207 +	struct config_field *field;
   9.208 +	u32 tmp_val;
   9.209 +	int req_start, req_end, field_start, field_end;
   9.210 +
   9.211 +	if (unlikely(verbose_request))
   9.212 +		printk(KERN_DEBUG
   9.213 +		       "pciback: %s: write request %d bytes at 0x%x = %x\n",
   9.214 +		       pci_name(dev), size, offset, value);
   9.215 +
   9.216 +	if (!valid_request(offset, size))
   9.217 +		return XEN_PCI_ERR_invalid_offset;
   9.218 +
   9.219 +	list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
   9.220 +		field = cfg_entry->field;
   9.221 +
   9.222 +		req_start = offset;
   9.223 +		req_end = offset + size;
   9.224 +		field_start = field->offset;
   9.225 +		field_end = field->offset + field->size;
   9.226 +
   9.227 +		if ((req_start >= field_start && req_start < field_end)
   9.228 +		    || (req_end > field_start && req_end <= field_end)) {
   9.229 +			tmp_val = 0;
   9.230 +
   9.231 +			err = pciback_config_read(dev, offset, size, &tmp_val);
   9.232 +			if (err)
   9.233 +				break;
   9.234 +
   9.235 +			tmp_val = merge_value(tmp_val, value, get_mask(size),
   9.236 +					      field_start - req_start);
   9.237 +
   9.238 +			err = conf_space_write(dev, cfg_entry, offset, tmp_val);
   9.239 +		}
   9.240 +	}
   9.241 +
   9.242 +	return pcibios_err_to_errno(err);
   9.243 +}
   9.244 +
   9.245 +void pciback_config_reset(struct pci_dev *dev)
   9.246 +{
   9.247 +	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
   9.248 +	struct config_field_entry *cfg_entry;
   9.249 +	struct config_field *field;
   9.250 +
   9.251 +	list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
   9.252 +		field = cfg_entry->field;
   9.253 +
   9.254 +		if (field->reset)
   9.255 +			field->reset(dev, field->offset, cfg_entry->data);
   9.256 +	}
   9.257 +}
   9.258 +
   9.259 +void pciback_config_free(struct pci_dev *dev)
   9.260 +{
   9.261 +	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
   9.262 +	struct config_field_entry *cfg_entry, *t;
   9.263 +	struct config_field *field;
   9.264 +
   9.265 +	list_for_each_entry_safe(cfg_entry, t, &dev_data->config_fields, list) {
   9.266 +		list_del(&cfg_entry->list);
   9.267 +
   9.268 +		field = cfg_entry->field;
   9.269 +
   9.270 +		if (field->release)
   9.271 +			field->release(dev, field->offset, cfg_entry->data);
   9.272 +
   9.273 +		kfree(cfg_entry);
   9.274 +	}
   9.275 +}
   9.276 +
   9.277 +int pciback_config_add_field(struct pci_dev *dev, struct config_field *field)
   9.278 +{
   9.279 +	int err = 0;
   9.280 +	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
   9.281 +	struct config_field_entry *cfg_entry;
   9.282 +	void *tmp;
   9.283 +
   9.284 +	cfg_entry = kmalloc(sizeof(*cfg_entry), GFP_KERNEL);
   9.285 +	if (!cfg_entry) {
   9.286 +		err = -ENOMEM;
   9.287 +		goto out;
   9.288 +	}
   9.289 +
   9.290 +	cfg_entry->data = NULL;
   9.291 +	cfg_entry->field = field;
   9.292 +
   9.293 +	if (field->init) {
   9.294 +		tmp = field->init(dev, field->offset);
   9.295 +
   9.296 +		if (IS_ERR(tmp)) {
   9.297 +			err = PTR_ERR(tmp);
   9.298 +			goto out;
   9.299 +		}
   9.300 +
   9.301 +		cfg_entry->data = tmp;
   9.302 +	}
   9.303 +
   9.304 +	list_add_tail(&cfg_entry->list, &dev_data->config_fields);
   9.305 +
   9.306 +      out:
   9.307 +	if (err)
   9.308 +		kfree(cfg_entry);
   9.309 +
   9.310 +	return err;
   9.311 +}
   9.312 +
   9.313 +/* This sets up the device's virtual configuration space to keep track of 
   9.314 + * certain registers (like the base address registers (BARs) so that we can
   9.315 + * keep the client from manipulating them directly.
   9.316 + */
   9.317 +int pciback_config_init(struct pci_dev *dev)
   9.318 +{
   9.319 +	int err = 0;
   9.320 +	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
   9.321 +
   9.322 +	INIT_LIST_HEAD(&dev_data->config_fields);
   9.323 +
   9.324 +	err = pciback_config_header_add_fields(dev);
   9.325 +
   9.326 +	return err;
   9.327 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.h	Thu Feb 16 23:44:41 2006 +0100
    10.3 @@ -0,0 +1,97 @@
    10.4 +/*
    10.5 + * PCI Backend - Common data structures for overriding the configuration space
    10.6 + *
    10.7 + * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
    10.8 + */
    10.9 +
   10.10 +#ifndef __XEN_PCIBACK_CONF_SPACE_H__
   10.11 +#define __XEN_PCIBACK_CONF_SPACE_H__
   10.12 +
   10.13 +#include <linux/list.h>
   10.14 +
   10.15 +typedef void *(*conf_field_init) (struct pci_dev * dev, int offset);
   10.16 +typedef void (*conf_field_reset) (struct pci_dev * dev, int offset, void *data);
   10.17 +typedef void (*conf_field_free) (struct pci_dev * dev, int offset, void *data);
   10.18 +
   10.19 +typedef int (*conf_dword_write) (struct pci_dev * dev, int offset, u32 value,
   10.20 +				 void *data);
   10.21 +typedef int (*conf_word_write) (struct pci_dev * dev, int offset, u16 value,
   10.22 +				void *data);
   10.23 +typedef int (*conf_byte_write) (struct pci_dev * dev, int offset, u8 value,
   10.24 +				void *data);
   10.25 +typedef int (*conf_dword_read) (struct pci_dev * dev, int offset, u32 * value,
   10.26 +				void *data);
   10.27 +typedef int (*conf_word_read) (struct pci_dev * dev, int offset, u16 * value,
   10.28 +			       void *data);
   10.29 +typedef int (*conf_byte_read) (struct pci_dev * dev, int offset, u8 * value,
   10.30 +			       void *data);
   10.31 +
   10.32 +/* These are the fields within the configuration space which we
   10.33 + * are interested in intercepting reads/writes to and changing their
   10.34 + * values.
   10.35 + */
   10.36 +struct config_field {
   10.37 +	unsigned int     offset;
   10.38 +	unsigned int     size;
   10.39 +	conf_field_init  init;
   10.40 +	conf_field_reset reset;
   10.41 +	conf_field_free  release;
   10.42 +	union {
   10.43 +		struct {
   10.44 +			conf_dword_write write;
   10.45 +			conf_dword_read read;
   10.46 +		} dw;
   10.47 +		struct {
   10.48 +			conf_word_write write;
   10.49 +			conf_word_read read;
   10.50 +		} w;
   10.51 +		struct {
   10.52 +			conf_byte_write write;
   10.53 +			conf_byte_read read;
   10.54 +		} b;
   10.55 +	} u;
   10.56 +};
   10.57 +
   10.58 +struct config_field_entry {
   10.59 +	struct list_head list;
   10.60 +	struct config_field *field;
   10.61 +	void *data;
   10.62 +};
   10.63 +
   10.64 +/* Add fields to a device - the add_fields macro expects to get a pointer to
   10.65 + * the first entry in an array (of which the ending is marked by size==0)
   10.66 + */
   10.67 +int pciback_config_add_field(struct pci_dev *dev, struct config_field *field);
   10.68 +static inline int pciback_config_add_fields(struct pci_dev *dev,
   10.69 +					    struct config_field *field)
   10.70 +{
   10.71 +	int i, err = 0;
   10.72 +	for (i = 0; field[i].size != 0; i++) {
   10.73 +		err = pciback_config_add_field(dev, &field[i]);
   10.74 +		if (err)
   10.75 +			break;
   10.76 +	}
   10.77 +	return err;
   10.78 +}
   10.79 +
   10.80 +/* Initializers which add fields to the virtual configuration space
   10.81 + * ** We could add initializers to allow a guest domain to touch
   10.82 + * the capability lists (for power management, the AGP bridge, etc.)
   10.83 + */
   10.84 +int pciback_config_header_add_fields(struct pci_dev *dev);
   10.85 +
   10.86 +/* Read/Write the real configuration space */
   10.87 +int pciback_read_config_byte(struct pci_dev *dev, int offset, u8 * value,
   10.88 +			     void *data);
   10.89 +int pciback_read_config_word(struct pci_dev *dev, int offset, u16 * value,
   10.90 +			     void *data);
   10.91 +int pciback_read_config_dword(struct pci_dev *dev, int offset, u32 * value,
   10.92 +			      void *data);
   10.93 +int pciback_write_config_byte(struct pci_dev *dev, int offset, u8 value,
   10.94 +			      void *data);
   10.95 +int pciback_write_config_word(struct pci_dev *dev, int offset, u16 value,
   10.96 +			      void *data);
   10.97 +int pciback_write_config_dword(struct pci_dev *dev, int offset, u32 value,
   10.98 +			       void *data);
   10.99 +
  10.100 +#endif				/* __XEN_PCIBACK_CONF_SPACE_H__ */
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_header.c	Thu Feb 16 23:44:41 2006 +0100
    11.3 @@ -0,0 +1,269 @@
    11.4 +/*
    11.5 + * PCI Backend - Handles the virtual fields in the configuration space headers.
    11.6 + *
    11.7 + * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
    11.8 + */
    11.9 +
   11.10 +#include <linux/kernel.h>
   11.11 +#include <linux/pci.h>
   11.12 +#include "pciback.h"
   11.13 +#include "conf_space.h"
   11.14 +
   11.15 +struct pci_bar_info {
   11.16 +	u32 val;
   11.17 +	u32 len_val;
   11.18 +	int which;
   11.19 +};
   11.20 +
   11.21 +#define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO))
   11.22 +#define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER)
   11.23 +
   11.24 +static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
   11.25 +{
   11.26 +	if (!dev->is_enabled && is_enable_cmd(value)) {
   11.27 +		if (unlikely(verbose_request))
   11.28 +			printk(KERN_DEBUG "pciback: %s: enable\n",
   11.29 +			       pci_name(dev));
   11.30 +		dev->is_enabled = 1;
   11.31 +		pcibios_enable_device(dev, (1 << PCI_NUM_RESOURCES) - 1);
   11.32 +	} else if (dev->is_enabled && !is_enable_cmd(value)) {
   11.33 +		if (unlikely(verbose_request))
   11.34 +			printk(KERN_DEBUG "pciback: %s: disable\n",
   11.35 +			       pci_name(dev));
   11.36 +		pciback_disable_device(dev);
   11.37 +	}
   11.38 +
   11.39 +	if (!dev->is_busmaster && is_master_cmd(value)) {
   11.40 +		if (unlikely(verbose_request))
   11.41 +			printk(KERN_DEBUG "pciback: %s: set bus master\n",
   11.42 +			       pci_name(dev));
   11.43 +		dev->is_busmaster = 1;
   11.44 +		pcibios_set_master(dev);
   11.45 +	}
   11.46 +
   11.47 +	if (value & PCI_COMMAND_INVALIDATE) {
   11.48 +		if (unlikely(verbose_request))
   11.49 +			printk(KERN_DEBUG
   11.50 +			       "pciback: %s: enable memory-write-invalidate\n",
   11.51 +			       pci_name(dev));
   11.52 +		pci_set_mwi(dev);
   11.53 +	}
   11.54 +
   11.55 +	return pci_write_config_word(dev, offset, value);
   11.56 +}
   11.57 +
   11.58 +static int rom_write(struct pci_dev *dev, int offset, u32 value, void *data)
   11.59 +{
   11.60 +	struct pci_bar_info *bar = data;
   11.61 +
   11.62 +	if (unlikely(!bar)) {
   11.63 +		printk(KERN_WARNING "pciback: driver data not found for %s\n",
   11.64 +		       pci_name(dev));
   11.65 +		return XEN_PCI_ERR_op_failed;
   11.66 +	}
   11.67 +
   11.68 +	/* A write to obtain the length must happen as a 32-bit write.
   11.69 +	 * This does not (yet) support writing individual bytes
   11.70 +	 */
   11.71 +	if (value == ~PCI_ROM_ADDRESS_ENABLE)
   11.72 +		bar->which = 1;
   11.73 +	else
   11.74 +		bar->which = 0;
   11.75 +
   11.76 +	/* Do we need to support enabling/disabling the rom address here? */
   11.77 +
   11.78 +	return 0;
   11.79 +}
   11.80 +
   11.81 +/* For the BARs, only allow writes which write ~0 or
   11.82 + * the correct resource information
   11.83 + * (Needed for when the driver probes the resource usage)
   11.84 + */
   11.85 +static int bar_write(struct pci_dev *dev, int offset, u32 value, void *data)
   11.86 +{
   11.87 +	struct pci_bar_info *bar = data;
   11.88 +
   11.89 +	if (unlikely(!bar)) {
   11.90 +		printk(KERN_WARNING "pciback: driver data not found for %s\n",
   11.91 +		       pci_name(dev));
   11.92 +		return XEN_PCI_ERR_op_failed;
   11.93 +	}
   11.94 +
   11.95 +	/* A write to obtain the length must happen as a 32-bit write.
   11.96 +	 * This does not (yet) support writing individual bytes
   11.97 +	 */
   11.98 +	if (value == ~0)
   11.99 +		bar->which = 1;
  11.100 +	else
  11.101 +		bar->which = 0;
  11.102 +
  11.103 +	return 0;
  11.104 +}
  11.105 +
  11.106 +static int bar_read(struct pci_dev *dev, int offset, u32 * value, void *data)
  11.107 +{
  11.108 +	struct pci_bar_info *bar = data;
  11.109 +
  11.110 +	if (unlikely(!bar)) {
  11.111 +		printk(KERN_WARNING "pciback: driver data not found for %s\n",
  11.112 +		       pci_name(dev));
  11.113 +		return XEN_PCI_ERR_op_failed;
  11.114 +	}
  11.115 +
  11.116 +	*value = bar->which ? bar->len_val : bar->val;
  11.117 +
  11.118 +	return 0;
  11.119 +}
  11.120 +
  11.121 +static inline void read_dev_bar(struct pci_dev *dev,
  11.122 +				struct pci_bar_info *bar_info, int offset,
  11.123 +				u32 len_mask)
  11.124 +{
  11.125 +	pci_read_config_dword(dev, offset, &bar_info->val);
  11.126 +	pci_write_config_dword(dev, offset, len_mask);
  11.127 +	pci_read_config_dword(dev, offset, &bar_info->len_val);
  11.128 +	pci_write_config_dword(dev, offset, bar_info->val);
  11.129 +}
  11.130 +
  11.131 +static void *bar_init(struct pci_dev *dev, int offset)
  11.132 +{
  11.133 +	struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL);
  11.134 +
  11.135 +	if (!bar)
  11.136 +		return ERR_PTR(-ENOMEM);
  11.137 +
  11.138 +	read_dev_bar(dev, bar, offset, ~0);
  11.139 +	bar->which = 0;
  11.140 +
  11.141 +	return bar;
  11.142 +}
  11.143 +
  11.144 +static void *rom_init(struct pci_dev *dev, int offset)
  11.145 +{
  11.146 +	struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL);
  11.147 +
  11.148 +	if (!bar)
  11.149 +		return ERR_PTR(-ENOMEM);
  11.150 +
  11.151 +	read_dev_bar(dev, bar, offset, ~PCI_ROM_ADDRESS_ENABLE);
  11.152 +	bar->which = 0;
  11.153 +
  11.154 +	return bar;
  11.155 +}
  11.156 +
  11.157 +static void bar_reset(struct pci_dev *dev, int offset, void *data)
  11.158 +{
  11.159 +	struct pci_bar_info *bar = data;
  11.160 +
  11.161 +	bar->which = 0;
  11.162 +}
  11.163 +
  11.164 +static void bar_release(struct pci_dev *dev, int offset, void *data)
  11.165 +{
  11.166 +	kfree(data);
  11.167 +}
  11.168 +
  11.169 +static int interrupt_read(struct pci_dev *dev, int offset, u8 * value,
  11.170 +			  void *data)
  11.171 +{
  11.172 +	*value = (u8) dev->irq;
  11.173 +
  11.174 +	return 0;
  11.175 +}
  11.176 +
  11.177 +struct config_field header_common[] = {
  11.178 +	{
  11.179 +	 .offset    = PCI_COMMAND,
  11.180 +	 .size      = 2,
  11.181 +	 .u.w.read  = pciback_read_config_word,
  11.182 +	 .u.w.write = command_write,
  11.183 +	 },
  11.184 +	{
  11.185 +	 .offset    = PCI_INTERRUPT_LINE,
  11.186 +	 .size      = 1,
  11.187 +	 .u.b.read  = interrupt_read,
  11.188 +	 .u.b.write = NULL,
  11.189 +	 },
  11.190 +	{
  11.191 +	 /* Any side effects of letting driver domain control cache line? */
  11.192 +	 .offset    = PCI_CACHE_LINE_SIZE,
  11.193 +	 .size      = 1,
  11.194 +	 .u.b.read  = pciback_read_config_byte,
  11.195 +	 .u.b.write = pciback_write_config_byte,
  11.196 +	 },
  11.197 +	{
  11.198 +	 .size = 0,
  11.199 +	 },
  11.200 +};
  11.201 +
  11.202 +#define CFG_FIELD_BAR(reg_offset) 			\
  11.203 +	{ 						\
  11.204 +	 .offset     = reg_offset, 			\
  11.205 +	 .size       = 4, 				\
  11.206 +	 .init       = bar_init, 			\
  11.207 +	 .reset      = bar_reset, 			\
  11.208 +	 .release    = bar_release, 			\
  11.209 +	 .u.dw.read  = bar_read, 			\
  11.210 +	 .u.dw.write = bar_write, 			\
  11.211 +	 }
  11.212 +
  11.213 +#define CFG_FIELD_ROM(reg_offset) 			\
  11.214 +	{ 						\
  11.215 +	 .offset     = reg_offset, 			\
  11.216 +	 .size       = 4, 				\
  11.217 +	 .init       = rom_init, 			\
  11.218 +	 .reset      = bar_reset, 			\
  11.219 +	 .release    = bar_release, 			\
  11.220 +	 .u.dw.read  = bar_read, 			\
  11.221 +	 .u.dw.write = rom_write, 			\
  11.222 +	 }
  11.223 +
  11.224 +struct config_field header_0[] = {
  11.225 +	CFG_FIELD_BAR(PCI_BASE_ADDRESS_0),
  11.226 +	CFG_FIELD_BAR(PCI_BASE_ADDRESS_1),
  11.227 +	CFG_FIELD_BAR(PCI_BASE_ADDRESS_2),
  11.228 +	CFG_FIELD_BAR(PCI_BASE_ADDRESS_3),
  11.229 +	CFG_FIELD_BAR(PCI_BASE_ADDRESS_4),
  11.230 +	CFG_FIELD_BAR(PCI_BASE_ADDRESS_5),
  11.231 +	CFG_FIELD_ROM(PCI_ROM_ADDRESS),
  11.232 +	{
  11.233 +	 .size = 0,
  11.234 +	 },
  11.235 +};
  11.236 +
  11.237 +struct config_field header_1[] = {
  11.238 +	CFG_FIELD_BAR(PCI_BASE_ADDRESS_0),
  11.239 +	CFG_FIELD_BAR(PCI_BASE_ADDRESS_1),
  11.240 +	CFG_FIELD_ROM(PCI_ROM_ADDRESS1),
  11.241 +	{
  11.242 +	 .size = 0,
  11.243 +	 },
  11.244 +};
  11.245 +
  11.246 +int pciback_config_header_add_fields(struct pci_dev *dev)
  11.247 +{
  11.248 +	int err;
  11.249 +
  11.250 +	err = pciback_config_add_fields(dev, header_common);
  11.251 +	if (err)
  11.252 +		goto out;
  11.253 +
  11.254 +	switch (dev->hdr_type) {
  11.255 +	case PCI_HEADER_TYPE_NORMAL:
  11.256 +		err = pciback_config_add_fields(dev, header_0);
  11.257 +		break;
  11.258 +
  11.259 +	case PCI_HEADER_TYPE_BRIDGE:
  11.260 +		err = pciback_config_add_fields(dev, header_1);
  11.261 +		break;
  11.262 +
  11.263 +	default:
  11.264 +		err = -EINVAL;
  11.265 +		printk(KERN_ERR "pciback: %s: Unsupported header type %d!\n",
  11.266 +		       pci_name(dev), dev->hdr_type);
  11.267 +		break;
  11.268 +	}
  11.269 +
  11.270 +      out:
  11.271 +	return err;
  11.272 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/passthrough.c	Thu Feb 16 23:44:41 2006 +0100
    12.3 @@ -0,0 +1,116 @@
    12.4 +/*
    12.5 + * PCI Backend - Provides restricted access to the real PCI bus topology
    12.6 + *               to the frontend
    12.7 + *
    12.8 + *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
    12.9 + */
   12.10 +
   12.11 +#include <linux/list.h>
   12.12 +#include <linux/pci.h>
   12.13 +#include "pciback.h"
   12.14 +
   12.15 +struct passthrough_dev_data {
   12.16 +	struct list_head dev_list;
   12.17 +};
   12.18 +
   12.19 +struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
   12.20 +				    unsigned int domain, unsigned int bus,
   12.21 +				    unsigned int devfn)
   12.22 +{
   12.23 +	struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
   12.24 +	struct pci_dev_entry *dev_entry;
   12.25 +
   12.26 +	list_for_each_entry(dev_entry, &dev_data->dev_list, list) {
   12.27 +		if (domain == (unsigned int)pci_domain_nr(dev_entry->dev->bus)
   12.28 +		    && bus == (unsigned int)dev_entry->dev->bus->number
   12.29 +		    && devfn == dev_entry->dev->devfn)
   12.30 +			return dev_entry->dev;
   12.31 +	}
   12.32 +
   12.33 +	return NULL;
   12.34 +}
   12.35 +
   12.36 +/* Must hold pciback_device->dev_lock when calling this */
   12.37 +int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
   12.38 +{
   12.39 +	struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
   12.40 +	struct pci_dev_entry *dev_entry;
   12.41 +
   12.42 +	dev_entry = kmalloc(sizeof(*dev_entry), GFP_KERNEL);
   12.43 +	if (!dev_entry)
   12.44 +		return -ENOMEM;
   12.45 +	dev_entry->dev = dev;
   12.46 +
   12.47 +	list_add_tail(&dev_entry->list, &dev_data->dev_list);
   12.48 +
   12.49 +	return 0;
   12.50 +}
   12.51 +
   12.52 +int pciback_init_devices(struct pciback_device *pdev)
   12.53 +{
   12.54 +	struct passthrough_dev_data *dev_data;
   12.55 +
   12.56 +	dev_data = kmalloc(sizeof(*dev_data), GFP_KERNEL);
   12.57 +	if (!dev_data)
   12.58 +		return -ENOMEM;
   12.59 +
   12.60 +	INIT_LIST_HEAD(&dev_data->dev_list);
   12.61 +
   12.62 +	pdev->pci_dev_data = dev_data;
   12.63 +
   12.64 +	return 0;
   12.65 +}
   12.66 +
   12.67 +int pciback_publish_pci_roots(struct pciback_device *pdev,
   12.68 +			      publish_pci_root_cb publish_root_cb)
   12.69 +{
   12.70 +	int err = 0;
   12.71 +	struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
   12.72 +	struct pci_dev_entry *dev_entry, *e;
   12.73 +	struct pci_dev *dev;
   12.74 +	int found;
   12.75 +	unsigned int domain, bus;
   12.76 +
   12.77 +	list_for_each_entry(dev_entry, &dev_data->dev_list, list) {
   12.78 +		/* Only publish this device as a root if none of its
   12.79 +		 * parent bridges are exported
   12.80 +		 */
   12.81 +		found = 0;
   12.82 +		dev = dev_entry->dev->bus->self;
   12.83 +		for (; !found && dev != NULL; dev = dev->bus->self) {
   12.84 +			list_for_each_entry(e, &dev_data->dev_list, list) {
   12.85 +				if (dev == e->dev) {
   12.86 +					found = 1;
   12.87 +					break;
   12.88 +				}
   12.89 +			}
   12.90 +		}
   12.91 +
   12.92 +		domain = (unsigned int)pci_domain_nr(dev_entry->dev->bus);
   12.93 +		bus = (unsigned int)dev_entry->dev->bus->number;
   12.94 +
   12.95 +		if (!found) {
   12.96 +			err = publish_root_cb(pdev, domain, bus);
   12.97 +			if (err)
   12.98 +				break;
   12.99 +		}
  12.100 +	}
  12.101 +
  12.102 +	return err;
  12.103 +}
  12.104 +
  12.105 +/* Must hold pciback_device->dev_lock when calling this */
  12.106 +void pciback_release_devices(struct pciback_device *pdev)
  12.107 +{
  12.108 +	struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
  12.109 +	struct pci_dev_entry *dev_entry, *t;
  12.110 +
  12.111 +	list_for_each_entry_safe(dev_entry, t, &dev_data->dev_list, list) {
  12.112 +		list_del(&dev_entry->list);
  12.113 +		pcistub_put_pci_dev(dev_entry->dev);
  12.114 +		kfree(dev_entry);
  12.115 +	}
  12.116 +
  12.117 +	kfree(dev_data);
  12.118 +	pdev->pci_dev_data = NULL;
  12.119 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c	Thu Feb 16 23:44:41 2006 +0100
    13.3 @@ -0,0 +1,377 @@
    13.4 +/*
    13.5 + * PCI Stub Driver - Grabs devices in backend to be exported later
    13.6 + *
    13.7 + *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
    13.8 + */
    13.9 +#include <linux/module.h>
   13.10 +#include <linux/init.h>
   13.11 +#include <linux/list.h>
   13.12 +#include <linux/spinlock.h>
   13.13 +#include <asm/atomic.h>
   13.14 +#include "pciback.h"
   13.15 +
   13.16 +static char *pci_devs_to_hide = NULL;
   13.17 +module_param_named(hide, pci_devs_to_hide, charp, 0444);
   13.18 +
   13.19 +struct pci_stub_device_id {
   13.20 +	struct list_head slot_list;
   13.21 +	int domain;
   13.22 +	unsigned char bus;
   13.23 +	unsigned int devfn;
   13.24 +};
   13.25 +LIST_HEAD(pci_stub_device_ids);
   13.26 +
   13.27 +struct pci_stub_device {
   13.28 +	struct list_head dev_list;
   13.29 +	struct pci_dev *dev;
   13.30 +	atomic_t in_use;
   13.31 +};
   13.32 +/* Access to pci_stub_devices & seized_devices lists and the initialize_devices
   13.33 + * flag must be locked with pci_stub_devices_lock
   13.34 + */
   13.35 +DEFINE_SPINLOCK(pci_stub_devices_lock);
   13.36 +LIST_HEAD(pci_stub_devices);
   13.37 +
   13.38 +/* wait for device_initcall before initializing our devices
   13.39 + * (see pcistub_init_devices_late)
   13.40 + */
   13.41 +static int initialize_devices = 0;
   13.42 +LIST_HEAD(seized_devices);
   13.43 +
   13.44 +static inline struct pci_dev *get_pci_dev(struct pci_stub_device *psdev)
   13.45 +{
   13.46 +	if (atomic_dec_and_test(&psdev->in_use))
   13.47 +		return psdev->dev;
   13.48 +	else {
   13.49 +		atomic_inc(&psdev->in_use);
   13.50 +		return NULL;
   13.51 +	}
   13.52 +}
   13.53 +
   13.54 +struct pci_dev *pcistub_get_pci_dev_by_slot(int domain, int bus,
   13.55 +					    int slot, int func)
   13.56 +{
   13.57 +	struct pci_stub_device *psdev;
   13.58 +	struct pci_dev *found_dev = NULL;
   13.59 +
   13.60 +	spin_lock(&pci_stub_devices_lock);
   13.61 +
   13.62 +	list_for_each_entry(psdev, &pci_stub_devices, dev_list) {
   13.63 +		if (psdev->dev != NULL
   13.64 +		    && domain == pci_domain_nr(psdev->dev->bus)
   13.65 +		    && bus == psdev->dev->bus->number
   13.66 +		    && PCI_DEVFN(slot, func) == psdev->dev->devfn) {
   13.67 +			found_dev = get_pci_dev(psdev);
   13.68 +			break;
   13.69 +		}
   13.70 +	}
   13.71 +
   13.72 +	spin_unlock(&pci_stub_devices_lock);
   13.73 +	return found_dev;
   13.74 +}
   13.75 +
   13.76 +struct pci_dev *pcistub_get_pci_dev(struct pci_dev *dev)
   13.77 +{
   13.78 +	struct pci_stub_device *psdev;
   13.79 +	struct pci_dev *found_dev = NULL;
   13.80 +
   13.81 +	spin_lock(&pci_stub_devices_lock);
   13.82 +
   13.83 +	list_for_each_entry(psdev, &pci_stub_devices, dev_list) {
   13.84 +		if (psdev->dev == dev) {
   13.85 +			found_dev = get_pci_dev(psdev);
   13.86 +			break;
   13.87 +		}
   13.88 +	}
   13.89 +
   13.90 +	spin_unlock(&pci_stub_devices_lock);
   13.91 +	return found_dev;
   13.92 +}
   13.93 +
   13.94 +void pcistub_put_pci_dev(struct pci_dev *dev)
   13.95 +{
   13.96 +	struct pci_stub_device *psdev;
   13.97 +
   13.98 +	spin_lock(&pci_stub_devices_lock);
   13.99 +
  13.100 +	list_for_each_entry(psdev, &pci_stub_devices, dev_list) {
  13.101 +		if (psdev->dev == dev) {
  13.102 +			/* Cleanup our device
  13.103 +			 * (so it's ready for the next domain)
  13.104 +			 */
  13.105 +			pciback_reset_device(psdev->dev);
  13.106 +
  13.107 +			atomic_inc(&psdev->in_use);
  13.108 +			break;
  13.109 +		}
  13.110 +	}
  13.111 +
  13.112 +	spin_unlock(&pci_stub_devices_lock);
  13.113 +}
  13.114 +
  13.115 +static int __devinit pcistub_match(struct pci_dev *dev,
  13.116 +				   struct pci_stub_device_id *pdev_id)
  13.117 +{
  13.118 +	/* Match the specified device by domain, bus, slot, func and also if
  13.119 +	 * any of the device's parent bridges match.
  13.120 +	 */
  13.121 +	for (; dev != NULL; dev = dev->bus->self) {
  13.122 +		if (pci_domain_nr(dev->bus) == pdev_id->domain
  13.123 +		    && dev->bus->number == pdev_id->bus
  13.124 +		    && dev->devfn == pdev_id->devfn)
  13.125 +			return 1;
  13.126 +	}
  13.127 +
  13.128 +	return 0;
  13.129 +}
  13.130 +
  13.131 +static int __devinit pcistub_init_device(struct pci_dev *dev)
  13.132 +{
  13.133 +	struct pciback_dev_data *dev_data;
  13.134 +	int err = 0;
  13.135 +
  13.136 +	/* The PCI backend is not intended to be a module (or to work with
  13.137 +	 * removable PCI devices (yet). If it were, pciback_config_free()
  13.138 +	 * would need to be called somewhere to free the memory allocated
  13.139 +	 * here and then to call kfree(pci_get_drvdata(psdev->dev)).
  13.140 +	 */
  13.141 +	dev_data = kmalloc(sizeof(*dev_data), GFP_KERNEL);
  13.142 +	if (!dev_data) {
  13.143 +		err = -ENOMEM;
  13.144 +		goto out;
  13.145 +	}
  13.146 +	pci_set_drvdata(dev, dev_data);
  13.147 +
  13.148 +	err = pciback_config_init(dev);
  13.149 +	if (err)
  13.150 +		goto out;
  13.151 +
  13.152 +	/* HACK: Force device (& ACPI) to determine what IRQ it's on - we
  13.153 +	 * must do this here because pcibios_enable_device may specify
  13.154 +	 * the pci device's true irq (and possibly its other resources)
  13.155 +	 * if they differ from what's in the configuration space.
  13.156 +	 * This makes the assumption that the device's resources won't
  13.157 +	 * change after this point (otherwise this code may break!)
  13.158 +	 */
  13.159 +	err = pci_enable_device(dev);
  13.160 +	if (err)
  13.161 +		goto config_release;
  13.162 +
  13.163 +	/* Now disable the device (this also ensures some private device
  13.164 +	 * data is setup before we export)
  13.165 +	 * This calls pciback_config_reset(dev)
  13.166 +	 */
  13.167 +	pciback_reset_device(dev);
  13.168 +
  13.169 +	return 0;
  13.170 +
  13.171 +      config_release:
  13.172 +	pciback_config_free(dev);
  13.173 +
  13.174 +      out:
  13.175 +	pci_set_drvdata(dev, NULL);
  13.176 +	kfree(dev_data);
  13.177 +	return err;
  13.178 +}
  13.179 +
  13.180 +/*
  13.181 + * Because some initialization still happens on
  13.182 + * devices during fs_initcall, we need to defer
  13.183 + * full initialization of our devices until
  13.184 + * device_initcall.
  13.185 + */
  13.186 +static int __init pcistub_init_devices_late(void)
  13.187 +{
  13.188 +	struct pci_stub_device *psdev, *t;
  13.189 +	int err = 0;
  13.190 +
  13.191 +	spin_lock(&pci_stub_devices_lock);
  13.192 +
  13.193 +	list_for_each_entry_safe(psdev, t, &seized_devices, dev_list) {
  13.194 +		list_del(&psdev->dev_list);
  13.195 +		err = pcistub_init_device(psdev->dev);
  13.196 +		if (err) {
  13.197 +			printk(KERN_ERR
  13.198 +			       "pciback: %s error %d initializing device\n",
  13.199 +			       pci_name(psdev->dev), err);
  13.200 +			kfree(psdev);
  13.201 +			continue;
  13.202 +		}
  13.203 +
  13.204 +		list_add_tail(&psdev->dev_list, &pci_stub_devices);
  13.205 +	}
  13.206 +
  13.207 +	initialize_devices = 1;
  13.208 +
  13.209 +	spin_unlock(&pci_stub_devices_lock);
  13.210 +
  13.211 +	return 0;
  13.212 +}
  13.213 +
  13.214 +device_initcall(pcistub_init_devices_late);
  13.215 +
  13.216 +static int __devinit pcistub_seize(struct pci_dev *dev)
  13.217 +{
  13.218 +	struct pci_stub_device *psdev;
  13.219 +	int err = 0;
  13.220 +
  13.221 +	psdev = kmalloc(sizeof(*psdev), GFP_KERNEL);
  13.222 +	if (!psdev)
  13.223 +		return -ENOMEM;
  13.224 +
  13.225 +	psdev->dev = dev;
  13.226 +	atomic_set(&psdev->in_use, 1);
  13.227 +
  13.228 +	spin_lock(&pci_stub_devices_lock);
  13.229 +
  13.230 +	if (initialize_devices) {
  13.231 +		err = pcistub_init_device(psdev->dev);
  13.232 +		if (err)
  13.233 +			goto out;
  13.234 +
  13.235 +		list_add(&psdev->dev_list, &pci_stub_devices);
  13.236 +	} else
  13.237 +		list_add(&psdev->dev_list, &seized_devices);
  13.238 +
  13.239 +      out:
  13.240 +	spin_unlock(&pci_stub_devices_lock);
  13.241 +
  13.242 +	if (err)
  13.243 +		kfree(psdev);
  13.244 +
  13.245 +	return err;
  13.246 +}
  13.247 +
  13.248 +static int __devinit pcistub_probe(struct pci_dev *dev,
  13.249 +				   const struct pci_device_id *id)
  13.250 +{
  13.251 +	struct pci_stub_device_id *pdev_id;
  13.252 +	struct pci_dev *seized_dev;
  13.253 +	int err = 0;
  13.254 +
  13.255 +	list_for_each_entry(pdev_id, &pci_stub_device_ids, slot_list) {
  13.256 +
  13.257 +		if (!pcistub_match(dev, pdev_id))
  13.258 +			continue;
  13.259 +
  13.260 +		if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL
  13.261 +		    && dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
  13.262 +			printk(KERN_ERR
  13.263 +			       "pciback: %s: can't export pci devices that "
  13.264 +			       "don't have a normal (0) or bridge (1) "
  13.265 +			       "header type!\n", pci_name(dev));
  13.266 +			break;
  13.267 +		}
  13.268 +
  13.269 +		pr_info("pciback: seizing PCI device %s\n", pci_name(dev));
  13.270 +		seized_dev = pci_dev_get(dev);
  13.271 +
  13.272 +		if (seized_dev) {
  13.273 +			err = pcistub_seize(seized_dev);
  13.274 +			if (err) {
  13.275 +				pci_dev_put(dev);
  13.276 +				goto out;
  13.277 +			}
  13.278 +
  13.279 +			/* Success! */
  13.280 +			goto out;
  13.281 +		}
  13.282 +	}
  13.283 +
  13.284 +	/* Didn't find the device */
  13.285 +	err = -ENODEV;
  13.286 +
  13.287 +      out:
  13.288 +	return err;
  13.289 +}
  13.290 +
  13.291 +struct pci_device_id pcistub_ids[] = {
  13.292 +	{
  13.293 +	 .vendor = PCI_ANY_ID,
  13.294 +	 .device = PCI_ANY_ID,
  13.295 +	 .subvendor = PCI_ANY_ID,
  13.296 +	 .subdevice = PCI_ANY_ID,
  13.297 +	 },
  13.298 +	{0,},
  13.299 +};
  13.300 +
  13.301 +/*
  13.302 + * Note: There is no MODULE_DEVICE_TABLE entry here because this isn't
  13.303 + * for a normal device. I don't want it to be loaded automatically.
  13.304 + */
  13.305 +
  13.306 +struct pci_driver pciback_pci_driver = {
  13.307 +	.name = "pciback",
  13.308 +	.id_table = pcistub_ids,
  13.309 +	.probe = pcistub_probe,
  13.310 +};
  13.311 +
  13.312 +static int __init pcistub_init(void)
  13.313 +{
  13.314 +	int pos = 0;
  13.315 +	struct pci_stub_device_id *pci_dev_id;
  13.316 +	int err = 0;
  13.317 +	int domain, bus, slot, func;
  13.318 +	int parsed;
  13.319 +
  13.320 +	if (pci_devs_to_hide && *pci_devs_to_hide) {
  13.321 +		do {
  13.322 +			parsed = 0;
  13.323 +
  13.324 +			err = sscanf(pci_devs_to_hide + pos,
  13.325 +				     " (%x:%x:%x.%x) %n",
  13.326 +				     &domain, &bus, &slot, &func, &parsed);
  13.327 +			if (err != 4) {
  13.328 +				domain = 0;
  13.329 +				err = sscanf(pci_devs_to_hide + pos,
  13.330 +					     " (%x:%x.%x) %n",
  13.331 +					     &bus, &slot, &func, &parsed);
  13.332 +				if (err != 3)
  13.333 +					goto parse_error;
  13.334 +			}
  13.335 +
  13.336 +			pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL);
  13.337 +			if (!pci_dev_id) {
  13.338 +				err = -ENOMEM;
  13.339 +				goto out;
  13.340 +			}
  13.341 +
  13.342 +			pci_dev_id->domain = domain;
  13.343 +			pci_dev_id->bus = bus;
  13.344 +			pci_dev_id->devfn = PCI_DEVFN(slot, func);
  13.345 +
  13.346 +			pr_debug
  13.347 +			    ("pciback: wants to seize %04x:%02x:%02x.%01x\n",
  13.348 +			     domain, bus, slot, func);
  13.349 +
  13.350 +			list_add_tail(&pci_dev_id->slot_list,
  13.351 +				      &pci_stub_device_ids);
  13.352 +
  13.353 +			/* if parsed<=0, we've reached the end of the string */
  13.354 +			pos += parsed;
  13.355 +		} while (parsed > 0 && pci_devs_to_hide[pos]);
  13.356 +
  13.357 +		/* If we're the first PCI Device Driver to register, we're the
  13.358 +		 * first one to get offered PCI devices as they become
  13.359 +		 * available (and thus we can be the first to grab them)
  13.360 +		 */
  13.361 +		pci_register_driver(&pciback_pci_driver);
  13.362 +	}
  13.363 +
  13.364 +      out:
  13.365 +	return err;
  13.366 +
  13.367 +      parse_error:
  13.368 +	printk(KERN_ERR "pciback: Error parsing pci_devs_to_hide at \"%s\"\n",
  13.369 +	       pci_devs_to_hide + pos);
  13.370 +	return -EINVAL;
  13.371 +}
  13.372 +
  13.373 +/*
  13.374 + * fs_initcall happens before device_initcall
  13.375 + * so pciback *should* get called first (b/c we 
  13.376 + * want to suck up any device before other drivers
  13.377 + * get a chance by being the first pci device
  13.378 + * driver to register)
  13.379 + */
  13.380 +fs_initcall(pcistub_init);
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/pciback.h	Thu Feb 16 23:44:41 2006 +0100
    14.3 @@ -0,0 +1,73 @@
    14.4 +/*
    14.5 + * PCI Backend Common Data Structures & Function Declarations
    14.6 + *
    14.7 + *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
    14.8 + */
    14.9 +#ifndef __XEN_PCIBACK_H__
   14.10 +#define __XEN_PCIBACK_H__
   14.11 +
   14.12 +#include <linux/pci.h>
   14.13 +#include <linux/interrupt.h>
   14.14 +#include <xen/xenbus.h>
   14.15 +#include <linux/list.h>
   14.16 +#include <linux/spinlock.h>
   14.17 +#include <xen/interface/io/pciif.h>
   14.18 +
   14.19 +struct pci_dev_entry {
   14.20 +	struct list_head list;
   14.21 +	struct pci_dev *dev;
   14.22 +};
   14.23 +
   14.24 +struct pciback_device {
   14.25 +	void *pci_dev_data;
   14.26 +	spinlock_t dev_lock;
   14.27 +
   14.28 +	struct xenbus_device *xdev;
   14.29 +
   14.30 +	struct xenbus_watch be_watch;
   14.31 +	u8 be_watching;
   14.32 +
   14.33 +	int evtchn_irq;
   14.34 +
   14.35 +	struct xen_pci_sharedinfo *sh_info;
   14.36 +};
   14.37 +
   14.38 +struct pciback_dev_data {
   14.39 +	struct list_head config_fields;
   14.40 +};
   14.41 +
   14.42 +/* Get/Put PCI Devices that are hidden from the PCI Backend Domain */
   14.43 +struct pci_dev *pcistub_get_pci_dev_by_slot(int domain, int bus,
   14.44 +					    int slot, int func);
   14.45 +struct pci_dev *pcistub_get_pci_dev(struct pci_dev *dev);
   14.46 +void pcistub_put_pci_dev(struct pci_dev *dev);
   14.47 +
   14.48 +/* Ensure a device is turned off or reset */
   14.49 +void pciback_disable_device(struct pci_dev *dev);
   14.50 +void pciback_reset_device(struct pci_dev *pdev);
   14.51 +
   14.52 +/* Access a virtual configuration space for a PCI device */
   14.53 +int pciback_config_init(struct pci_dev *dev);
   14.54 +void pciback_config_reset(struct pci_dev *dev);
   14.55 +void pciback_config_free(struct pci_dev *dev);
   14.56 +int pciback_config_read(struct pci_dev *dev, int offset, int size,
   14.57 +			u32 * ret_val);
   14.58 +int pciback_config_write(struct pci_dev *dev, int offset, int size, u32 value);
   14.59 +
   14.60 +/* Handle requests for specific devices from the frontend */
   14.61 +typedef int (*publish_pci_root_cb) (struct pciback_device * pdev,
   14.62 +				    unsigned int domain, unsigned int bus);
   14.63 +int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev);
   14.64 +struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
   14.65 +				    unsigned int domain, unsigned int bus,
   14.66 +				    unsigned int devfn);
   14.67 +int pciback_init_devices(struct pciback_device *pdev);
   14.68 +int pciback_publish_pci_roots(struct pciback_device *pdev,
   14.69 +			      publish_pci_root_cb cb);
   14.70 +void pciback_release_devices(struct pciback_device *pdev);
   14.71 +
   14.72 +/* Handles events from front-end */
   14.73 +irqreturn_t pciback_handle_event(int irq, void *dev_id, struct pt_regs *regs);
   14.74 +
   14.75 +extern int verbose_request;
   14.76 +#endif
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/pciback_ops.c	Thu Feb 16 23:44:41 2006 +0100
    15.3 @@ -0,0 +1,84 @@
    15.4 +/*
    15.5 + * PCI Backend Operations - respond to PCI requests from Frontend
    15.6 + *
    15.7 + *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
    15.8 + */
    15.9 +#include <linux/module.h>
   15.10 +#include <asm/bitops.h>
   15.11 +#include "pciback.h"
   15.12 +
   15.13 +int verbose_request = 0;
   15.14 +module_param(verbose_request, int, 0644);
   15.15 +
   15.16 +/* For those architectures without a pcibios_disable_device */
   15.17 +void __attribute__ ((weak)) pcibios_disable_device(struct pci_dev *dev) { }
   15.18 +
   15.19 +void pciback_disable_device(struct pci_dev *dev)
   15.20 +{
   15.21 +	if (dev->is_enabled) {
   15.22 +		dev->is_enabled = 0;
   15.23 +		pcibios_disable_device(dev);
   15.24 +	}
   15.25 +}
   15.26 +
   15.27 +/* Ensure a device is "turned off" and ready to be exported.
   15.28 + * This also sets up the device's private data to keep track of what should
   15.29 + * be in the base address registers (BARs) so that we can keep the
   15.30 + * client from manipulating them directly.
   15.31 + */
   15.32 +void pciback_reset_device(struct pci_dev *dev)
   15.33 +{
   15.34 +	u16 cmd;
   15.35 +
   15.36 +	/* Disable devices (but not bridges) */
   15.37 +	if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) {
   15.38 +		pciback_disable_device(dev);
   15.39 +
   15.40 +		pci_write_config_word(dev, PCI_COMMAND, 0);
   15.41 +
   15.42 +		dev->is_enabled = 0;
   15.43 +		dev->is_busmaster = 0;
   15.44 +	} else {
   15.45 +		pci_read_config_word(dev, PCI_COMMAND, &cmd);
   15.46 +		if (cmd & (PCI_COMMAND_INVALIDATE)) {
   15.47 +			cmd &= ~(PCI_COMMAND_INVALIDATE);
   15.48 +			pci_write_config_word(dev, PCI_COMMAND, cmd);
   15.49 +
   15.50 +			dev->is_busmaster = 0;
   15.51 +		}
   15.52 +	}
   15.53 +
   15.54 +	pciback_config_reset(dev);
   15.55 +}
   15.56 +
   15.57 +irqreturn_t pciback_handle_event(int irq, void *dev_id, struct pt_regs *regs)
   15.58 +{
   15.59 +	struct pciback_device *pdev = dev_id;
   15.60 +	struct pci_dev *dev;
   15.61 +	struct xen_pci_op *op = &pdev->sh_info->op;
   15.62 +
   15.63 +	if (unlikely(!test_bit(_XEN_PCIF_active,
   15.64 +			       (unsigned long *)&pdev->sh_info->flags))) {
   15.65 +		pr_debug("pciback: interrupt, but no active operation\n");
   15.66 +		goto out;
   15.67 +	}
   15.68 +
   15.69 +	dev = pciback_get_pci_dev(pdev, op->domain, op->bus, op->devfn);
   15.70 +
   15.71 +	if (dev == NULL)
   15.72 +		op->err = XEN_PCI_ERR_dev_not_found;
   15.73 +	else if (op->cmd == XEN_PCI_OP_conf_read)
   15.74 +		op->err = pciback_config_read(dev, op->offset, op->size,
   15.75 +					      &op->value);
   15.76 +	else if (op->cmd == XEN_PCI_OP_conf_write)
   15.77 +		op->err = pciback_config_write(dev, op->offset, op->size,
   15.78 +					       op->value);
   15.79 +	else
   15.80 +		op->err = XEN_PCI_ERR_not_implemented;
   15.81 +
   15.82 +	wmb();
   15.83 +	clear_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags);
   15.84 +
   15.85 +      out:
   15.86 +	return IRQ_HANDLED;
   15.87 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/vpci.c	Thu Feb 16 23:44:41 2006 +0100
    16.3 @@ -0,0 +1,163 @@
    16.4 +/*
    16.5 + * PCI Backend - Provides a Virtual PCI bus (with real devices)
    16.6 + *               to the frontend
    16.7 + *
    16.8 + *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
    16.9 + */
   16.10 +
   16.11 +#include <linux/list.h>
   16.12 +#include <linux/slab.h>
   16.13 +#include <linux/pci.h>
   16.14 +#include "pciback.h"
   16.15 +
   16.16 +#define PCI_SLOT_MAX 32
   16.17 +
   16.18 +struct vpci_dev_data {
   16.19 +	struct list_head dev_list[PCI_SLOT_MAX];
   16.20 +};
   16.21 +
   16.22 +static inline struct list_head *list_first(struct list_head *head)
   16.23 +{
   16.24 +	return head->next;
   16.25 +}
   16.26 +
   16.27 +struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
   16.28 +				    unsigned int domain, unsigned int bus,
   16.29 +				    unsigned int devfn)
   16.30 +{
   16.31 +	struct pci_dev_entry *dev_entry;
   16.32 +	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
   16.33 +
   16.34 +	if (domain != 0 || bus != 0)
   16.35 +		return NULL;
   16.36 +
   16.37 +	if (PCI_SLOT(devfn) < PCI_SLOT_MAX) {
   16.38 +		/* we don't need to lock the list here because once the backend
   16.39 +		 * is in operation, it won't have any more devices addeded
   16.40 +		 * (or removed).
   16.41 +		 */
   16.42 +		list_for_each_entry(dev_entry,
   16.43 +				    &vpci_dev->dev_list[PCI_SLOT(devfn)],
   16.44 +				    list) {
   16.45 +			if (PCI_FUNC(dev_entry->dev->devfn) == PCI_FUNC(devfn))
   16.46 +				return dev_entry->dev;
   16.47 +		}
   16.48 +	}
   16.49 +	return NULL;
   16.50 +}
   16.51 +
   16.52 +static inline int match_slot(struct pci_dev *l, struct pci_dev *r)
   16.53 +{
   16.54 +	if (pci_domain_nr(l->bus) == pci_domain_nr(r->bus)
   16.55 +	    && l->bus == r->bus && PCI_SLOT(l->devfn) == PCI_SLOT(r->devfn))
   16.56 +		return 1;
   16.57 +
   16.58 +	return 0;
   16.59 +}
   16.60 +
   16.61 +/* Must hold pciback_device->dev_lock when calling this */
   16.62 +int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
   16.63 +{
   16.64 +	int err = 0, slot;
   16.65 +	struct pci_dev_entry *t, *dev_entry;
   16.66 +	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
   16.67 +
   16.68 +	if ((dev->class >> 24) == PCI_BASE_CLASS_BRIDGE) {
   16.69 +		err = -EFAULT;
   16.70 +		xenbus_dev_fatal(pdev->xdev, err,
   16.71 +				 "Can't export bridges on the virtual PCI bus");
   16.72 +		goto out;
   16.73 +	}
   16.74 +
   16.75 +	dev_entry = kmalloc(sizeof(*dev_entry), GFP_KERNEL);
   16.76 +	if (!dev_entry) {
   16.77 +		err = -ENOMEM;
   16.78 +		xenbus_dev_fatal(pdev->xdev, err,
   16.79 +				 "Error adding entry to virtual PCI bus");
   16.80 +		goto out;
   16.81 +	}
   16.82 +
   16.83 +	dev_entry->dev = dev;
   16.84 +
   16.85 +	/* Keep multi-function devices together on the virtual PCI bus */
   16.86 +	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
   16.87 +		if (!list_empty(&vpci_dev->dev_list[slot])) {
   16.88 +			t = list_entry(list_first(&vpci_dev->dev_list[slot]),
   16.89 +				       struct pci_dev_entry, list);
   16.90 +
   16.91 +			if (match_slot(dev, t->dev)) {
   16.92 +				pr_info("pciback: vpci: %s: "
   16.93 +					"assign to virtual slot %d func %d\n",
   16.94 +					pci_name(dev), slot,
   16.95 +					PCI_FUNC(dev->devfn));
   16.96 +				list_add_tail(&dev_entry->list,
   16.97 +					      &vpci_dev->dev_list[slot]);
   16.98 +				goto out;
   16.99 +			}
  16.100 +		}
  16.101 +	}
  16.102 +
  16.103 +	/* Assign to a new slot on the virtual PCI bus */
  16.104 +	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
  16.105 +		if (list_empty(&vpci_dev->dev_list[slot])) {
  16.106 +			printk(KERN_INFO
  16.107 +			       "pciback: vpci: %s: assign to virtual slot %d\n",
  16.108 +			       pci_name(dev), slot);
  16.109 +			list_add_tail(&dev_entry->list,
  16.110 +				      &vpci_dev->dev_list[slot]);
  16.111 +			goto out;
  16.112 +		}
  16.113 +	}
  16.114 +
  16.115 +	err = -ENOMEM;
  16.116 +	xenbus_dev_fatal(pdev->xdev, err,
  16.117 +			 "No more space on root virtual PCI bus");
  16.118 +
  16.119 +      out:
  16.120 +	return err;
  16.121 +}
  16.122 +
  16.123 +int pciback_init_devices(struct pciback_device *pdev)
  16.124 +{
  16.125 +	int slot;
  16.126 +	struct vpci_dev_data *vpci_dev;
  16.127 +
  16.128 +	vpci_dev = kmalloc(sizeof(*vpci_dev), GFP_KERNEL);
  16.129 +	if (!vpci_dev)
  16.130 +		return -ENOMEM;
  16.131 +
  16.132 +	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
  16.133 +		INIT_LIST_HEAD(&vpci_dev->dev_list[slot]);
  16.134 +	}
  16.135 +
  16.136 +	pdev->pci_dev_data = vpci_dev;
  16.137 +
  16.138 +	return 0;
  16.139 +}
  16.140 +
  16.141 +int pciback_publish_pci_roots(struct pciback_device *pdev,
  16.142 +			      publish_pci_root_cb publish_cb)
  16.143 +{
  16.144 +	/* The Virtual PCI bus has only one root */
  16.145 +	return publish_cb(pdev, 0, 0);
  16.146 +}
  16.147 +
  16.148 +/* Must hold pciback_device->dev_lock when calling this */
  16.149 +void pciback_release_devices(struct pciback_device *pdev)
  16.150 +{
  16.151 +	int slot;
  16.152 +	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
  16.153 +
  16.154 +	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
  16.155 +		struct pci_dev_entry *e, *tmp;
  16.156 +		list_for_each_entry_safe(e, tmp, &vpci_dev->dev_list[slot],
  16.157 +					 list) {
  16.158 +			list_del(&e->list);
  16.159 +			pcistub_put_pci_dev(e->dev);
  16.160 +			kfree(e);
  16.161 +		}
  16.162 +	}
  16.163 +
  16.164 +	kfree(vpci_dev);
  16.165 +	pdev->pci_dev_data = NULL;
  16.166 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c	Thu Feb 16 23:44:41 2006 +0100
    17.3 @@ -0,0 +1,439 @@
    17.4 +/*
    17.5 + * PCI Backend Xenbus Setup - handles setup with frontend and xend
    17.6 + *
    17.7 + *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
    17.8 + */
    17.9 +#include <linux/module.h>
   17.10 +#include <linux/init.h>
   17.11 +#include <linux/list.h>
   17.12 +#include <xen/xenbus.h>
   17.13 +#include <xen/evtchn.h>
   17.14 +#include "pciback.h"
   17.15 +
   17.16 +#define INVALID_EVTCHN_IRQ  (-1)
   17.17 +
   17.18 +struct pciback_device *alloc_pdev(struct xenbus_device *xdev)
   17.19 +{
   17.20 +	struct pciback_device *pdev;
   17.21 +
   17.22 +	pdev = kmalloc(sizeof(struct pciback_device), GFP_KERNEL);
   17.23 +	if (pdev == NULL)
   17.24 +		goto out;
   17.25 +	dev_dbg(&xdev->dev, "allocated pdev @ 0x%p\n", pdev);
   17.26 +
   17.27 +	pdev->xdev = xdev;
   17.28 +	xdev->data = pdev;
   17.29 +
   17.30 +	spin_lock_init(&pdev->dev_lock);
   17.31 +
   17.32 +	pdev->sh_info = NULL;
   17.33 +	pdev->evtchn_irq = INVALID_EVTCHN_IRQ;
   17.34 +	pdev->be_watching = 0;
   17.35 +
   17.36 +	if (pciback_init_devices(pdev)) {
   17.37 +		kfree(pdev);
   17.38 +		pdev = NULL;
   17.39 +	}
   17.40 +      out:
   17.41 +	return pdev;
   17.42 +}
   17.43 +
   17.44 +void free_pdev(struct pciback_device *pdev)
   17.45 +{
   17.46 +	if (pdev->be_watching)
   17.47 +		unregister_xenbus_watch(&pdev->be_watch);
   17.48 +
   17.49 +	/* Ensure the guest can't trigger our handler before removing devices */
   17.50 +	if (pdev->evtchn_irq != INVALID_EVTCHN_IRQ)
   17.51 +		unbind_from_irqhandler(pdev->evtchn_irq, pdev);
   17.52 +
   17.53 +	if (pdev->sh_info)
   17.54 +		xenbus_unmap_ring_vfree(pdev->xdev, pdev->sh_info);
   17.55 +
   17.56 +	pciback_release_devices(pdev);
   17.57 +
   17.58 +	pdev->xdev->data = NULL;
   17.59 +	pdev->xdev = NULL;
   17.60 +
   17.61 +	kfree(pdev);
   17.62 +}
   17.63 +
   17.64 +static int pciback_do_attach(struct pciback_device *pdev, int gnt_ref,
   17.65 +			     int remote_evtchn)
   17.66 +{
   17.67 +	int err = 0;
   17.68 +	int evtchn;
   17.69 +	dev_dbg(&pdev->xdev->dev,
   17.70 +		"Attaching to frontend resources - gnt_ref=%d evtchn=%d\n",
   17.71 +		gnt_ref, remote_evtchn);
   17.72 +
   17.73 +	err =
   17.74 +	    xenbus_map_ring_valloc(pdev->xdev, gnt_ref,
   17.75 +				   (void **)&pdev->sh_info);
   17.76 +	if (err)
   17.77 +		goto out;
   17.78 +
   17.79 +	err = xenbus_bind_evtchn(pdev->xdev, remote_evtchn, &evtchn);
   17.80 +	if (err)
   17.81 +		goto out;
   17.82 +
   17.83 +	err = bind_evtchn_to_irqhandler(evtchn, pciback_handle_event,
   17.84 +					SA_SAMPLE_RANDOM, "pciback", pdev);
   17.85 +	if (err < 0) {
   17.86 +		xenbus_dev_fatal(pdev->xdev, err,
   17.87 +				 "Error binding event channel to IRQ");
   17.88 +		goto out;
   17.89 +	}
   17.90 +	pdev->evtchn_irq = err;
   17.91 +	err = 0;
   17.92 +
   17.93 +	dev_dbg(&pdev->xdev->dev, "Attached!\n");
   17.94 +      out:
   17.95 +	return err;
   17.96 +}
   17.97 +
   17.98 +static int pciback_attach(struct pciback_device *pdev)
   17.99 +{
  17.100 +	int err = 0;
  17.101 +	int gnt_ref, remote_evtchn;
  17.102 +	char *magic = NULL;
  17.103 +
  17.104 +	spin_lock(&pdev->dev_lock);
  17.105 +
  17.106 +	/* Make sure we only do this setup once */
  17.107 +	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
  17.108 +	    XenbusStateInitialised)
  17.109 +		goto out;
  17.110 +
  17.111 +	/* Wait for frontend to state that it has published the configuration */
  17.112 +	if (xenbus_read_driver_state(pdev->xdev->otherend) !=
  17.113 +	    XenbusStateInitialised)
  17.114 +		goto out;
  17.115 +
  17.116 +	dev_dbg(&pdev->xdev->dev, "Reading frontend config\n");
  17.117 +
  17.118 +	err = xenbus_gather(XBT_NULL, pdev->xdev->otherend,
  17.119 +			    "pci-op-ref", "%u", &gnt_ref,
  17.120 +			    "event-channel", "%u", &remote_evtchn,
  17.121 +			    "magic", NULL, &magic, NULL);
  17.122 +	if (err) {
  17.123 +		/* If configuration didn't get read correctly, wait longer */
  17.124 +		xenbus_dev_fatal(pdev->xdev, err,
  17.125 +				 "Error reading configuration from frontend");
  17.126 +		goto out;
  17.127 +	}
  17.128 +
  17.129 +	if (magic == NULL || strcmp(magic, XEN_PCI_MAGIC) != 0) {
  17.130 +		xenbus_dev_fatal(pdev->xdev, -EFAULT,
  17.131 +				 "version mismatch (%s/%s) with pcifront - "
  17.132 +				 "halting pciback",
  17.133 +				 magic, XEN_PCI_MAGIC);
  17.134 +		goto out;
  17.135 +	}
  17.136 +
  17.137 +	err = pciback_do_attach(pdev, gnt_ref, remote_evtchn);
  17.138 +	if (err)
  17.139 +		goto out;
  17.140 +
  17.141 +	dev_dbg(&pdev->xdev->dev, "Connecting...\n");
  17.142 +
  17.143 +	err = xenbus_switch_state(pdev->xdev, XBT_NULL, XenbusStateConnected);
  17.144 +	if (err)
  17.145 +		xenbus_dev_fatal(pdev->xdev, err,
  17.146 +				 "Error switching to connected state!");
  17.147 +
  17.148 +	dev_dbg(&pdev->xdev->dev, "Connected? %d\n", err);
  17.149 +      out:
  17.150 +	spin_unlock(&pdev->dev_lock);
  17.151 +
  17.152 +	if (magic)
  17.153 +		kfree(magic);
  17.154 +
  17.155 +	return err;
  17.156 +}
  17.157 +
  17.158 +static void pciback_frontend_changed(struct xenbus_device *xdev,
  17.159 +				     XenbusState fe_state)
  17.160 +{
  17.161 +	struct pciback_device *pdev = xdev->data;
  17.162 +
  17.163 +	dev_dbg(&xdev->dev, "fe state changed %d\n", fe_state);
  17.164 +
  17.165 +	switch (fe_state) {
  17.166 +	case XenbusStateInitialised:
  17.167 +		pciback_attach(pdev);
  17.168 +		break;
  17.169 +
  17.170 +	case XenbusStateClosing:
  17.171 +		xenbus_switch_state(xdev, XBT_NULL, XenbusStateClosing);
  17.172 +		break;
  17.173 +
  17.174 +	case XenbusStateClosed:
  17.175 +		dev_dbg(&xdev->dev, "frontend is gone! unregister device\n");
  17.176 +		device_unregister(&xdev->dev);
  17.177 +		break;
  17.178 +
  17.179 +	default:
  17.180 +		break;
  17.181 +	}
  17.182 +}
  17.183 +
  17.184 +static int pciback_publish_pci_root(struct pciback_device *pdev,
  17.185 +				    unsigned int domain, unsigned int bus)
  17.186 +{
  17.187 +	unsigned int d, b;
  17.188 +	int i, root_num, len, err;
  17.189 +	char str[64];
  17.190 +
  17.191 +	dev_dbg(&pdev->xdev->dev, "Publishing pci roots\n");
  17.192 +
  17.193 +	err = xenbus_scanf(XBT_NULL, pdev->xdev->nodename,
  17.194 +			   "root_num", "%d", &root_num);
  17.195 +	if (err == 0 || err == -ENOENT)
  17.196 +		root_num = 0;
  17.197 +	else if (err < 0)
  17.198 +		goto out;
  17.199 +
  17.200 +	/* Verify that we haven't already published this pci root */
  17.201 +	for (i = 0; i < root_num; i++) {
  17.202 +		len = snprintf(str, sizeof(str), "root-%d", i);
  17.203 +		if (unlikely(len >= (sizeof(str) - 1))) {
  17.204 +			err = -ENOMEM;
  17.205 +			goto out;
  17.206 +		}
  17.207 +
  17.208 +		err = xenbus_scanf(XBT_NULL, pdev->xdev->nodename,
  17.209 +				   str, "%x:%x", &d, &b);
  17.210 +		if (err < 0)
  17.211 +			goto out;
  17.212 +		if (err != 2) {
  17.213 +			err = -EINVAL;
  17.214 +			goto out;
  17.215 +		}
  17.216 +
  17.217 +		if (d == domain && b == bus) {
  17.218 +			err = 0;
  17.219 +			goto out;
  17.220 +		}
  17.221 +	}
  17.222 +
  17.223 +	len = snprintf(str, sizeof(str), "root-%d", root_num);
  17.224 +	if (unlikely(len >= (sizeof(str) - 1))) {
  17.225 +		err = -ENOMEM;
  17.226 +		goto out;
  17.227 +	}
  17.228 +
  17.229 +	dev_dbg(&pdev->xdev->dev, "writing root %d at %04x:%02x\n",
  17.230 +		root_num, domain, bus);
  17.231 +
  17.232 +	err = xenbus_printf(XBT_NULL, pdev->xdev->nodename, str,
  17.233 +			    "%04x:%02x", domain, bus);
  17.234 +	if (err)
  17.235 +		goto out;
  17.236 +
  17.237 +	err = xenbus_printf(XBT_NULL, pdev->xdev->nodename,
  17.238 +			    "root_num", "%d", (root_num + 1));
  17.239 +
  17.240 +      out:
  17.241 +	return err;
  17.242 +}
  17.243 +
  17.244 +static int pciback_export_device(struct pciback_device *pdev,
  17.245 +				 int domain, int bus, int slot, int func)
  17.246 +{
  17.247 +	struct pci_dev *dev;
  17.248 +	int err = 0;
  17.249 +
  17.250 +	dev_dbg(&pdev->xdev->dev, "exporting dom %x bus %x slot %x func %x\n",
  17.251 +		domain, bus, slot, func);
  17.252 +
  17.253 +	dev = pcistub_get_pci_dev_by_slot(domain, bus, slot, func);
  17.254 +	if (!dev) {
  17.255 +		err = -EINVAL;
  17.256 +		xenbus_dev_fatal(pdev->xdev, err,
  17.257 +				 "Couldn't locate PCI device "
  17.258 +				 "(%04x:%02x:%02x.%01x)! "
  17.259 +				 "perhaps already in-use?",
  17.260 +				 domain, bus, slot, func);
  17.261 +		goto out;
  17.262 +	}
  17.263 +
  17.264 +	err = pciback_add_pci_dev(pdev, dev);
  17.265 +	if (err)
  17.266 +		goto out;
  17.267 +
  17.268 +	/* TODO: It'd be nice to export a bridge and have all of its children
  17.269 +	 * get exported with it. This may be best done in xend (which will
  17.270 +	 * have to calculate resource usage anyway) but we probably want to
  17.271 +	 * put something in here to ensure that if a bridge gets given to a
  17.272 +	 * driver domain, that all devices under that bridge are not given
  17.273 +	 * to other driver domains (as he who controls the bridge can disable
  17.274 +	 * it and stop the other devices from working).
  17.275 +	 */
  17.276 +      out:
  17.277 +	return err;
  17.278 +}
  17.279 +
  17.280 +static int pciback_setup_backend(struct pciback_device *pdev)
  17.281 +{
  17.282 +	/* Get configuration from xend (if available now) */
  17.283 +	int domain, bus, slot, func;
  17.284 +	int err = 0;
  17.285 +	int i, num_devs;
  17.286 +	char dev_str[64];
  17.287 +
  17.288 +	spin_lock(&pdev->dev_lock);
  17.289 +
  17.290 +	/* It's possible we could get the call to setup twice, so make sure
  17.291 +	 * we're not already connected.
  17.292 +	 */
  17.293 +	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
  17.294 +	    XenbusStateInitWait)
  17.295 +		goto out;
  17.296 +
  17.297 +	dev_dbg(&pdev->xdev->dev, "getting be setup\n");
  17.298 +
  17.299 +	err = xenbus_scanf(XBT_NULL, pdev->xdev->nodename, "num_devs", "%d",
  17.300 +			   &num_devs);
  17.301 +	if (err != 1) {
  17.302 +		if (err >= 0)
  17.303 +			err = -EINVAL;
  17.304 +		xenbus_dev_fatal(pdev->xdev, err,
  17.305 +				 "Error reading number of devices");
  17.306 +		goto out;
  17.307 +	}
  17.308 +
  17.309 +	for (i = 0; i < num_devs; i++) {
  17.310 +		int l = snprintf(dev_str, sizeof(dev_str), "dev-%d", i);
  17.311 +		if (unlikely(l >= (sizeof(dev_str) - 1))) {
  17.312 +			err = -ENOMEM;
  17.313 +			xenbus_dev_fatal(pdev->xdev, err,
  17.314 +					 "String overflow while reading "
  17.315 +					 "configuration");
  17.316 +			goto out;
  17.317 +		}
  17.318 +
  17.319 +		err = xenbus_scanf(XBT_NULL, pdev->xdev->nodename, dev_str,
  17.320 +				   "%x:%x:%x.%x", &domain, &bus, &slot, &func);
  17.321 +		if (err < 0) {
  17.322 +			xenbus_dev_fatal(pdev->xdev, err,
  17.323 +					 "Error reading device configuration");
  17.324 +			goto out;
  17.325 +		}
  17.326 +		if (err != 4) {
  17.327 +			err = -EINVAL;
  17.328 +			xenbus_dev_fatal(pdev->xdev, err,
  17.329 +					 "Error parsing pci device "
  17.330 +					 "configuration");
  17.331 +			goto out;
  17.332 +		}
  17.333 +
  17.334 +		err = pciback_export_device(pdev, domain, bus, slot, func);
  17.335 +		if (err)
  17.336 +			goto out;
  17.337 +	}
  17.338 +
  17.339 +	err = pciback_publish_pci_roots(pdev, pciback_publish_pci_root);
  17.340 +	if (err) {
  17.341 +		xenbus_dev_fatal(pdev->xdev, err,
  17.342 +				 "Error while publish PCI root buses "
  17.343 +				 "for frontend");
  17.344 +		goto out;
  17.345 +	}
  17.346 +
  17.347 +	err = xenbus_switch_state(pdev->xdev, XBT_NULL, XenbusStateInitialised);
  17.348 +	if (err)
  17.349 +		xenbus_dev_fatal(pdev->xdev, err,
  17.350 +				 "Error switching to initialised state!");
  17.351 +
  17.352 +      out:
  17.353 +	spin_unlock(&pdev->dev_lock);
  17.354 +
  17.355 +	if (!err)
  17.356 +		/* see if pcifront is already configured (if not, we'll wait) */
  17.357 +		pciback_attach(pdev);
  17.358 +
  17.359 +	return err;
  17.360 +}
  17.361 +
  17.362 +static void pciback_be_watch(struct xenbus_watch *watch,
  17.363 +			     const char **vec, unsigned int len)
  17.364 +{
  17.365 +	struct pciback_device *pdev =
  17.366 +	    container_of(watch, struct pciback_device, be_watch);
  17.367 +
  17.368 +	switch (xenbus_read_driver_state(pdev->xdev->nodename)) {
  17.369 +	case XenbusStateInitWait:
  17.370 +		pciback_setup_backend(pdev);
  17.371 +		break;
  17.372 +
  17.373 +	default:
  17.374 +		break;
  17.375 +	}
  17.376 +}
  17.377 +
  17.378 +static int pciback_xenbus_probe(struct xenbus_device *dev,
  17.379 +				const struct xenbus_device_id *id)
  17.380 +{
  17.381 +	int err = 0;
  17.382 +	struct pciback_device *pdev = alloc_pdev(dev);
  17.383 +
  17.384 +	if (pdev == NULL) {
  17.385 +		err = -ENOMEM;
  17.386 +		xenbus_dev_fatal(dev, err,
  17.387 +				 "Error allocating pciback_device struct");
  17.388 +		goto out;
  17.389 +	}
  17.390 +
  17.391 +	/* wait for xend to configure us */
  17.392 +	err = xenbus_switch_state(dev, XBT_NULL, XenbusStateInitWait);
  17.393 +	if (err)
  17.394 +		goto out;
  17.395 +
  17.396 +	/* watch the backend node for backend configuration information */
  17.397 +	err = xenbus_watch_path(dev, dev->nodename, &pdev->be_watch,
  17.398 +				pciback_be_watch);
  17.399 +	if (err)
  17.400 +		goto out;
  17.401 +	pdev->be_watching = 1;
  17.402 +
  17.403 +	/* We need to force a call to our callback here in case
  17.404 +	 * xend already configured us!
  17.405 +	 */
  17.406 +	pciback_be_watch(&pdev->be_watch, NULL, 0);
  17.407 +
  17.408 +      out:
  17.409 +	return err;
  17.410 +}
  17.411 +
  17.412 +static int pciback_xenbus_remove(struct xenbus_device *dev)
  17.413 +{
  17.414 +	struct pciback_device *pdev = dev->data;
  17.415 +
  17.416 +	if (pdev != NULL)
  17.417 +		free_pdev(pdev);
  17.418 +
  17.419 +	return 0;
  17.420 +}
  17.421 +
  17.422 +static struct xenbus_device_id xenpci_ids[] = {
  17.423 +	{"pci"},
  17.424 +	{{0}},
  17.425 +};
  17.426 +
  17.427 +static struct xenbus_driver xenbus_pciback_driver = {
  17.428 +	.name 			= "pciback",
  17.429 +	.owner 			= THIS_MODULE,
  17.430 +	.ids 			= xenpci_ids,
  17.431 +	.probe 			= pciback_xenbus_probe,
  17.432 +	.remove 		= pciback_xenbus_remove,
  17.433 +	.otherend_changed 	= pciback_frontend_changed,
  17.434 +};
  17.435 +
  17.436 +static __init int pciback_xenbus_register(void)
  17.437 +{
  17.438 +	return xenbus_register_backend(&xenbus_pciback_driver);
  17.439 +}
  17.440 +
  17.441 +/* Must only initialize our xenbus driver after the pcistub driver */
  17.442 +device_initcall(pciback_xenbus_register);
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pcifront/Makefile	Thu Feb 16 23:44:41 2006 +0100
    18.3 @@ -0,0 +1,7 @@
    18.4 +obj-y += pcifront.o
    18.5 +
    18.6 +pcifront-y := pci_op.o xenbus.o pci.o
    18.7 +
    18.8 +ifeq ($(CONFIG_XEN_PCIDEV_FE_DEBUG),y)
    18.9 +EXTRA_CFLAGS += -DDEBUG
   18.10 +endif
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pcifront/pci.c	Thu Feb 16 23:44:41 2006 +0100
    19.3 @@ -0,0 +1,44 @@
    19.4 +/*
    19.5 + * PCI Frontend Operations - ensure only one PCI frontend runs at a time
    19.6 + *
    19.7 + *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
    19.8 + */
    19.9 +#include <linux/module.h>
   19.10 +#include <linux/init.h>
   19.11 +#include <linux/pci.h>
   19.12 +#include <linux/spinlock.h>
   19.13 +#include "pcifront.h"
   19.14 +
   19.15 +DEFINE_SPINLOCK(pcifront_dev_lock);
   19.16 +static struct pcifront_device *pcifront_dev = NULL;
   19.17 +
   19.18 +int pcifront_connect(struct pcifront_device *pdev)
   19.19 +{
   19.20 +	int err = 0;
   19.21 +
   19.22 +	spin_lock(&pcifront_dev_lock);
   19.23 +
   19.24 +	if (!pcifront_dev)
   19.25 +		dev_info(&pdev->xdev->dev, "Installing PCI frontend\n");
   19.26 +	else {
   19.27 +		dev_err(&pdev->xdev->dev, "PCI frontend already installed!\n");
   19.28 +		err = -EEXIST;
   19.29 +	}
   19.30 +
   19.31 +	spin_unlock(&pcifront_dev_lock);
   19.32 +
   19.33 +	return err;
   19.34 +}
   19.35 +
   19.36 +void pcifront_disconnect(struct pcifront_device *pdev)
   19.37 +{
   19.38 +	spin_lock(&pcifront_dev_lock);
   19.39 +
   19.40 +	if (pdev == pcifront_dev) {
   19.41 +		dev_info(&pdev->xdev->dev,
   19.42 +			 "Disconnecting PCI Frontend Buses\n");
   19.43 +		pcifront_dev = NULL;
   19.44 +	}
   19.45 +
   19.46 +	spin_unlock(&pcifront_dev_lock);
   19.47 +}
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c	Thu Feb 16 23:44:41 2006 +0100
    20.3 @@ -0,0 +1,245 @@
    20.4 +/*
    20.5 + * PCI Frontend Operations - Communicates with frontend
    20.6 + *
    20.7 + *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
    20.8 + */
    20.9 +#include <linux/module.h>
   20.10 +#include <linux/version.h>
   20.11 +#include <linux/init.h>
   20.12 +#include <linux/pci.h>
   20.13 +#include <linux/spinlock.h>
   20.14 +#include <xen/evtchn.h>
   20.15 +#include "pcifront.h"
   20.16 +
   20.17 +static int verbose_request = 0;
   20.18 +module_param(verbose_request, int, 0644);
   20.19 +
   20.20 +static int errno_to_pcibios_err(int errno)
   20.21 +{
   20.22 +	switch (errno) {
   20.23 +	case XEN_PCI_ERR_success:
   20.24 +		return PCIBIOS_SUCCESSFUL;
   20.25 +
   20.26 +	case XEN_PCI_ERR_dev_not_found:
   20.27 +		return PCIBIOS_DEVICE_NOT_FOUND;
   20.28 +
   20.29 +	case XEN_PCI_ERR_invalid_offset:
   20.30 +	case XEN_PCI_ERR_op_failed:
   20.31 +		return PCIBIOS_BAD_REGISTER_NUMBER;
   20.32 +
   20.33 +	case XEN_PCI_ERR_not_implemented:
   20.34 +		return PCIBIOS_FUNC_NOT_SUPPORTED;
   20.35 +
   20.36 +	case XEN_PCI_ERR_access_denied:
   20.37 +		return PCIBIOS_SET_FAILED;
   20.38 +	}
   20.39 +	return errno;
   20.40 +}
   20.41 +
   20.42 +static int do_pci_op(struct pcifront_device *pdev, struct xen_pci_op *op)
   20.43 +{
   20.44 +	int err = 0;
   20.45 +	struct xen_pci_op *active_op = &pdev->sh_info->op;
   20.46 +	unsigned long irq_flags;
   20.47 +
   20.48 +	unsigned int volatile ttl = (1U << 29);
   20.49 +
   20.50 +	spin_lock_irqsave(&pdev->sh_info_lock, irq_flags);
   20.51 +
   20.52 +	memcpy(active_op, op, sizeof(struct xen_pci_op));
   20.53 +
   20.54 +	/* Go */
   20.55 +	wmb();
   20.56 +	set_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags);
   20.57 +	notify_remote_via_evtchn(pdev->evtchn);
   20.58 +
   20.59 +	/* IRQs are disabled for the pci config. space reads/writes,
   20.60 +	 * which means no event channel to notify us that the backend
   20.61 +	 * is done so spin while waiting for the answer */
   20.62 +	while (test_bit
   20.63 +	       (_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags)) {
   20.64 +		if (!ttl) {
   20.65 +			dev_err(&pdev->xdev->dev,
   20.66 +				"pciback not responding!!!\n");
   20.67 +			clear_bit(_XEN_PCIF_active,
   20.68 +				  (unsigned long *)&pdev->sh_info->flags);
   20.69 +			err = XEN_PCI_ERR_dev_not_found;
   20.70 +			goto out;
   20.71 +		}
   20.72 +		ttl--;
   20.73 +	}
   20.74 +
   20.75 +	memcpy(op, active_op, sizeof(struct xen_pci_op));
   20.76 +
   20.77 +	err = op->err;
   20.78 +      out:
   20.79 +	spin_unlock_irqrestore(&pdev->sh_info_lock, irq_flags);
   20.80 +	return err;
   20.81 +}
   20.82 +
   20.83 +/* Access to this function is spinlocked in drivers/pci/access.c */
   20.84 +static int pcifront_bus_read(struct pci_bus *bus, unsigned int devfn,
   20.85 +			     int where, int size, u32 * val)
   20.86 +{
   20.87 +	int err = 0;
   20.88 +	struct xen_pci_op op = {
   20.89 +		.cmd    = XEN_PCI_OP_conf_read,
   20.90 +		.domain = pci_domain_nr(bus),
   20.91 +		.bus    = bus->number,
   20.92 +		.devfn  = devfn,
   20.93 +		.offset = where,
   20.94 +		.size   = size,
   20.95 +	};
   20.96 +	struct pcifront_sd *sd = bus->sysdata;
   20.97 +	struct pcifront_device *pdev = sd->pdev;
   20.98 +
   20.99 +	if (verbose_request)
  20.100 +		dev_info(&pdev->xdev->dev,
  20.101 +			 "read dev=%04x:%02x:%02x.%01x - offset %x size %d\n",
  20.102 +			 pci_domain_nr(bus), bus->number, PCI_SLOT(devfn),
  20.103 +			 PCI_FUNC(devfn), where, size);
  20.104 +
  20.105 +	err = do_pci_op(pdev, &op);
  20.106 +
  20.107 +	if (likely(!err)) {
  20.108 +		if (verbose_request)
  20.109 +			dev_info(&pdev->xdev->dev, "read got back value %x\n",
  20.110 +				 op.value);
  20.111 +
  20.112 +		*val = op.value;
  20.113 +	} else if (err == -ENODEV) {
  20.114 +		/* No device here, pretend that it just returned 0 */
  20.115 +		err = 0;
  20.116 +		*val = 0;
  20.117 +	}
  20.118 +
  20.119 +	return errno_to_pcibios_err(err);
  20.120 +}
  20.121 +
  20.122 +/* Access to this function is spinlocked in drivers/pci/access.c */
  20.123 +static int pcifront_bus_write(struct pci_bus *bus, unsigned int devfn,
  20.124 +			      int where, int size, u32 val)
  20.125 +{
  20.126 +	struct xen_pci_op op = {
  20.127 +		.cmd    = XEN_PCI_OP_conf_write,
  20.128 +		.domain = pci_domain_nr(bus),
  20.129 +		.bus    = bus->number,
  20.130 +		.devfn  = devfn,
  20.131 +		.offset = where,
  20.132 +		.size   = size,
  20.133 +		.value  = val,
  20.134 +	};
  20.135 +	struct pcifront_sd *sd = bus->sysdata;
  20.136 +	struct pcifront_device *pdev = sd->pdev;
  20.137 +
  20.138 +	if (verbose_request)
  20.139 +		dev_info(&pdev->xdev->dev,
  20.140 +			 "write dev=%04x:%02x:%02x.%01x - "
  20.141 +			 "offset %x size %d val %x\n",
  20.142 +			 pci_domain_nr(bus), bus->number,
  20.143 +			 PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, val);
  20.144 +
  20.145 +	return errno_to_pcibios_err(do_pci_op(pdev, &op));
  20.146 +}
  20.147 +
  20.148 +struct pci_ops pcifront_bus_ops = {
  20.149 +	.read = pcifront_bus_read,
  20.150 +	.write = pcifront_bus_write,
  20.151 +};
  20.152 +
  20.153 +/* Claim resources for the PCI frontend as-is, backend won't allow changes */
  20.154 +static void pcifront_claim_resource(struct pci_dev *dev, void *data)
  20.155 +{
  20.156 +	struct pcifront_device *pdev = data;
  20.157 +	int i;
  20.158 +	struct resource *r;
  20.159 +
  20.160 +	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
  20.161 +		r = &dev->resource[i];
  20.162 +
  20.163 +		if (!r->parent && r->start && r->flags) {
  20.164 +			dev_dbg(&pdev->xdev->dev, "claiming resource %s/%d\n",
  20.165 +					pci_name(dev), i);
  20.166 +			pci_claim_resource(dev, i);
  20.167 +		}
  20.168 +	}
  20.169 +}
  20.170 +
  20.171 +int pcifront_scan_root(struct pcifront_device *pdev,
  20.172 +		       unsigned int domain, unsigned int bus)
  20.173 +{
  20.174 +	struct pci_bus *b;
  20.175 +	struct pcifront_sd *sd = NULL;
  20.176 +	struct pci_bus_entry *bus_entry = NULL;
  20.177 +	int err = 0;
  20.178 +
  20.179 +#ifndef CONFIG_PCI_DOMAINS
  20.180 +	if (domain != 0) {
  20.181 +		dev_err(&pdev->xdev->dev,
  20.182 +			"PCI Root in non-zero PCI Domain! domain=%d\n", domain);
  20.183 +		dev_err(&pdev->xdev->dev,
  20.184 +			"Please compile with CONFIG_PCI_DOMAINS\n");
  20.185 +		err = -EINVAL;
  20.186 +		goto err_out;
  20.187 +	}
  20.188 +#endif
  20.189 +
  20.190 +	dev_info(&pdev->xdev->dev, "Creating PCI Frontend Bus %04x:%02x\n",
  20.191 +		 domain, bus);
  20.192 +
  20.193 +	bus_entry = kmalloc(sizeof(*bus_entry), GFP_KERNEL);
  20.194 +	sd = kmalloc(sizeof(*sd), GFP_KERNEL);
  20.195 +	if (!bus_entry || !sd) {
  20.196 +		err = -ENOMEM;
  20.197 +		goto err_out;
  20.198 +	}
  20.199 +	sd->domain = domain;
  20.200 +	sd->pdev = pdev;
  20.201 +
  20.202 +	b = pci_scan_bus_parented(&pdev->xdev->dev, bus, &pcifront_bus_ops, sd);
  20.203 +	if (!b) {
  20.204 +		dev_err(&pdev->xdev->dev, "Error creating PCI Frontend Bus!\n");
  20.205 +		err = -ENOMEM;
  20.206 +		goto err_out;
  20.207 +	}
  20.208 +	bus_entry->bus = b;
  20.209 +
  20.210 +	list_add(&bus_entry->list, &pdev->root_buses);
  20.211 +
  20.212 +	/* Claim resources before going "live" with our devices */
  20.213 +	pci_walk_bus(b, pcifront_claim_resource, pdev);
  20.214 +
  20.215 +	pci_bus_add_devices(b);
  20.216 +
  20.217 +	return 0;
  20.218 +
  20.219 +      err_out:
  20.220 +	kfree(bus_entry);
  20.221 +	kfree(sd);
  20.222 +
  20.223 +	return err;
  20.224 +}
  20.225 +
  20.226 +void pcifront_free_roots(struct pcifront_device *pdev)
  20.227 +{
  20.228 +	struct pci_bus_entry *bus_entry, *t;
  20.229 +
  20.230 +	list_for_each_entry_safe(bus_entry, t, &pdev->root_buses, list) {
  20.231 +		/* TODO: Removing a PCI Bus is untested (as it normally
  20.232 +		 * just goes away on domain shutdown)
  20.233 +		 */
  20.234 +		list_del(&bus_entry->list);
  20.235 +
  20.236 +		spin_lock(&pci_bus_lock);
  20.237 +		list_del(&bus_entry->bus->node);
  20.238 +		spin_unlock(&pci_bus_lock);
  20.239 +
  20.240 +		kfree(bus_entry->bus->sysdata);
  20.241 +
  20.242 +		device_unregister(bus_entry->bus->bridge);
  20.243 +
  20.244 +		/* Do we need to free() the bus itself? */
  20.245 +
  20.246 +		kfree(bus_entry);
  20.247 +	}
  20.248 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pcifront/pcifront.h	Thu Feb 16 23:44:41 2006 +0100
    21.3 @@ -0,0 +1,40 @@
    21.4 +/*
    21.5 + * PCI Frontend - Common data structures & function declarations
    21.6 + *
    21.7 + *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
    21.8 + */
    21.9 +#ifndef __XEN_PCIFRONT_H__
   21.10 +#define __XEN_PCIFRONT_H__
   21.11 +
   21.12 +#include <linux/spinlock.h>
   21.13 +#include <linux/pci.h>
   21.14 +#include <xen/xenbus.h>
   21.15 +#include <xen/interface/io/pciif.h>
   21.16 +#include <xen/pcifront.h>
   21.17 +
   21.18 +struct pci_bus_entry {
   21.19 +	struct list_head list;
   21.20 +	struct pci_bus *bus;
   21.21 +};
   21.22 +
   21.23 +struct pcifront_device {
   21.24 +	struct xenbus_device *xdev;
   21.25 +	struct list_head root_buses;
   21.26 +	spinlock_t dev_lock;
   21.27 +
   21.28 +	int evtchn;
   21.29 +	int gnt_ref;
   21.30 +
   21.31 +	/* Lock this when doing any operations in sh_info */
   21.32 +	spinlock_t sh_info_lock;
   21.33 +	struct xen_pci_sharedinfo *sh_info;
   21.34 +};
   21.35 +
   21.36 +int pcifront_connect(struct pcifront_device *pdev);
   21.37 +void pcifront_disconnect(struct pcifront_device *pdev);
   21.38 +
   21.39 +int pcifront_scan_root(struct pcifront_device *pdev,
   21.40 +		       unsigned int domain, unsigned int bus);
   21.41 +void pcifront_free_roots(struct pcifront_device *pdev);
   21.42 +
   21.43 +#endif	/* __XEN_PCIFRONT_H__ */
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c	Thu Feb 16 23:44:41 2006 +0100
    22.3 @@ -0,0 +1,295 @@
    22.4 +/*
    22.5 + * PCI Frontend Xenbus Setup - handles setup with backend (imports page/evtchn)
    22.6 + *
    22.7 + *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
    22.8 + */
    22.9 +#include <linux/module.h>
   22.10 +#include <linux/init.h>
   22.11 +#include <linux/mm.h>
   22.12 +#include <xen/xenbus.h>
   22.13 +#include "pcifront.h"
   22.14 +
   22.15 +#define INVALID_GRANT_REF (0)
   22.16 +#define INVALID_EVTCHN    (-1)
   22.17 +
   22.18 +static struct pcifront_device *alloc_pdev(struct xenbus_device *xdev)
   22.19 +{
   22.20 +	struct pcifront_device *pdev;
   22.21 +
   22.22 +	pdev = kmalloc(sizeof(struct pcifront_device), GFP_KERNEL);
   22.23 +	if (pdev == NULL)
   22.24 +		goto out;
   22.25 +
   22.26 +	pdev->sh_info =
   22.27 +	    (struct xen_pci_sharedinfo *)__get_free_page(GFP_KERNEL);
   22.28 +	if (pdev->sh_info == NULL) {
   22.29 +		kfree(pdev);
   22.30 +		pdev = NULL;
   22.31 +		goto out;
   22.32 +	}
   22.33 +	pdev->sh_info->flags = 0;
   22.34 +
   22.35 +	xdev->data = pdev;
   22.36 +	pdev->xdev = xdev;
   22.37 +
   22.38 +	INIT_LIST_HEAD(&pdev->root_buses);
   22.39 +
   22.40 +	spin_lock_init(&pdev->dev_lock);
   22.41 +	spin_lock_init(&pdev->sh_info_lock);
   22.42 +
   22.43 +	pdev->evtchn = INVALID_EVTCHN;
   22.44 +	pdev->gnt_ref = INVALID_GRANT_REF;
   22.45 +
   22.46 +	dev_dbg(&xdev->dev, "Allocated pdev @ 0x%p pdev->sh_info @ 0x%p\n",
   22.47 +		pdev, pdev->sh_info);
   22.48 +      out:
   22.49 +	return pdev;
   22.50 +}
   22.51 +
   22.52 +static void free_pdev(struct pcifront_device *pdev)
   22.53 +{
   22.54 +	dev_dbg(&pdev->xdev->dev, "freeing pdev @ 0x%p\n", pdev);
   22.55 +
   22.56 +	if (pdev->evtchn != INVALID_EVTCHN)
   22.57 +		xenbus_free_evtchn(pdev->xdev, pdev->evtchn);
   22.58 +
   22.59 +	if (pdev->gnt_ref != INVALID_GRANT_REF)
   22.60 +		gnttab_end_foreign_access(pdev->gnt_ref, 0,
   22.61 +					  (unsigned long)pdev->sh_info);
   22.62 +
   22.63 +	pdev->xdev->data = NULL;
   22.64 +
   22.65 +	kfree(pdev);
   22.66 +}
   22.67 +
   22.68 +static int pcifront_publish_info(struct pcifront_device *pdev)
   22.69 +{
   22.70 +	int err = 0;
   22.71 +	xenbus_transaction_t trans;
   22.72 +
   22.73 +	err = xenbus_grant_ring(pdev->xdev, virt_to_mfn(pdev->sh_info));
   22.74 +	if (err < 0)
   22.75 +		goto out;
   22.76 +
   22.77 +	pdev->gnt_ref = err;
   22.78 +
   22.79 +	err = xenbus_alloc_evtchn(pdev->xdev, &pdev->evtchn);
   22.80 +	if (err)
   22.81 +		goto out;
   22.82 +
   22.83 +      do_publish:
   22.84 +	err = xenbus_transaction_start(&trans);
   22.85 +	if (err) {
   22.86 +		xenbus_dev_fatal(pdev->xdev, err,
   22.87 +				 "Error writing configuration for backend "
   22.88 +				 "(start transaction)");
   22.89 +		goto out;
   22.90 +	}
   22.91 +
   22.92 +	err = xenbus_printf(trans, pdev->xdev->nodename,
   22.93 +			    "pci-op-ref", "%u", pdev->gnt_ref);
   22.94 +	if (!err)
   22.95 +		err = xenbus_printf(trans, pdev->xdev->nodename,
   22.96 +				    "event-channel", "%u", pdev->evtchn);
   22.97 +	if (!err)
   22.98 +		err = xenbus_printf(trans, pdev->xdev->nodename,
   22.99 +				    "magic", XEN_PCI_MAGIC);
  22.100 +	if (!err)
  22.101 +		err =
  22.102 +		    xenbus_switch_state(pdev->xdev, trans,
  22.103 +					XenbusStateInitialised);
  22.104 +
  22.105 +	if (err) {
  22.106 +		xenbus_transaction_end(trans, 1);
  22.107 +		xenbus_dev_fatal(pdev->xdev, err,
  22.108 +				 "Error writing configuration for backend");
  22.109 +		goto out;
  22.110 +	} else {
  22.111 +		err = xenbus_transaction_end(trans, 0);
  22.112 +		if (err == -EAGAIN)
  22.113 +			goto do_publish;
  22.114 +		else if (err) {
  22.115 +			xenbus_dev_fatal(pdev->xdev, err,
  22.116 +					 "Error completing transaction "
  22.117 +					 "for backend");
  22.118 +			goto out;
  22.119 +		}
  22.120 +	}
  22.121 +
  22.122 +	dev_dbg(&pdev->xdev->dev, "publishing successful!\n");
  22.123 +
  22.124 +      out:
  22.125 +	return err;
  22.126 +}
  22.127 +
  22.128 +static int pcifront_try_connect(struct pcifront_device *pdev)
  22.129 +{
  22.130 +	int err = -EFAULT;
  22.131 +	int i, num_roots, len;
  22.132 +	char str[64];
  22.133 +	unsigned int domain, bus;
  22.134 +
  22.135 +	spin_lock(&pdev->dev_lock);
  22.136 +
  22.137 +	/* Only connect once */
  22.138 +	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
  22.139 +	    XenbusStateInitialised)
  22.140 +		goto out;
  22.141 +
  22.142 +	err = pcifront_connect(pdev);
  22.143 +	if (err) {
  22.144 +		xenbus_dev_fatal(pdev->xdev, err,
  22.145 +				 "Error connecting PCI Frontend");
  22.146 +		goto out;
  22.147 +	}
  22.148 +
  22.149 +	err = xenbus_scanf(XBT_NULL, pdev->xdev->otherend,
  22.150 +			   "root_num", "%d", &num_roots);
  22.151 +	if (err == -ENOENT) {
  22.152 +		xenbus_dev_error(pdev->xdev, err,
  22.153 +				 "No PCI Roots found, trying 0000:00");
  22.154 +		err = pcifront_scan_root(pdev, 0, 0);
  22.155 +		num_roots = 0;
  22.156 +	} else if (err != 1) {
  22.157 +		if (err == 0)
  22.158 +			err = -EINVAL;
  22.159 +		xenbus_dev_fatal(pdev->xdev, err,
  22.160 +				 "Error reading number of PCI roots");
  22.161 +		goto out;
  22.162 +	}
  22.163 +
  22.164 +	for (i = 0; i < num_roots; i++) {
  22.165 +		len = snprintf(str, sizeof(str), "root-%d", i);
  22.166 +		if (unlikely(len >= (sizeof(str) - 1))) {
  22.167 +			err = -ENOMEM;
  22.168 +			goto out;
  22.169 +		}
  22.170 +
  22.171 +		err = xenbus_scanf(XBT_NULL, pdev->xdev->otherend, str,
  22.172 +				   "%x:%x", &domain, &bus);
  22.173 +		if (err != 2) {
  22.174 +			if (err >= 0)
  22.175 +				err = -EINVAL;
  22.176 +			xenbus_dev_fatal(pdev->xdev, err,
  22.177 +					 "Error reading PCI root %d", i);
  22.178 +			goto out;
  22.179 +		}
  22.180 +
  22.181 +		err = pcifront_scan_root(pdev, domain, bus);
  22.182 +		if (err) {
  22.183 +			xenbus_dev_fatal(pdev->xdev, err,
  22.184 +					 "Error scanning PCI root %04x:%02x",
  22.185 +					 domain, bus);
  22.186 +			goto out;
  22.187 +		}
  22.188 +	}
  22.189 +
  22.190 +	err = xenbus_switch_state(pdev->xdev, XBT_NULL, XenbusStateConnected);
  22.191 +	if (err)
  22.192 +		goto out;
  22.193 +
  22.194 +      out:
  22.195 +	spin_unlock(&pdev->dev_lock);
  22.196 +	return err;
  22.197 +}
  22.198 +
  22.199 +static int pcifront_try_disconnect(struct pcifront_device *pdev)
  22.200 +{
  22.201 +	int err = 0;
  22.202 +	XenbusState prev_state;
  22.203 +
  22.204 +	spin_lock(&pdev->dev_lock);
  22.205 +
  22.206 +	prev_state = xenbus_read_driver_state(pdev->xdev->nodename);
  22.207 +
  22.208 +	if (prev_state < XenbusStateClosing)
  22.209 +		err = xenbus_switch_state(pdev->xdev, XBT_NULL,
  22.210 +					XenbusStateClosing);
  22.211 +
  22.212 +	if (!err && prev_state == XenbusStateConnected)
  22.213 +		pcifront_disconnect(pdev);
  22.214 +
  22.215 +	spin_unlock(&pdev->dev_lock);
  22.216 +
  22.217 +	return err;
  22.218 +}
  22.219 +
  22.220 +static void pcifront_backend_changed(struct xenbus_device *xdev,
  22.221 +				     XenbusState be_state)
  22.222 +{
  22.223 +	struct pcifront_device *pdev = xdev->data;
  22.224 +
  22.225 +	switch (be_state) {
  22.226 +	case XenbusStateClosing:
  22.227 +		dev_warn(&xdev->dev, "backend going away!\n");
  22.228 +		pcifront_try_disconnect(pdev);
  22.229 +		break;
  22.230 +
  22.231 +	case XenbusStateClosed:
  22.232 +		dev_warn(&xdev->dev, "backend went away!\n");
  22.233 +		pcifront_try_disconnect(pdev);
  22.234 +
  22.235 +		device_unregister(&pdev->xdev->dev);
  22.236 +		break;
  22.237 +
  22.238 +	case XenbusStateConnected:
  22.239 +		pcifront_try_connect(pdev);
  22.240 +		break;
  22.241 +
  22.242 +	default:
  22.243 +		break;
  22.244 +	}
  22.245 +}
  22.246 +
  22.247 +static int pcifront_xenbus_probe(struct xenbus_device *xdev,
  22.248 +				 const struct xenbus_device_id *id)
  22.249 +{
  22.250 +	int err = 0;
  22.251 +	struct pcifront_device *pdev = alloc_pdev(xdev);
  22.252 +
  22.253 +	if (pdev == NULL) {
  22.254 +		err = -ENOMEM;
  22.255 +		xenbus_dev_fatal(xdev, err,
  22.256 +				 "Error allocating pcifront_device struct");
  22.257 +		goto out;
  22.258 +	}
  22.259 +
  22.260 +	err = pcifront_publish_info(pdev);
  22.261 +
  22.262 +      out:
  22.263 +	return err;
  22.264 +}
  22.265 +
  22.266 +static int pcifront_xenbus_remove(struct xenbus_device *xdev)
  22.267 +{
  22.268 +	if (xdev->data)
  22.269 +		free_pdev(xdev->data);
  22.270 +
  22.271 +	return 0;
  22.272 +}
  22.273 +
  22.274 +static struct xenbus_device_id xenpci_ids[] = {
  22.275 +	{"pci"},
  22.276 +	{{0}},
  22.277 +};
  22.278 +
  22.279 +static struct xenbus_driver xenbus_pcifront_driver = {
  22.280 +	.name 			= "pcifront",
  22.281 +	.owner 			= THIS_MODULE,
  22.282 +	.ids 			= xenpci_ids,
  22.283 +	.probe 			= pcifront_xenbus_probe,
  22.284 +	.remove 		= pcifront_xenbus_remove,
  22.285 +	.otherend_changed 	= pcifront_backend_changed,
  22.286 +};
  22.287 +
  22.288 +static int __init pcifront_init(void)
  22.289 +{
  22.290 +	int err = 0;
  22.291 +
  22.292 +	err = xenbus_register_frontend(&xenbus_pcifront_driver);
  22.293 +
  22.294 +	return err;
  22.295 +}
  22.296 +
  22.297 +/* Initialize after the Xen PCI Frontend Stub is initialized */
  22.298 +subsys_initcall(pcifront_init);
    23.1 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pci.h	Thu Feb 16 23:37:40 2006 +0100
    23.2 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pci.h	Thu Feb 16 23:44:41 2006 +0100
    23.3 @@ -134,6 +134,10 @@ static inline void pci_dma_burst_advice(
    23.4  
    23.5  #endif /* __KERNEL__ */
    23.6  
    23.7 +#ifdef CONFIG_XEN_PCIDEV_FRONTEND
    23.8 +#include <xen/pcifront.h>
    23.9 +#endif /* CONFIG_XEN_PCIDEV_FRONTEND */
   23.10 +
   23.11  /* implement the pci_ DMA API in terms of the generic device dma_ one */
   23.12  #include <asm-generic/pci-dma-compat.h>
   23.13  
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/linux-2.6-xen-sparse/include/xen/pcifront.h	Thu Feb 16 23:44:41 2006 +0100
    24.3 @@ -0,0 +1,39 @@
    24.4 +/*
    24.5 + * PCI Frontend - arch-dependendent declarations
    24.6 + *
    24.7 + *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
    24.8 + */
    24.9 +#ifndef __XEN_ASM_PCIFRONT_H__
   24.10 +#define __XEN_ASM_PCIFRONT_H__
   24.11 +
   24.12 +#include <linux/config.h>
   24.13 +#include <linux/spinlock.h>
   24.14 +
   24.15 +#ifdef __KERNEL__
   24.16 +
   24.17 +struct pcifront_device;
   24.18 +
   24.19 +struct pcifront_sd {
   24.20 +	int domain;
   24.21 +	struct pcifront_device *pdev;
   24.22 +};
   24.23 +
   24.24 +struct pci_bus;
   24.25 +
   24.26 +#ifdef CONFIG_PCI_DOMAINS
   24.27 +static inline int pci_domain_nr(struct pci_bus *bus)
   24.28 +{
   24.29 +	struct pcifront_sd *sd = bus->sysdata;
   24.30 +	return sd->domain;
   24.31 +}
   24.32 +static inline int pci_proc_domain(struct pci_bus *bus)
   24.33 +{
   24.34 +	return pci_domain_nr(bus);
   24.35 +}
   24.36 +#endif /* CONFIG_PCI_DOMAINS */
   24.37 +
   24.38 +extern spinlock_t pci_bus_lock;
   24.39 +
   24.40 +#endif /* __KERNEL__ */
   24.41 +
   24.42 +#endif /* __XEN_ASM_PCIFRONT_H__ */
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/xen/include/public/io/pciif.h	Thu Feb 16 23:44:41 2006 +0100
    25.3 @@ -0,0 +1,55 @@
    25.4 +/*
    25.5 + * PCI Backend/Frontend Common Data Structures & Macros
    25.6 + *
    25.7 + *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
    25.8 + */
    25.9 +#ifndef __XEN_PCI_COMMON_H__
   25.10 +#define __XEN_PCI_COMMON_H__
   25.11 +
   25.12 +/* Be sure to bump this number if you change this file */
   25.13 +#define XEN_PCI_MAGIC		"7"
   25.14 +
   25.15 +/* xen_pci_sharedinfo flags */
   25.16 +#define _XEN_PCIF_active     (0)
   25.17 +#define XEN_PCIF_active      (1<<_XEN_PCI_active)
   25.18 +
   25.19 +/* xen_pci_op commands */
   25.20 +#define XEN_PCI_OP_conf_read    (0)
   25.21 +#define XEN_PCI_OP_conf_write   (1)
   25.22 +
   25.23 +/* xen_pci_op error numbers */
   25.24 +#define XEN_PCI_ERR_success          (0)
   25.25 +#define XEN_PCI_ERR_dev_not_found   (-1)
   25.26 +#define XEN_PCI_ERR_invalid_offset  (-2)
   25.27 +#define XEN_PCI_ERR_access_denied   (-3)
   25.28 +#define XEN_PCI_ERR_not_implemented (-4)
   25.29 +/* XEN_PCI_ERR_op_failed - backend failed to complete the operation */
   25.30 +#define XEN_PCI_ERR_op_failed       (-5)
   25.31 +
   25.32 +struct xen_pci_op {
   25.33 +	/* IN: what action to perform: XEN_PCI_OP_* */
   25.34 +	uint32_t cmd;
   25.35 +
   25.36 +	/* OUT: will contain an error number (if any) from errno.h */
   25.37 +	int32_t err;
   25.38 +
   25.39 +	/* IN: which device to touch */
   25.40 +	uint32_t domain; /* PCI Domain/Segment */
   25.41 +	uint32_t bus;
   25.42 +	uint32_t devfn;
   25.43 +
   25.44 +	/* IN: which configuration registers to touch */
   25.45 +	int32_t offset;
   25.46 +	int32_t size;
   25.47 +
   25.48 +	/* IN/OUT: Contains the result after a READ or the value to WRITE */
   25.49 +	uint32_t value;
   25.50 +};
   25.51 +
   25.52 +struct xen_pci_sharedinfo {
   25.53 +	/* flags - XEN_PCIF_* */
   25.54 +	uint32_t flags;
   25.55 +	struct xen_pci_op op;
   25.56 +};
   25.57 +
   25.58 +#endif /* __XEN_PCI_COMMON_H__ */