* [Qemu-devel] [PATCH] minor fix of pci_register_bus()
2009-05-01 9:33 [Qemu-devel] [PATCH 00/04] RFC: pci bridge clean up and multiple pci bus support Isaku Yamahata
@ 2009-05-01 9:33 ` Isaku Yamahata
2009-05-01 9:33 ` [Qemu-devel] [PATCH] use PCI_HEADER_TYPE Isaku Yamahata
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Isaku Yamahata @ 2009-05-01 9:33 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, mst
keep first_bus linked list correct.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
hw/pci.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/hw/pci.c b/hw/pci.c
index bfd3942..c824014 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -100,6 +100,7 @@ PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
bus->irq_opaque = pic;
bus->devfn_min = devfn_min;
bus->nirq = nirq;
+ bus->next = first_bus;
first_bus = bus;
register_savevm("PCIBUS", nbus++, 1, pcibus_save, pcibus_load, bus);
return bus;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH] use PCI_HEADER_TYPE.
2009-05-01 9:33 [Qemu-devel] [PATCH 00/04] RFC: pci bridge clean up and multiple pci bus support Isaku Yamahata
2009-05-01 9:33 ` [Qemu-devel] [PATCH] minor fix of pci_register_bus() Isaku Yamahata
@ 2009-05-01 9:33 ` Isaku Yamahata
2009-05-01 9:33 ` [Qemu-devel] [PATCH] pci bus: preliminary for multi pci bus support Isaku Yamahata
2009-05-01 9:33 ` [Qemu-devel] [PATCH] try to implement complete pci-to-pci bridge emulator Isaku Yamahata
3 siblings, 0 replies; 7+ messages in thread
From: Isaku Yamahata @ 2009-05-01 9:33 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, mst
use symbolic value instead of 0x0e and related value.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
hw/ac97.c | 2 +-
hw/acpi.c | 2 +-
hw/apb_pci.c | 2 +-
hw/cirrus_vga.c | 3 +--
hw/grackle_pci.c | 4 ++--
hw/ide.c | 6 +++---
hw/macio.c | 2 +-
hw/ne2000.c | 2 +-
hw/openpic.c | 2 +-
hw/pci.c | 3 ++-
hw/pci.h | 4 ++++
hw/pcnet.c | 2 +-
hw/piix_pci.c | 9 ++++++---
hw/prep_pci.c | 2 +-
hw/rtl8139.c | 2 +-
hw/sun4u.c | 2 +-
hw/unin_pci.c | 8 ++++----
hw/usb-uhci.c | 4 ++--
hw/vga.c | 2 +-
hw/virtio.c | 2 +-
hw/vmware_vga.c | 4 +---
21 files changed, 37 insertions(+), 32 deletions(-)
diff --git a/hw/ac97.c b/hw/ac97.c
index ade2719..d9ef141 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -1348,7 +1348,7 @@ int ac97_init (PCIBus *bus, AudioState *audio)
c[0x08] = 0x01; /* rid revision ro */
c[0x09] = 0x00; /* pi programming interface ro */
pci_config_set_class(c, PCI_CLASS_MULTIMEDIA_AUDIO); /* ro */
- c[0x0e] = 0x00; /* headtyp header type ro */
+ c[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; /* headtyp header type ro */
c[0x10] = 0x01; /* nabmar native audio mixer base
address rw */
diff --git a/hw/acpi.c b/hw/acpi.c
index 53c1fec..bc5b73c 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -515,7 +515,7 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
pci_conf[0x08] = 0x03; // revision number
pci_conf[0x09] = 0x00;
pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_OTHER);
- pci_conf[0x0e] = 0x00; // header_type
+ pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
pci_conf[0x3d] = 0x01; // interrupt pin 1
pci_conf[0x40] = 0x01; /* PM io base read only bit */
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index a179acd..36ecb55 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -262,7 +262,7 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
d->config[0x09] = 0x00; // programming i/f
pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
d->config[0x0D] = 0x10; // latency_timer
- d->config[0x0E] = 0x00; // header_type
+ d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
/* APB secondary busses */
*bus2 = pci_bridge_init(s->bus, 8, PCI_VENDOR_ID_SUN,
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index df98f85..815681a 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -187,7 +187,6 @@
// PCI 0x08, 0x00ff0000
#define PCI_CLASS_SUB_VGA 0x00
// PCI 0x0c, 0x00ff0000 (0x0c:cacheline,0x0d:latency,0x0e:headertype,0x0f:Built-in self test)
-#define PCI_CLASS_HEADERTYPE_00h 0x00
// 0x10-0x3f (headertype 00h)
// PCI 0x10,0x14,0x18,0x1c,0x20,0x24: base address mapping registers
// 0x10: MEMBASE, 0x14: IOBASE(hard-coded in XFree86 3.x)
@@ -3349,7 +3348,7 @@ void pci_cirrus_vga_init(PCIBus *bus, int vga_ram_size)
pci_config_set_device_id(pci_conf, device_id);
pci_conf[0x04] = PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS;
pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
- pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h;
+ pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL;
/* setup VGA */
s = &d->cirrus_vga;
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index 5161727..61606b2 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -149,7 +149,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic)
d->config[0x08] = 0x00; // revision
d->config[0x09] = 0x01;
pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
- d->config[0x0e] = 0x00; // header_type
+ d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
#if 0
/* PCI2PCI bridge same values as PearPC - check this */
@@ -157,7 +157,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic)
pci_config_set_device_id(d->config, PCI_DEVICE_ID_DEC_21154);
d->config[0x08] = 0x02; // revision
pci_config_set_class(d->config, PCI_CLASS_BRIDGE_PCI);
- d->config[0x0e] = 0x01; // header_type
+ d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_BRIDGE; // header_type
d->config[0x18] = 0x0; // primary_bus
d->config[0x19] = 0x1; // secondary_bus
diff --git a/hw/ide.c b/hw/ide.c
index e61cefb..b2a1288 100644
--- a/hw/ide.c
+++ b/hw/ide.c
@@ -3301,7 +3301,7 @@ void pci_cmd646_ide_init(PCIBus *bus, BlockDriverState **hd_table,
pci_conf[0x09] = 0x8f;
pci_config_set_class(pci_conf, PCI_CLASS_STORAGE_IDE);
- pci_conf[0x0e] = 0x00; // header_type
+ pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
pci_conf[0x51] = 0x04; // enable IDE0
if (secondary_ide_enabled) {
@@ -3371,7 +3371,7 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371SB_1);
pci_conf[0x09] = 0x80; // legacy ATA mode
pci_config_set_class(pci_conf, PCI_CLASS_STORAGE_IDE);
- pci_conf[0x0e] = 0x00; // header_type
+ pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
qemu_register_reset(piix3_reset, d);
piix3_reset(d);
@@ -3411,7 +3411,7 @@ void pci_piix4_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB);
pci_conf[0x09] = 0x80; // legacy ATA mode
pci_config_set_class(pci_conf, PCI_CLASS_STORAGE_IDE);
- pci_conf[0x0e] = 0x00; // header_type
+ pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
qemu_register_reset(piix3_reset, d);
piix3_reset(d);
diff --git a/hw/macio.c b/hw/macio.c
index 1333aa3..28dbaa7 100644
--- a/hw/macio.c
+++ b/hw/macio.c
@@ -110,7 +110,7 @@ void macio_init (PCIBus *bus, int device_id, int is_oldworld, int pic_mem_index,
pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
pci_config_set_device_id(d->config, device_id);
pci_config_set_class(d->config, PCI_CLASS_OTHERS << 8);
- d->config[0x0e] = 0x00; // header_type
+ d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
d->config[0x3d] = 0x01; // interrupt on pin 1
diff --git a/hw/ne2000.c b/hw/ne2000.c
index 99612e2..07e512e 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -814,7 +814,7 @@ PCIDevice *pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn)
pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_REALTEK);
pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_REALTEK_8029);
pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET);
- pci_conf[0x0e] = 0x00; // header_type
+ pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
pci_conf[0x3d] = 1; // interrupt pin 0
pci_register_io_region(&d->dev, 0, 0x100,
diff --git a/hw/openpic.c b/hw/openpic.c
index 733284a..53747c4 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -1208,7 +1208,7 @@ qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_IBM);
pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_IBM_OPENPIC2);
pci_config_set_class(pci_conf, PCI_CLASS_SYSTEM_OTHER); // FIXME?
- pci_conf[0x0e] = 0x00; // header_type
+ pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
pci_conf[0x3d] = 0x00; // no interrupt pin
/* Register I/O spaces */
diff --git a/hw/pci.c b/hw/pci.c
index c824014..ee7d403 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -884,7 +884,8 @@ PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
s->dev.config[0x09] = 0x00; // programming i/f
pci_config_set_class(s->dev.config, PCI_CLASS_BRIDGE_PCI);
s->dev.config[0x0D] = 0x10; // latency_timer
- s->dev.config[0x0E] = 0x81; // header_type
+ s->dev.config[PCI_HEADER_TYPE] =
+ PCI_HEADER_TYPE_MULTI_FUNCTION | PCI_HEADER_TYPE_BRIDGE; // header_type
s->dev.config[0x1E] = 0xa0; // secondary status
s->bus = pci_register_secondary_bus(&s->dev, map_irq);
diff --git a/hw/pci.h b/hw/pci.h
index 4a30d98..ff858a1 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -102,6 +102,10 @@ typedef struct PCIIORegion {
#define PCI_REVISION_ID 0x08 /* 8 bits */
#define PCI_CLASS_DEVICE 0x0a /* Device class */
#define PCI_HEADER_TYPE 0x0e /* 8 bits */
+#define PCI_HEADER_TYPE_NORMAL 0
+#define PCI_HEADER_TYPE_BRIDGE 1
+#define PCI_HEADER_TYPE_CARDBUS 2
+#define PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
#define PCI_SUBSYSTEM_VENDOR_ID 0x2c /* 16 bits */
#define PCI_SUBSYSTEM_ID 0x2e /* 16 bits */
#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
diff --git a/hw/pcnet.c b/hw/pcnet.c
index acbaee6..4e15c01 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -2033,7 +2033,7 @@ PCIDevice *pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn)
pci_conf[0x08] = 0x10;
pci_conf[0x09] = 0x00;
pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET);
- pci_conf[0x0e] = 0x00; // header_type
+ pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
*(uint32_t *)&pci_conf[0x10] = cpu_to_le32(0x00000001);
*(uint32_t *)&pci_conf[0x14] = cpu_to_le32(0x00000000);
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index b8607aa..2b19cc6 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -196,7 +196,7 @@ PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic)
pci_config_set_device_id(d->config, PCI_DEVICE_ID_INTEL_82441);
d->config[0x08] = 0x02; // revision
pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
- d->config[0x0e] = 0x00; // header_type
+ d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
d->config[0x72] = 0x02; /* SMRAM */
@@ -334,7 +334,8 @@ int piix3_init(PCIBus *bus, int devfn)
pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371SB_0); // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_ISA);
- pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
+ pci_conf[PCI_HEADER_TYPE] =
+ PCI_HEADER_TYPE_NORMAL | PCI_HEADER_TYPE_MULTI_FUNCTION; // header_type = PCI_multifunction, generic
piix3_reset(d);
return d->devfn;
@@ -355,7 +356,9 @@ int piix4_init(PCIBus *bus, int devfn)
pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB_0); // 82371AB/EB/MB PIIX4 PCI-to-ISA bridge
pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_ISA);
- pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
+ pci_conf[PCI_HEADER_TYPE] =
+ PCI_HEADER_TYPE_NORMAL | PCI_HEADER_TYPE_MULTI_FUNCTION; // header_type = PCI_multifunction, generic
+
piix4_reset(d);
return d->devfn;
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index 2055005..a97b845 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -161,7 +161,7 @@ PCIBus *pci_prep_init(qemu_irq *pic)
pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
d->config[0x0C] = 0x08; // cache_line_size
d->config[0x0D] = 0x10; // latency_timer
- d->config[0x0E] = 0x00; // header_type
+ d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
d->config[0x34] = 0x00; // capabilities_pointer
return s->bus;
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 0093ff4..541d2cd 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3458,7 +3458,7 @@ PCIDevice *pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn)
pci_conf[0x04] = 0x05; /* command = I/O space, Bus Master */
pci_conf[0x08] = RTL8139_PCI_REVID; /* PCI revision ID; >=0x20 is for 8139C+ */
pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET);
- pci_conf[0x0e] = 0x00; /* header_type */
+ pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; /* header_type */
pci_conf[0x3d] = 1; /* interrupt pin 0 */
pci_conf[0x34] = 0xdc;
diff --git a/hw/sun4u.c b/hw/sun4u.c
index de635d4..8f9e56b 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -318,7 +318,7 @@ pci_ebus_init(PCIBus *bus, int devfn)
s->config[0x09] = 0x00; // programming i/f
pci_config_set_class(s->config, PCI_CLASS_BRIDGE_OTHER);
s->config[0x0D] = 0x0a; // latency_timer
- s->config[0x0E] = 0x00; // header_type
+ s->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
pci_register_io_region(s, 0, 0x1000000, PCI_ADDRESS_SPACE_MEM,
ebus_mmio_mapfunc);
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index 9fc073a..b751916 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -192,7 +192,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
d->config[0x0C] = 0x08; // cache_line_size
d->config[0x0D] = 0x10; // latency_timer
- d->config[0x0E] = 0x00; // header_type
+ d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
d->config[0x34] = 0x00; // capabilities_pointer
#if 0 // XXX: not activated as PPC BIOS doesn't handle multiple buses properly
@@ -205,7 +205,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
pci_config_set_class(d->config, PCI_CLASS_BRIDGE_PCI);
d->config[0x0C] = 0x08; // cache_line_size
d->config[0x0D] = 0x20; // latency_timer
- d->config[0x0E] = 0x01; // header_type
+ d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_BRIDGE; // header_type
d->config[0x18] = 0x01; // primary_bus
d->config[0x19] = 0x02; // secondary_bus
@@ -240,7 +240,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
d->config[0x0C] = 0x08; // cache_line_size
d->config[0x0D] = 0x10; // latency_timer
- d->config[0x0E] = 0x00; // header_type
+ d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
// d->config[0x34] = 0x80; // capabilities_pointer
#if 0 // XXX: not needed for now
@@ -261,7 +261,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
d->config[0x0C] = 0x08; // cache_line_size
d->config[0x0D] = 0x10; // latency_timer
- d->config[0x0E] = 0x00; // header_type
+ d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
d->config[0x34] = 0x00; // capabilities_pointer
#endif
register_savevm("uninorth", 0, 1, pci_unin_save, pci_unin_load, d);
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index d42d394..689d40a 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1084,7 +1084,7 @@ void usb_uhci_piix3_init(PCIBus *bus, int devfn)
pci_conf[0x08] = 0x01; // revision number
pci_conf[0x09] = 0x00;
pci_config_set_class(pci_conf, PCI_CLASS_SERIAL_USB);
- pci_conf[0x0e] = 0x00; // header_type
+ pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
pci_conf[0x3d] = 4; // interrupt pin 3
pci_conf[0x60] = 0x10; // release number
@@ -1118,7 +1118,7 @@ void usb_uhci_piix4_init(PCIBus *bus, int devfn)
pci_conf[0x08] = 0x01; // revision number
pci_conf[0x09] = 0x00;
pci_config_set_class(pci_conf, PCI_CLASS_SERIAL_USB);
- pci_conf[0x0e] = 0x00; // header_type
+ pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
pci_conf[0x3d] = 4; // interrupt pin 3
pci_conf[0x60] = 0x10; // release number
diff --git a/hw/vga.c b/hw/vga.c
index 517ce3d..2de92af 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -2507,7 +2507,7 @@ int pci_vga_init(PCIBus *bus, int vga_ram_size,
pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_QEMU);
pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_QEMU_VGA);
pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
- pci_conf[0x0e] = 0x00; // header_type
+ pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
/* XXX: vga_ram_size must be a power of two */
pci_register_io_region(&d->dev, 0, vga_ram_size,
diff --git a/hw/virtio.c b/hw/virtio.c
index 4aa5f20..78c7637 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -788,7 +788,7 @@ VirtIODevice *virtio_init_pci(PCIBus *bus, const char *name,
config[0x09] = pif;
pci_config_set_class(config, class_code);
- config[0x0e] = 0x00;
+ config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL;
config[0x2c] = subvendor & 0xFF;
config[0x2d] = (subvendor >> 8) & 0xFF;
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index 2299aff..26cf789 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1210,8 +1210,6 @@ static void pci_vmsvga_map_mem(PCIDevice *pci_dev, int region_num,
iomemtype);
}
-#define PCI_CLASS_HEADERTYPE_00h 0x00
-
void pci_vmsvga_init(PCIBus *bus, int vga_ram_size)
{
struct pci_vmsvga_state_s *s;
@@ -1226,7 +1224,7 @@ void pci_vmsvga_init(PCIBus *bus, int vga_ram_size)
pci_config_set_class(s->card.config, PCI_CLASS_DISPLAY_VGA);
s->card.config[0x0c] = 0x08; /* Cache line size */
s->card.config[0x0d] = 0x40; /* Latency timer */
- s->card.config[0x0e] = PCI_CLASS_HEADERTYPE_00h;
+ s->card.config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL;
s->card.config[0x2c] = PCI_VENDOR_ID_VMWARE & 0xff;
s->card.config[0x2d] = PCI_VENDOR_ID_VMWARE >> 8;
s->card.config[0x2e] = SVGA_PCI_DEVICE_ID & 0xff;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH] pci bus: preliminary for multi pci bus support.
2009-05-01 9:33 [Qemu-devel] [PATCH 00/04] RFC: pci bridge clean up and multiple pci bus support Isaku Yamahata
2009-05-01 9:33 ` [Qemu-devel] [PATCH] minor fix of pci_register_bus() Isaku Yamahata
2009-05-01 9:33 ` [Qemu-devel] [PATCH] use PCI_HEADER_TYPE Isaku Yamahata
@ 2009-05-01 9:33 ` Isaku Yamahata
2009-05-01 9:33 ` [Qemu-devel] [PATCH] try to implement complete pci-to-pci bridge emulator Isaku Yamahata
3 siblings, 0 replies; 7+ messages in thread
From: Isaku Yamahata @ 2009-05-01 9:33 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, mst
This patch is preliminary for multi pci bus support to
add -pci option.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
Makefile.target | 2 +-
hw/apb_pci.c | 4 +-
hw/pc.c | 7 ++
hw/pci.c | 20 ++++--
hw/pci.h | 3 +-
hw/pci_bridge.c | 208 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/pci_bridge.h | 35 +++++++++
hw/pci_ids.h | 1 +
qemu-options.hx | 10 +++
vl.c | 5 ++
10 files changed, 285 insertions(+), 10 deletions(-)
create mode 100644 hw/pci_bridge.c
create mode 100644 hw/pci_bridge.h
diff --git a/Makefile.target b/Makefile.target
index 82ada5a..897b039 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -498,7 +498,7 @@ endif #CONFIG_BSD_USER
# System emulator target
ifndef CONFIG_USER_ONLY
-OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o dma-helpers.o
+OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o dma-helpers.o pci_bridge.o
# virtio has to be here due to weird dependency between PCI and virtio-net.
# need to fix this properly
OBJS+=virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 36ecb55..3685330 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -267,9 +267,9 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
/* APB secondary busses */
*bus2 = pci_bridge_init(s->bus, 8, PCI_VENDOR_ID_SUN,
PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
- "Advanced PCI Bus secondary bridge 1");
+ "Advanced PCI Bus secondary bridge 1", 1);
*bus3 = pci_bridge_init(s->bus, 9, PCI_VENDOR_ID_SUN,
PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
- "Advanced PCI Bus secondary bridge 2");
+ "Advanced PCI Bus secondary bridge 2", 2);
return s->bus;
}
diff --git a/hw/pc.c b/hw/pc.c
index 07b75f3..f881a30 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -25,6 +25,7 @@
#include "pc.h"
#include "fdc.h"
#include "pci.h"
+#include "pci_bridge.h"
#include "block.h"
#include "sysemu.h"
#include "audio/audio.h"
@@ -1023,6 +1024,12 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size,
}
}
+ if (pci_enabled) {
+ if (pci_device_init() < 0) {
+ exit(1);
+ }
+ }
+
for(i = 0; i < nb_nics; i++) {
NICInfo *nd = &nd_table[i];
diff --git a/hw/pci.c b/hw/pci.c
index ee7d403..0be3662 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -40,7 +40,7 @@ struct PCIBus {
SetIRQFunc *low_set_irq;
qemu_irq *irq_opaque;
PCIDevice *devices[256];
- PCIDevice *parent_dev;
+ PCIDevice *self;
PCIBus *next;
/* The bus IRQ state is the logical OR of the connected devices.
Keep a count of the number of devices with raised IRQs. */
@@ -106,12 +106,16 @@ PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
return bus;
}
-static PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn map_irq)
+/* XXX qemu_irq, devfn_min, nirq */
+static PCIBus *pci_register_secondary_bus(PCIDevice *dev, int bus_num,
+ pci_map_irq_fn map_irq)
{
PCIBus *bus;
bus = qemu_mallocz(sizeof(PCIBus));
bus->map_irq = map_irq;
- bus->parent_dev = dev;
+ bus->self = dev;
+ bus->bus_num = bus_num;
+
bus->next = dev->bus->next;
dev->bus->next = bus;
return bus;
@@ -654,7 +658,7 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
irq_num = bus->map_irq(pci_dev, irq_num);
if (bus->set_irq)
break;
- pci_dev = bus->parent_dev;
+ pci_dev = bus->self;
}
bus->irq_count[irq_num] += change;
bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
@@ -867,7 +871,8 @@ PCIDevice *pci_find_device(int bus_num, int slot, int function)
}
PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
- pci_map_irq_fn map_irq, const char *name)
+ pci_map_irq_fn map_irq, const char *name,
+ int secondary_bus_num)
{
PCIBridge *s;
s = (PCIBridge *)pci_register_device(bus, name, sizeof(PCIBridge),
@@ -886,8 +891,11 @@ PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
s->dev.config[0x0D] = 0x10; // latency_timer
s->dev.config[PCI_HEADER_TYPE] =
PCI_HEADER_TYPE_MULTI_FUNCTION | PCI_HEADER_TYPE_BRIDGE; // header_type
+ s->dev.config[0x18] = bus->bus_num; // primary bus number
+ s->dev.config[0x19] = secondary_bus_num; // secondary bus number
+ s->dev.config[0x1A] = secondary_bus_num; // subordinate bus number
s->dev.config[0x1E] = 0xa0; // secondary status
- s->bus = pci_register_secondary_bus(&s->dev, map_irq);
+ s->bus = pci_register_secondary_bus(&s->dev, secondary_bus_num, map_irq);
return s->bus;
}
diff --git a/hw/pci.h b/hw/pci.h
index ff858a1..5993fb3 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -197,7 +197,8 @@ int pci_assign_devaddr(const char *addr, int *domp, int *busp, unsigned *slotp);
void pci_info(Monitor *mon);
PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
- pci_map_irq_fn map_irq, const char *name);
+ pci_map_irq_fn map_irq, const char *name,
+ int secondary_bus);
static inline void
pci_config_set_vendor_id(uint8_t *pci_config, uint16_t val)
diff --git a/hw/pci_bridge.c b/hw/pci_bridge.c
new file mode 100644
index 0000000..d74737b
--- /dev/null
+++ b/hw/pci_bridge.c
@@ -0,0 +1,208 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ */
+
+#include <stdlib.h>
+
+#include "sysemu.h"
+#include "hw.h"
+#include "pci.h"
+#include "pci_bridge.h"
+
+struct PCIDeviceInfo {
+ int dom;
+ int bus;
+ unsigned int slot;
+ unsigned int func;
+ int secondary_bus;
+
+ const char *model;
+ const char *options;
+};
+
+#define MAX_PCI_DEVS 256
+static int nb_pci_devices;
+static struct PCIDeviceInfo pd_table[MAX_PCI_DEVS];
+
+/*
+ * Parse [[<domain>:]<bus>:]<slot>.<func>, return -1 on error
+ */
+static int pci_parse_devfn(const char *addr,
+ int *domp, int *busp,
+ unsigned int *slotp, unsigned int *funcp)
+{
+ const char *p;
+ char *e;
+ unsigned long val;
+ unsigned long dom = 0;
+ unsigned long bus = 0;
+ unsigned int slot = 0;
+ unsigned int func = 0;
+
+ p = addr;
+ val = strtoul(p, &e, 16);
+ if (e == p)
+ return -1;
+ if (*e == ':') {
+ bus = val;
+ p = e + 1;
+ val = strtoul(p, &e, 16);
+ if (e == p)
+ return -1;
+ if (*e == ':') {
+ dom = bus;
+ bus = val;
+ p = e + 1;
+ val = strtoul(p, &e, 16);
+ if (e == p)
+ return -1;
+ }
+ }
+ slot = val;
+
+ if (*e != '.')
+ return -1;
+ p = e + 1;
+ val = strtoul(p, &e, 16);
+ if (e == p)
+ return -1;
+ func = val;
+
+ if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7)
+ return -1;
+
+ /* For now, only 0 domain is supported */
+ if (dom != 0)
+ return -1;
+
+ *domp = dom;
+ *busp = bus;
+ *slotp = slot;
+ *funcp = func;
+ return 0;
+}
+
+int pci_device_parse(const char* options)
+{
+ int ret = -1;
+ char buf[1024];
+ char *e;
+ struct PCIDeviceInfo *pd = &pd_table[nb_pci_devices];
+
+ if (nb_pci_devices >= MAX_PCI_DEVS) {
+ /* XXX:WARN */
+ goto out;
+ }
+
+
+ if (get_param_value(buf, sizeof(buf), "pci_addr", options) < 0) {
+ /* XXX error */
+ goto out;
+ }
+ if (pci_parse_devfn(buf, &pd->dom, &pd->bus, &pd->slot, &pd->func) < 0) {
+ goto out;
+ }
+
+ if (get_param_value(buf, sizeof(buf), "secondary", options) < 0) {
+ goto out;
+ }
+ pd->secondary_bus = strtoul(buf, &e, 16);
+ if (buf == e) {
+ goto out;
+ }
+ if (pd->secondary_bus > 0xff) {
+ goto out;
+ }
+
+ if (get_param_value(buf, sizeof(buf), "model", options) < 0) {
+ goto out;
+ }
+ pd->model = strdup(buf);
+ if (pd->model == NULL) {
+ goto out;
+ }
+
+ /* save for later use */
+ pd->options = strdup(options);
+ if (pd->options == NULL) {
+ goto out;
+ }
+
+ nb_pci_devices++;
+ ret = 0;
+
+out:
+ return ret;
+}
+
+static int pci_bridge_irq(PCIDevice *pci_dev, int irq_num)
+{
+ return (PCI_SLOT(pci_dev->devfn) + irq_num + 1) % 4;
+}
+
+static int pci_device_init_one(struct PCIDeviceInfo *pd)
+{
+ PCIBus *parent_bus;
+ PCIBus *bus;
+
+ if (pci_find_device(pd->bus, pd->slot, pd->func) != NULL) {
+ return -1;
+ }
+
+ parent_bus = pci_find_bus(pd->bus);
+ if (parent_bus == NULL) {
+ return -1;
+ }
+
+ bus = pci_bridge_init(parent_bus, PCI_DEVFN(pd->slot, pd->func),
+ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_11,
+ &pci_bridge_irq, "PCI Bridge", pd->secondary_bus);
+ return 0;
+}
+
+int pci_device_init(void)
+{
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < nb_pci_devices; i++) {
+ struct PCIDeviceInfo *pd = &pd_table[i];
+ const char *model = pd->model;
+
+ if (!strcmp(model, "bridge")) {
+ ret = pci_device_init_one(pd);
+ } else {
+ /* unknown model */
+ ret = -1;
+ }
+
+ if (ret < 0)
+ break;
+ }
+ return ret;
+}
+
+/*
+ * Local variables:
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tab-mode: nil
+ * End:
+ */
diff --git a/hw/pci_bridge.h b/hw/pci_bridge.h
new file mode 100644
index 0000000..90037f0
--- /dev/null
+++ b/hw/pci_bridge.h
@@ -0,0 +1,35 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ */
+
+#ifndef QEMU_PCI_BRIDGE_H
+#define QEMU_PCI_BRIDGE_H
+
+int pci_device_parse(const char* options);
+int pci_device_init(void);
+
+#endif /* QEMU_PCI_BRIDGE_H */
+/*
+ * Local variables:
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tab-mode: nil
+ * End:
+ */
diff --git a/hw/pci_ids.h b/hw/pci_ids.h
index 427fcd5..243bd55 100644
--- a/hw/pci_ids.h
+++ b/hw/pci_ids.h
@@ -86,6 +86,7 @@
#define PCI_VENDOR_ID_INTEL 0x8086
#define PCI_DEVICE_ID_INTEL_82441 0x1237
#define PCI_DEVICE_ID_INTEL_82801AA_5 0x2415
+#define PCI_DEVICE_ID_INTEL_82801BA_11 0x244e
#define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000
#define PCI_DEVICE_ID_INTEL_82371SB_1 0x7010
#define PCI_DEVICE_ID_INTEL_82371SB_2 0x7020
diff --git a/qemu-options.hx b/qemu-options.hx
index aa786e3..91dc975 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -886,6 +886,16 @@ override the default configuration (@option{-net nic -net user}) which
is activated if no @option{-net} options are provided.
ETEXI
+DEF("pci", HAS_ARG, QEMU_OPTION_pci, \
+ "-pci pci_addr=pci_addr,model=type[,model specific options]\n"
+ "pci_addr = [[<domain>:]<bus>:]<slot>.<func>\n"
+ "model = bridge\n")
+STEXI
+@item -pci pci_addr=@var{pci_addr},model=@var{type}[,@var{model specific options}]
+connect pci device of model @var{type} at pci bus address of @var{pci_addr}
+with model specific options.
+ETEXI
+
#ifdef CONFIG_SLIRP
DEF("tftp", HAS_ARG, QEMU_OPTION_tftp, \
"-tftp dir allow tftp access to files in dir [-net user]\n")
diff --git a/vl.c b/vl.c
index ac4b32f..fcaa0a2 100644
--- a/vl.c
+++ b/vl.c
@@ -134,6 +134,7 @@ int main(int argc, char **argv)
#include "hw/usb.h"
#include "hw/pcmcia.h"
#include "hw/pc.h"
+#include "hw/pci_bridge.h"
#include "hw/audiodev.h"
#include "hw/isa.h"
#include "hw/baum.h"
@@ -5118,6 +5119,10 @@ int main(int argc, char **argv, char **envp)
net_clients[nb_net_clients] = optarg;
nb_net_clients++;
break;
+ case QEMU_OPTION_pci:
+ if (pci_device_parse(optarg) < 0)
+ exit(1);
+ break;
#ifdef CONFIG_SLIRP
case QEMU_OPTION_tftp:
tftp_prefix = optarg;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH] try to implement complete pci-to-pci bridge emulator.
2009-05-01 9:33 [Qemu-devel] [PATCH 00/04] RFC: pci bridge clean up and multiple pci bus support Isaku Yamahata
` (2 preceding siblings ...)
2009-05-01 9:33 ` [Qemu-devel] [PATCH] pci bus: preliminary for multi pci bus support Isaku Yamahata
@ 2009-05-01 9:33 ` Isaku Yamahata
2009-05-01 14:17 ` M. Warner Losh
3 siblings, 1 reply; 7+ messages in thread
From: Isaku Yamahata @ 2009-05-01 9:33 UTC (permalink / raw)
To: qemu-devel; +Cc: armbru, mst
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
hw/pci.c | 175 +++++++++++++++++++++++++++++++++++++++------------------
hw/pci.h | 30 ++++++++++
hw/unin_pci.c | 2 +-
3 files changed, 151 insertions(+), 56 deletions(-)
diff --git a/hw/pci.c b/hw/pci.c
index 0be3662..a1123cb 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -21,6 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#include <assert.h>
#include "hw.h"
#include "pci.h"
#include "monitor.h"
@@ -461,6 +462,9 @@ void pci_default_write_config(PCIDevice *d,
int can_write, i;
uint32_t end, addr;
+ assert((d->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION) ==
+ PCI_HEADER_TYPE_NORMAL);
+
if (len == 4 && ((address >= 0x10 && address < 0x10 + 4 * 6) ||
(address >= 0x30 && address < 0x34))) {
PCIIORegion *r;
@@ -490,56 +494,28 @@ void pci_default_write_config(PCIDevice *d,
/* not efficient, but simple */
addr = address;
for(i = 0; i < len; i++) {
- /* default read/write accesses */
- switch(d->config[0x0e]) {
+ /* default read/write accesses */
+ switch(addr) {
case 0x00:
- case 0x80:
- switch(addr) {
- case 0x00:
- case 0x01:
- case 0x02:
- case 0x03:
- case 0x06:
- case 0x07:
- case 0x08:
- case 0x09:
- case 0x0a:
- case 0x0b:
- case 0x0e:
- case 0x10 ... 0x27: /* base */
- case 0x2c ... 0x2f: /* read-only subsystem ID & vendor ID */
- case 0x30 ... 0x33: /* rom */
- case 0x3d:
- can_write = 0;
- break;
- default:
- can_write = 1;
- break;
- }
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x06:
+ case 0x07:
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ case 0x0e:
+ case 0x10 ... 0x27: /* base */
+ case 0x2c ... 0x2f: /* read-only subsystem ID & vendor ID */
+ case 0x30 ... 0x33: /* rom */
+ case 0x3d:
+ can_write = 0;
break;
default:
- case 0x01:
- switch(addr) {
- case 0x00:
- case 0x01:
- case 0x02:
- case 0x03:
- case 0x06:
- case 0x07:
- case 0x08:
- case 0x09:
- case 0x0a:
- case 0x0b:
- case 0x0e:
- case 0x2c ... 0x2f: /* read-only subsystem ID & vendor ID */
- case 0x38 ... 0x3b: /* rom */
- case 0x3d:
- can_write = 0;
- break;
- default:
- can_write = 1;
- break;
- }
+ can_write = 1;
+
break;
}
if (can_write) {
@@ -836,18 +812,107 @@ typedef struct {
static void pci_bridge_write_config(PCIDevice *d,
uint32_t address, uint32_t val, int len)
{
+ int can_write;
PCIBridge *s = (PCIBridge *)d;
+ uint32_t addr = address;
+ int i;
+
+ assert((d->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION) ==
+ PCI_HEADER_TYPE_BRIDGE);
+
+ for (i = 0; i < len; i++) {
+ uint8_t val8 = val & 0xff;
+ switch (addr) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x06:
+ case 0x07:
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ case 0x0e: /* header type */
+ case 0x10 ... 0x17: /* BAR */
+ /* BAR0, BAR1, ROM isn't implemented. so RO to 0 */
+ case 0x30 ... 0x33: /* IO base/limit upper 16bits. always 0*/
+ case 0x38 ... 0x3b: /* rom */
+ /* Expansion ROM isn't implemented. so RO to 0 */
+ case 0x3d:
+ case PCI_BRIDGE_CONTROL: /* 0x3e */
+ can_write = 0;
+ break;
+
+ case PCI_COMMAND: /* 0x04 */
+ val8 &= ~PCI_COMMAND_RESERVED_BRIDGE;
+ can_write = 1;
+ break;
+ case PCI_COMMAND + 1: /* 0x05 */
+ val8 &= ~PCI_COMMAND_RESERVED_MASK_HI_BRIDGE;
+ can_write = 1;
+ break;
- if (address == 0x19 || (address == 0x18 && len > 1)) {
- if (address == 0x19)
+ case PCI_IO_BASE: /* 0x1c */
+ case PCI_IO_LIMIT: /* 0x1d */
+ val8 = (val8 & PCI_IO_RANGE_MASK) |
+ (d->config[addr] & ~PCI_IO_BASE);
+ can_write = 1;
+ break;
+
+ case PCI_SECONDARY_BUS: /* 0x19 */
s->bus->bus_num = val & 0xff;
- else
- s->bus->bus_num = (val >> 8) & 0xff;
-#if defined(DEBUG_PCI)
- printf ("pci-bridge: %s: Assigned bus %d\n", d->name, s->bus->bus_num);
-#endif
+ can_write = 1;
+ break;
+
+ case PCI_MEMORY_BASE: /* 0x20 */
+ case PCI_MEMORY_LIMIT: /* 0x22 */
+ val8 = val8 & PCI_MEMORY_RANGE_MASK;
+ can_write = 1;
+ break;
+ case PCI_MEMORY_BASE + 1: /* 0x21 */
+ case PCI_MEMORY_LIMIT + 1: /* 0x23 */
+ can_write = 1;
+ break;
+
+ case PCI_PREF_MEMORY_BASE: /* 0x24 */
+ case PCI_PREF_MEMORY_LIMIT: /* 0x26*/
+ val8 = val8 & PCI_PREF_RANGE_MASK;
+ can_write = 1;
+ break;
+ case PCI_PREF_MEMORY_BASE + 1: /* 0x25 */
+ case PCI_PREF_MEMORY_LIMIT + 1: /* 0x27 */
+ can_write = 1;
+ break;
+
+ case PCI_PREF_BASE_UPPER32: /* 0x28 */
+ case PCI_PREF_LIMIT_UPPER32: /* 0x2c */
+ can_write = 0;
+ /*
+ val8 = val8 & PCI_PREF_RANGE_MASK;
+ can_write = 1;
+ */
+ break;
+ case (PCI_PREF_BASE_UPPER32 + 1) ... (PCI_PREF_BASE_UPPER32 + 3):
+ /* 0x28 ... 2b */
+ case (PCI_PREF_LIMIT_UPPER32 + 1) ... (PCI_PREF_LIMIT_UPPER32 + 3):
+ /* 0x2c ... 3f */
+ can_write = 0;
+ /* can_write = 1; */
+ break;
+
+ default:
+ can_write = 1;
+ break;
+ }
+
+ if (can_write)
+ d->config[addr] = val8;
+
+ if (+addr > 0xff)
+ break;
+ val >>= 8;
}
- pci_default_write_config(d, address, val, len);
}
PCIBus *pci_find_bus(int bus_num)
diff --git a/hw/pci.h b/hw/pci.h
index 5993fb3..f5b1052 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -137,6 +137,36 @@ typedef struct PCIIORegion {
#define PCI_COMMAND_RESERVED_MASK_HI (PCI_COMMAND_RESERVED >> 8)
+/* Header type 1 (PCI-to-PCI bridges) */
+#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */
+
+#define PCI_IO_BASE 0x1c /* I/O range behind the bridge */
+#define PCI_IO_LIMIT 0x1d
+#define PCI_IO_RANGE_TYPE_MASK 0x0fUL /* I/O bridging type */
+#define PCI_IO_RANGE_TYPE_16 0x00
+#define PCI_IO_RANGE_TYPE_32 0x01
+#define PCI_IO_RANGE_MASK (~0x0fUL)
+#define PCI_MEMORY_BASE 0x20 /* Memory range behind */
+#define PCI_MEMORY_LIMIT 0x22
+#define PCI_MEMORY_RANGE_TYPE_MASK 0x0fUL
+#define PCI_MEMORY_RANGE_MASK (~0x0fUL)
+#define PCI_PREF_MEMORY_BASE 0x24 /* Prefetchable memory range behind */
+#define PCI_PREF_MEMORY_LIMIT 0x26
+#define PCI_PREF_RANGE_TYPE_MASK 0x0fUL
+#define PCI_PREF_RANGE_TYPE_32 0x00
+#define PCI_PREF_RANGE_TYPE_64 0x01
+#define PCI_PREF_RANGE_MASK (~0x0fUL)
+#define PCI_PREF_BASE_UPPER32 0x28 /* Upper half of prefetchable memory range */
+#define PCI_PREF_LIMIT_UPPER32 0x2c
+#define PCI_IO_BASE_UPPER16 0x30 /* Upper half of I/O addresses */
+#define PCI_IO_LIMIT_UPPER16 0x32
+#define PCI_BRIDGE_CONTROL 0x3e
+
+/* Bits in the PCI Command Register (PCI 2.3 spec) */
+#define PCI_COMMAND_RESERVED_BRIDGE 0xf880
+
+#define PCI_COMMAND_RESERVED_MASK_HI_BRIDGE (PCI_COMMAND_RESERVED >> 8)
+
struct PCIDevice {
/* PCI config space */
uint8_t config[256];
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index b751916..d4c79fc 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -198,7 +198,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
#if 0 // XXX: not activated as PPC BIOS doesn't handle multiple buses properly
/* pci-to-pci bridge */
d = pci_register_device("Uni-north bridge", sizeof(PCIDevice), 0, 13 << 3,
- NULL, NULL);
+ NULL, pci_bridge_write_config);
pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_DEC);
pci_config_set_device_id(d->config, PCI_DEVICE_ID_DEC_21154);
d->config[0x08] = 0x05; // revision
--
1.6.0.2
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH] try to implement complete pci-to-pci bridge emulator.
2009-05-01 9:33 ` [Qemu-devel] [PATCH] try to implement complete pci-to-pci bridge emulator Isaku Yamahata
@ 2009-05-01 14:17 ` M. Warner Losh
2009-05-04 16:06 ` Isaku Yamahata
0 siblings, 1 reply; 7+ messages in thread
From: M. Warner Losh @ 2009-05-01 14:17 UTC (permalink / raw)
To: yamahata; +Cc: mst, qemu-devel, armbru
In message: <1241170436-2800-5-git-send-email-yamahata@valinux.co.jp>
Isaku Yamahata <yamahata@valinux.co.jp> writes:
: Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
: ---
: hw/pci.c | 175 +++++++++++++++++++++++++++++++++++++++------------------
: hw/pci.h | 30 ++++++++++
: hw/unin_pci.c | 2 +-
: 3 files changed, 151 insertions(+), 56 deletions(-)
:
: diff --git a/hw/pci.c b/hw/pci.c
: index 0be3662..a1123cb 100644
: --- a/hw/pci.c
: +++ b/hw/pci.c
...
: + case 0x01:
: + case 0x02:
: + case 0x03:
: + case 0x06:
: + case 0x07:
: + case 0x08:
: + case 0x09:
: + case 0x0a:
: + case 0x0b:
: + case 0x0e:
: + case 0x10 ... 0x27: /* base */
This is wrong. BARs are writable, and must be writable to determine
their size.
: + case 0x2c ... 0x2f: /* read-only subsystem ID & vendor ID */
: + case 0x30 ... 0x33: /* rom */
This is wrong too. You have to be able to turn on and off this
mapping by writing bit 0.
: + case 0x3d:
: + can_write = 0;
: break;
General comment: hard coded magic numbers like the above are very hard
to read.
Warner
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH] try to implement complete pci-to-pci bridge emulator.
2009-05-01 14:17 ` M. Warner Losh
@ 2009-05-04 16:06 ` Isaku Yamahata
0 siblings, 0 replies; 7+ messages in thread
From: Isaku Yamahata @ 2009-05-04 16:06 UTC (permalink / raw)
To: M. Warner Losh; +Cc: armbru, qemu-devel, mst
Thank you for review.
On Fri, May 01, 2009 at 08:17:50AM -0600, M. Warner Losh wrote:
> In message: <1241170436-2800-5-git-send-email-yamahata@valinux.co.jp>
> Isaku Yamahata <yamahata@valinux.co.jp> writes:
> : Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> : ---
> : hw/pci.c | 175 +++++++++++++++++++++++++++++++++++++++------------------
> : hw/pci.h | 30 ++++++++++
> : hw/unin_pci.c | 2 +-
> : 3 files changed, 151 insertions(+), 56 deletions(-)
> :
> : diff --git a/hw/pci.c b/hw/pci.c
> : index 0be3662..a1123cb 100644
> : --- a/hw/pci.c
> : +++ b/hw/pci.c
> ...
> : + case 0x01:
> : + case 0x02:
> : + case 0x03:
> : + case 0x06:
> : + case 0x07:
> : + case 0x08:
> : + case 0x09:
> : + case 0x0a:
> : + case 0x0b:
> : + case 0x0e:
> : + case 0x10 ... 0x27: /* base */
>
> This is wrong. BARs are writable, and must be writable to determine
> their size.
BAR/ROM case is handled by the if clause specially, so the case
doesn't make sense.
I didn't changed the original logic. Yes, these switch is confusing.
> : + case 0x2c ... 0x2f: /* read-only subsystem ID & vendor ID */
> : + case 0x30 ... 0x33: /* rom */
>
> This is wrong too. You have to be able to turn on and off this
> mapping by writing bit 0.
ditto.
Hmm, your comment makes me think of whole rewriting PCI configuration
space write emulation.
Would it be a good idea? or is it overkill because the current code is
just enough to make OSes work?
I'm thinking of something of the following (pseudo) code.
What do you think? I want feed back before digging deep into PCI
spec details and coding. Maybe the special treatment of BAR/ROM
registers can be removed with this logic.
struct pci_config_reg {
uint8 writable_mask;
void (*changed)(struct pci_dev* dev);
};
struct pci_config_reg regs[] = {
/* register 0 */
{ .writable_mask = 0 /* read only */
.changed = NULL
},
...
};
pci_default_write_config()
for (...) {
d->config[addr] =
(regs[addr].writable_mask & val) |
(~regs[addr].writable_mask & d->config[addr]);
if (regs[addr].changed)
(regs[addr].changed)(d)
> : + case 0x3d:
> : + can_write = 0;
> : break;
>
> General comment: hard coded magic numbers like the above are very hard
> to read.
So as the original code is. Okay, then I'll introduce more PCI
related constants and use them...
--
yamahata
^ permalink raw reply [flat|nested] 7+ messages in thread