All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC PATCH 00/04] pci bridge clean up and multiple pci bus support
@ 2009-05-01 13:16 Isaku Yamahata
  2009-05-01 13:16 ` [Qemu-devel] [PATCH] minor fix of pci_register_bus() Isaku Yamahata
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Isaku Yamahata @ 2009-05-01 13:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: mtosatti, armbru, mst

Although I haven't finished this work, people seems to be
interested in pci bridge emultion and multiple pci bus support.
So I decided to send out these patches to avoid duplicated work.

Please comment on pci bridge emulation and multiple pci bus support.
I'm aware of Markus's work and I'm willing to help it.
Eventually those patches will be integrated.

thanks,

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Qemu-devel] [PATCH] minor fix of pci_register_bus()
  2009-05-01 13:16 [Qemu-devel] [RFC PATCH 00/04] pci bridge clean up and multiple pci bus support Isaku Yamahata
@ 2009-05-01 13:16 ` Isaku Yamahata
  2009-05-03 19:16   ` Blue Swirl
  2009-05-01 13:17 ` [Qemu-devel] [PATCH] use PCI_HEADER_TYPE Isaku Yamahata
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 7+ messages in thread
From: Isaku Yamahata @ 2009-05-01 13:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: mtosatti, 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 13:16 [Qemu-devel] [RFC PATCH 00/04] pci bridge clean up and multiple pci bus support Isaku Yamahata
  2009-05-01 13:16 ` [Qemu-devel] [PATCH] minor fix of pci_register_bus() Isaku Yamahata
@ 2009-05-01 13:17 ` Isaku Yamahata
  2009-05-03 19:07   ` Blue Swirl
  2009-05-01 13:17 ` [Qemu-devel] [PATCH] pci bus: preliminary for multi pci bus support Isaku Yamahata
  2009-05-01 13:17 ` [Qemu-devel] [PATCH] try to implement complete pci-to-pci bridge emulator Isaku Yamahata
  3 siblings, 1 reply; 7+ messages in thread
From: Isaku Yamahata @ 2009-05-01 13:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: mtosatti, 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 13:16 [Qemu-devel] [RFC PATCH 00/04] pci bridge clean up and multiple pci bus support Isaku Yamahata
  2009-05-01 13:16 ` [Qemu-devel] [PATCH] minor fix of pci_register_bus() Isaku Yamahata
  2009-05-01 13:17 ` [Qemu-devel] [PATCH] use PCI_HEADER_TYPE Isaku Yamahata
@ 2009-05-01 13:17 ` Isaku Yamahata
  2009-05-01 13:17 ` [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 13:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: mtosatti, 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 13:16 [Qemu-devel] [RFC PATCH 00/04] pci bridge clean up and multiple pci bus support Isaku Yamahata
                   ` (2 preceding siblings ...)
  2009-05-01 13:17 ` [Qemu-devel] [PATCH] pci bus: preliminary for multi pci bus support Isaku Yamahata
@ 2009-05-01 13:17 ` Isaku Yamahata
  3 siblings, 0 replies; 7+ messages in thread
From: Isaku Yamahata @ 2009-05-01 13:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: mtosatti, 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] use PCI_HEADER_TYPE.
  2009-05-01 13:17 ` [Qemu-devel] [PATCH] use PCI_HEADER_TYPE Isaku Yamahata
@ 2009-05-03 19:07   ` Blue Swirl
  0 siblings, 0 replies; 7+ messages in thread
From: Blue Swirl @ 2009-05-03 19:07 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: mtosatti, mst, qemu-devel, armbru

On 5/1/09, Isaku Yamahata <yamahata@valinux.co.jp> wrote:
> use symbolic value instead of 0x0e and related value.
>
>  Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

Thanks, applied.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH] minor fix of pci_register_bus()
  2009-05-01 13:16 ` [Qemu-devel] [PATCH] minor fix of pci_register_bus() Isaku Yamahata
@ 2009-05-03 19:16   ` Blue Swirl
  0 siblings, 0 replies; 7+ messages in thread
From: Blue Swirl @ 2009-05-03 19:16 UTC (permalink / raw)
  To: Isaku Yamahata; +Cc: mtosatti, mst, qemu-devel, armbru

On 5/1/09, Isaku Yamahata <yamahata@valinux.co.jp> wrote:
> keep first_bus linked list correct.
>
>  Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

Thanks, applied.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2009-05-03 19:17 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-05-01 13:16 [Qemu-devel] [RFC PATCH 00/04] pci bridge clean up and multiple pci bus support Isaku Yamahata
2009-05-01 13:16 ` [Qemu-devel] [PATCH] minor fix of pci_register_bus() Isaku Yamahata
2009-05-03 19:16   ` Blue Swirl
2009-05-01 13:17 ` [Qemu-devel] [PATCH] use PCI_HEADER_TYPE Isaku Yamahata
2009-05-03 19:07   ` Blue Swirl
2009-05-01 13:17 ` [Qemu-devel] [PATCH] pci bus: preliminary for multi pci bus support Isaku Yamahata
2009-05-01 13:17 ` [Qemu-devel] [PATCH] try to implement complete pci-to-pci bridge emulator Isaku Yamahata

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.