# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1220524097 -3600
# Node ID a5bf2535e7bb15ccfbe8110d6e4505a5e32a5200
# Parent 294fc8fc4ba05c1fe91754dfe3b770834c56231b
ioemu: support PCI Express Capability Structure version 1.
Signed-off-by: Yuji Shimada <shimada-yxb@xxxxxxxxxxxxxxx>
---
tools/ioemu/hw/pass-through.c | 146 ++++++++++++++++++++++++++++++++++++++++--
tools/ioemu/hw/pass-through.h | 15 ++++
2 files changed, 156 insertions(+), 5 deletions(-)
diff -r 294fc8fc4ba0 -r a5bf2535e7bb tools/ioemu/hw/pass-through.c
--- a/tools/ioemu/hw/pass-through.c Thu Sep 04 11:26:25 2008 +0100
+++ b/tools/ioemu/hw/pass-through.c Thu Sep 04 11:28:17 2008 +0100
@@ -57,6 +57,10 @@ static uint32_t pt_irqpin_reg_init(struc
struct pt_reg_info_tbl *reg, uint32_t real_offset);
static uint32_t pt_bar_reg_init(struct pt_dev *ptdev,
struct pt_reg_info_tbl *reg, uint32_t real_offset);
+static uint32_t pt_linkctrl_reg_init(struct pt_dev *ptdev,
+ struct pt_reg_info_tbl *reg, uint32_t real_offset);
+static uint32_t pt_devctrl2_reg_init(struct pt_dev *ptdev,
+ struct pt_reg_info_tbl *reg, uint32_t real_offset);
static uint32_t pt_linkctrl2_reg_init(struct pt_dev *ptdev,
struct pt_reg_info_tbl *reg, uint32_t real_offset);
static uint32_t pt_msgctrl_reg_init(struct pt_dev *ptdev,
@@ -76,6 +80,8 @@ static uint8_t pt_msix_size_init(struct
static uint8_t pt_msix_size_init(struct pt_dev *ptdev,
struct pt_reg_grp_info_tbl *grp_reg, uint32_t base_offset);
static uint8_t pt_vendor_size_init(struct pt_dev *ptdev,
+ struct pt_reg_grp_info_tbl *grp_reg, uint32_t base_offset);
+static uint8_t pt_pcie_size_init(struct pt_dev *ptdev,
struct pt_reg_grp_info_tbl *grp_reg, uint32_t base_offset);
static int pt_byte_reg_read(struct pt_dev *ptdev,
struct pt_reg_tbl *cfg_entry,
@@ -438,7 +444,7 @@ static struct pt_reg_info_tbl pt_emu_reg
.init_val = 0x0000,
.ro_mask = 0x0000,
.emu_mask = 0xFFFF,
- .init = pt_common_reg_init,
+ .init = pt_linkctrl_reg_init,
.u.w.read = pt_word_reg_read,
.u.w.write = pt_linkctrl_reg_write,
},
@@ -449,7 +455,7 @@ static struct pt_reg_info_tbl pt_emu_reg
.init_val = 0x0000,
.ro_mask = 0x0000,
.emu_mask = 0xFFFF,
- .init = pt_common_reg_init,
+ .init = pt_devctrl2_reg_init,
.u.w.read = pt_word_reg_read,
.u.w.write = pt_devctrl2_reg_write,
},
@@ -666,8 +672,8 @@ static const struct pt_reg_grp_info_tbl
{
.grp_id = PCI_CAP_ID_EXP,
.grp_type = GRP_TYPE_EMU,
- .grp_size = 0x3C,
- .size_init = pt_reg_grp_size_init,
+ .grp_size = 0xFF,
+ .size_init = pt_pcie_size_init,
.emu_reg_tbl= pt_emu_reg_pcie_tbl,
},
/* MSI-X Capability Structure reg group */
@@ -1869,12 +1875,57 @@ static uint32_t pt_bar_reg_init(struct p
return reg_field;
}
+/* initialize Link Control register */
+static uint32_t pt_linkctrl_reg_init(struct pt_dev *ptdev,
+ struct pt_reg_info_tbl *reg, uint32_t real_offset)
+{
+ uint8_t cap_ver = 0;
+ uint8_t dev_type = 0;
+
+ cap_ver = (ptdev->dev.config[(real_offset - reg->offset) + PCI_EXP_FLAGS] &
+ (uint8_t)PCI_EXP_FLAGS_VERS);
+ dev_type = (ptdev->dev.config[(real_offset - reg->offset) + PCI_EXP_FLAGS]
&
+ (uint8_t)PCI_EXP_FLAGS_TYPE) >> 4;
+
+ /* no need to initialize in case of Root Complex Integrated Endpoint
+ * with cap_ver 1.x
+ */
+ if ((dev_type == PCI_EXP_TYPE_ROOT_INT_EP) && (cap_ver == 1))
+ return PT_INVALID_REG;
+
+ return reg->init_val;
+}
+
+/* initialize Device Control 2 register */
+static uint32_t pt_devctrl2_reg_init(struct pt_dev *ptdev,
+ struct pt_reg_info_tbl *reg, uint32_t real_offset)
+{
+ uint8_t cap_ver = 0;
+
+ cap_ver = (ptdev->dev.config[(real_offset - reg->offset) + PCI_EXP_FLAGS] &
+ (uint8_t)PCI_EXP_FLAGS_VERS);
+
+ /* no need to initialize in case of cap_ver 1.x */
+ if (cap_ver == 1)
+ return PT_INVALID_REG;
+
+ return reg->init_val;
+}
+
/* initialize Link Control 2 register */
static uint32_t pt_linkctrl2_reg_init(struct pt_dev *ptdev,
struct pt_reg_info_tbl *reg, uint32_t real_offset)
{
int reg_field = 0;
-
+ uint8_t cap_ver = 0;
+
+ cap_ver = (ptdev->dev.config[(real_offset - reg->offset) + PCI_EXP_FLAGS] &
+ (uint8_t)PCI_EXP_FLAGS_VERS);
+
+ /* no need to initialize in case of cap_ver 1.x */
+ if (cap_ver == 1)
+ return PT_INVALID_REG;
+
/* set Supported Link Speed */
reg_field |=
(0x0F &
@@ -2034,6 +2085,91 @@ static uint8_t pt_vendor_size_init(struc
struct pt_reg_grp_info_tbl *grp_reg, uint32_t base_offset)
{
return ptdev->dev.config[base_offset + 0x02];
+}
+
+/* get PCI Express Capability Structure register group size */
+static uint8_t pt_pcie_size_init(struct pt_dev *ptdev,
+ struct pt_reg_grp_info_tbl *grp_reg, uint32_t base_offset)
+{
+ PCIDevice *d = &ptdev->dev;
+ uint16_t exp_flag = 0;
+ uint16_t type = 0;
+ uint16_t vers = 0;
+ uint8_t pcie_size = 0;
+
+ exp_flag = *((uint16_t*)(d->config + (base_offset + PCI_EXP_FLAGS)));
+ type = (exp_flag & PCI_EXP_FLAGS_TYPE) >> 4;
+ vers = (exp_flag & PCI_EXP_FLAGS_VERS);
+
+ /* calculate size depend on capability version and device/port type */
+ /* in case of PCI Express Base Specification Rev 1.x */
+ if (vers == 1)
+ {
+ /* The PCI Express Capabilities, Device Capabilities, and Device
+ * Status/Control registers are required for all PCI Express devices.
+ * The Link Capabilities and Link Status/Control are required for all
+ * Endpoints that are not Root Complex Integrated Endpoints. Endpoints
+ * are not required to implement registers other than those listed
+ * above and terminate the capability structure.
+ */
+ switch (type) {
+ case PCI_EXP_TYPE_ENDPOINT:
+ case PCI_EXP_TYPE_LEG_END:
+ pcie_size = 0x14;
+ break;
+ case PCI_EXP_TYPE_ROOT_INT_EP:
+ /* has no link */
+ pcie_size = 0x0C;
+ break;
+ /* only EndPoint passthrough is supported */
+ case PCI_EXP_TYPE_ROOT_PORT:
+ case PCI_EXP_TYPE_UPSTREAM:
+ case PCI_EXP_TYPE_DOWNSTREAM:
+ case PCI_EXP_TYPE_PCI_BRIDGE:
+ case PCI_EXP_TYPE_PCIE_BRIDGE:
+ case PCI_EXP_TYPE_ROOT_EC:
+ default:
+ /* exit I/O emulator */
+ PT_LOG("Internal error: Unsupported device/port type[%d]. "
+ "I/O emulator exit.\n", type);
+ exit(1);
+ }
+ }
+ /* in case of PCI Express Base Specification Rev 2.0 */
+ else if (vers == 2)
+ {
+ switch (type) {
+ case PCI_EXP_TYPE_ENDPOINT:
+ case PCI_EXP_TYPE_LEG_END:
+ case PCI_EXP_TYPE_ROOT_INT_EP:
+ /* For Functions that do not implement the registers,
+ * these spaces must be hardwired to 0b.
+ */
+ pcie_size = 0x3C;
+ break;
+ /* only EndPoint passthrough is supported */
+ case PCI_EXP_TYPE_ROOT_PORT:
+ case PCI_EXP_TYPE_UPSTREAM:
+ case PCI_EXP_TYPE_DOWNSTREAM:
+ case PCI_EXP_TYPE_PCI_BRIDGE:
+ case PCI_EXP_TYPE_PCIE_BRIDGE:
+ case PCI_EXP_TYPE_ROOT_EC:
+ default:
+ /* exit I/O emulator */
+ PT_LOG("Internal error: Unsupported device/port type[%d]. "
+ "I/O emulator exit.\n", type);
+ exit(1);
+ }
+ }
+ else
+ {
+ /* exit I/O emulator */
+ PT_LOG("Internal error: Unsupported capability version[%d]. "
+ "I/O emulator exit.\n", vers);
+ exit(1);
+ }
+
+ return pcie_size;
}
/* read byte size emulate register */
diff -r 294fc8fc4ba0 -r a5bf2535e7bb tools/ioemu/hw/pass-through.h
--- a/tools/ioemu/hw/pass-through.h Thu Sep 04 11:26:25 2008 +0100
+++ b/tools/ioemu/hw/pass-through.h Thu Sep 04 11:28:17 2008 +0100
@@ -60,6 +60,21 @@
#ifndef PCI_MSI_FLAGS_MASK_BIT
/* interrupt masking & reporting supported */
#define PCI_MSI_FLAGS_MASK_BIT 0x0100
+#endif
+
+#ifndef PCI_EXP_TYPE_PCIE_BRIDGE
+/* PCI/PCI-X to PCIE Bridge */
+#define PCI_EXP_TYPE_PCIE_BRIDGE 0x8
+#endif
+
+#ifndef PCI_EXP_TYPE_ROOT_INT_EP
+/* Root Complex Integrated Endpoint */
+#define PCI_EXP_TYPE_ROOT_INT_EP 0x9
+#endif
+
+#ifndef PCI_EXP_TYPE_ROOT_EC
+/* Root Complex Event Collector */
+#define PCI_EXP_TYPE_ROOT_EC 0xa
#endif
#define PT_INVALID_REG 0xFFFFFFFF /* invalid register value */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|