qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH, RFC] Sparc64: convert APB to qdev


From: Blue Swirl
Subject: [Qemu-devel] [PATCH, RFC] Sparc64: convert APB to qdev
Date: Mon, 20 Jul 2009 13:26:19 +0300

I have a problem with APB conversion to qdev. For some reason, with
the patch applied, PCI config register access changes and OpenBIOS
can't find any PCI devices.

I get this output without the patch (CONFIG_DEBUG_PCI enabled for
OpenBIOS to get the PCI device list):

OpenBIOS for Sparc64
Initializing PCI devices...
0:0.0 - 108e:a000 - /pci -
0:1.0 - 108e:5000 - /pci/pci -
0:1.1 - 108e:5000 - /pci/pci/pci -
0:2.0 - 1234:1111 - /pci/pci/pci/QEMU,VGA -
0:3.0 - 108e:1000 - /pci/pci/pci/ebus -
0:4.0 - 10ec:8029 - /pci/pci/pci/NE2000 -
0:5.0 - 1095:646 - /pci/pci/pci/pci-ata -
Configuration device id QEMU version 1 machine id 0
CPUs: 1 x SUNW,UltraSPARC-II
UUID: 00000000-0000-0000-0000-000000000000
Welcome to OpenBIOS v1.0 built on Jul 11 2009 12:00
  Type 'help' for detailed information

[sparc64] Booting file 'disk' with parameters ''

0 > QEMU 0.11.50 monitor - type 'help' for more information
(qemu) info pci
  Bus  0, device   0, function 0:
    Host bridge: PCI device 108e:a000
      id ""
  Bus  0, device   1, function 0:
    PCI bridge: PCI device 108e:5000
      BUS 0.
      id ""
  Bus  0, device   1, function 1:
    PCI bridge: PCI device 108e:5000
      BUS 0.
      id ""
  Bus  0, device   2, function 0:
    VGA controller: PCI device 1234:1111
      BAR0: 32 bit memory at 0x00800000 [0x00ffffff].
      id ""
  Bus  0, device   3, function 0:
    Bridge: PCI device 108e:1000
      BAR0: 32 bit memory at 0x01000000 [0x01ffffff].
      BAR1: 32 bit memory at 0x02000000 [0x027fffff].
      id ""
  Bus  0, device   4, function 0:
    Ethernet controller: PCI device 10ec:8029
      IRQ 0.
      BAR0: I/O at 0x0400 [0x04ff].
      id ""
  Bus  0, device   5, function 0:
    IDE controller: PCI device 1095:0646
      IRQ 1.
      BAR0: I/O at 0x0500 [0x0507].
      BAR1: I/O at 0x0580 [0x0583].
      BAR2: I/O at 0x0600 [0x0607].
      BAR3: I/O at 0x0680 [0x0683].
      BAR4: I/O at 0x0700 [0x070f].
      id ""
(qemu) info qtree
bus: main-system-bus
  type System
  dev: m48t59, id ""
    dev-prop: size = 8192
    dev-prop: type = 59
    dev-prop: io_base = 0x74
    mmio ffffffffffffffff/0000000000002000
  dev: fdc, id ""
    gpio-in 1
    mmio ffffffffffffffff/0000000000000008

With the patch, I get the following:

OpenBIOS for Sparc64
Initializing PCI devices...
Configuration device id QEMU version 1 machine id 0
CPUs: 1 x SUNW,UltraSPARC-II
UUID: 00000000-0000-0000-0000-000000000000
Input device /pci/pci/pci/ebus/su not found.
Output device /pci/pci/pci/ebus/su not found.
Output device /pci/pci/pci/ebus/su not found.
Input device /pci/pci/pci/ebus/su not found.
Output device screen not found.
  Type 'help' for detailed information

[sparc64] Booting file 'disk' with parameters ''

0 > QEMU 0.11.50 monitor - type 'help' for more information
(qemu) info pci
  Bus  0, device   0, function 0:
    Host bridge: PCI device 108e:a000
      id ""
  Bus  0, device   1, function 0:
    PCI bridge: PCI device 108e:5000
      BUS 0.
      id ""
  Bus  0, device   1, function 1:
    PCI bridge: PCI device 108e:5000
      BUS 0.
      id ""
  Bus  0, device   2, function 0:
    VGA controller: PCI device 1234:1111
      BAR0: 32 bit memory at 0xffffffff [0x007ffffe].
      id ""
  Bus  0, device   3, function 0:
    Bridge: PCI device 108e:1000
      BAR0: 32 bit memory at 0xffffffff [0x00fffffe].
      BAR1: 32 bit memory at 0xffffffff [0x007ffffe].
      id ""
  Bus  0, device   4, function 0:
    Ethernet controller: PCI device 10ec:8029
      IRQ 0.
      BAR0: I/O at 0xffffffff [0x00fe].
      id ""
  Bus  0, device   5, function 0:
    IDE controller: PCI device 1095:0646
      IRQ 0.
      BAR0: I/O at 0xffffffff [0x0006].
      BAR1: I/O at 0xffffffff [0x0002].
      BAR2: I/O at 0xffffffff [0x0006].
      BAR3: I/O at 0xffffffff [0x0002].
      BAR4: I/O at 0xffffffff [0x000e].
      id ""
(qemu) info qtree
bus: main-system-bus
  type System
  dev: m48t59, id ""
    dev-prop: size = 8192
    dev-prop: type = 59
    dev-prop: io_base = 0x74
    mmio ffffffffffffffff/0000000000002000
  dev: fdc, id ""
    gpio-in 1
    mmio ffffffffffffffff/0000000000000008
  dev: pbm, id ""
    mmio 000001fe00002000/0000000000000040
    mmio 000001fe02000000/0000000000010000
    mmio 000001fe01000000/0000000000000010
    mmio 000001ff00000000/0000000010000000

DEBUG_ABP enabled so that the config reg accesses are printed (with the patch):
Initializing PCI devices...
APB: config_writel addr 0000000000000000 val 80000000
APB: config_writel addr 0000000000000000 val 80000000
APB: config_writel addr 0000000000000000 val 80000800
APB: config_writel addr 0000000000000000 val 80000800
APB: config_writel addr 0000000000000000 val 80001000
APB: config_writel addr 0000000000000000 val 80001000
APB: config_writel addr 0000000000000000 val 80001800
APB: config_writel addr 0000000000000000 val 80001800
APB: config_writel addr 0000000000000000 val 80002000
APB: config_writel addr 0000000000000000 val 80002000
APB: config_writel addr 0000000000000000 val 80002800
APB: config_writel addr 0000000000000000 val 80002800

Without the patch:
Initializing PCI devices...
APB: config_writel addr 0000000000000000 val 80000000
APB: config_writel addr 0000000000000000 val 80000000
APB: config_writel addr 0000000000000000 val 80000008
APB: config_writel addr 0000000000000000 val 80000008
APB: config_writel addr 0000000000000000 val 80000008
0:0.0 - 108e:a000 - APB: config_writel addr 0000000000000000 val 8000000c
/pci - APB: config_writel addr 0000000000000000 val 8000003c
APB: config_writel addr 0000000000000000 val 80000010
APB: config_writel addr 0000000000000000 val 80000010
APB: config_writel addr 0000000000000000 val 80000010

Strange.

BTW, the config probe is implemented incorrectly for both OpenBIOS and
QEMU, but that shouldn't be the issue because both assume config
mechanism 1.

Signed-off-by: Blue Swirl <address@hidden>
---
 hw/apb_pci.c |  103 ++++++++++++++++++++++++++++++++++++++++------------------
 hw/pci.c     |    8 +++--
 2 files changed, 76 insertions(+), 35 deletions(-)

diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 9f2a44d..627d8d5 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -26,7 +26,7 @@
    Ultrasparc PCI host is called the PCI Bus Module (PBM).  The APB is
    the secondary PCI bridge.  */

-#include "hw.h"
+#include "sysbus.h"
 #include "pci.h"

 /* debug APB */
@@ -42,7 +42,10 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
 typedef target_phys_addr_t pci_addr_t;
 #include "pci_host.h"

-typedef PCIHostState APBState;
+typedef struct APBState {
+    SysBusDevice busdev;
+    PCIHostState host_state;
+} APBState;

 static void pci_apb_config_writel (void *opaque, target_phys_addr_t addr,
                                          uint32_t val)
@@ -54,7 +57,7 @@ static void pci_apb_config_writel (void *opaque,
target_phys_addr_t addr,
 #endif
     APB_DPRINTF("config_writel addr " TARGET_FMT_plx " val %x\n", addr,
                 val);
-    s->config_reg = val;
+    s->host_state.config_reg = val;
 }

 static uint32_t pci_apb_config_readl (void *opaque,
@@ -63,7 +66,7 @@ static uint32_t pci_apb_config_readl (void *opaque,
     APBState *s = opaque;
     uint32_t val;

-    val = s->config_reg;
+    val = s->host_state.config_reg;
 #ifdef TARGET_WORDS_BIGENDIAN
     val = bswap32(val);
 #endif
@@ -225,34 +228,65 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
                      target_phys_addr_t mem_base,
                      qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
 {
-    APBState *s;
-    PCIDevice *d;
-    int pci_mem_config, pci_mem_data, apb_config, pci_ioport;
+    DeviceState *dev;
+    SysBusDevice *s;
+    APBState *d;

-    s = qemu_mallocz(sizeof(APBState));
     /* Ultrasparc PBM main bus */
-    s->bus = pci_register_bus(NULL, "pci",
-                              pci_apb_set_irq, pci_pbm_map_irq, pic, 0, 32);
+    dev = qdev_create(NULL, "pbm");
+    qdev_init(dev);
+    s = sysbus_from_qdev(dev);
+    /* apb_config */
+    sysbus_mmio_map(s, 0, special_base + 0x2000ULL);
+    /* pci_ioport */
+    sysbus_mmio_map(s, 1, special_base + 0x2000000ULL);
+    /* mem_config: XXX size should be 4G-prom */
+    sysbus_mmio_map(s, 2, special_base + 0x1000000ULL);
+    /* mem_data */
+    sysbus_mmio_map(s, 3, mem_base);
+    d = FROM_SYSBUS(APBState, s);
+    d->host_state.bus = pci_register_bus(NULL, "pci",
+                                         pci_apb_set_irq, pci_pbm_map_irq, pic,
+                                         0, 32);
+    pci_create_simple(d->host_state.bus, 0, "pbm");
+    /* APB secondary busses */
+    *bus2 = pci_bridge_init(d->host_state.bus, 8, PCI_VENDOR_ID_SUN,
+                            PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
+                            "Advanced PCI Bus secondary bridge 1");
+    *bus3 = pci_bridge_init(d->host_state.bus, 9, PCI_VENDOR_ID_SUN,
+                            PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
+                            "Advanced PCI Bus secondary bridge 2");

-    pci_mem_config = cpu_register_io_memory(pci_apb_config_read,
-                                            pci_apb_config_write, s);
+    return d->host_state.bus;
+}
+
+static void pci_pbm_init_device(SysBusDevice *dev)
+{
+
+    APBState *s;
+    int pci_mem_config, pci_mem_data, apb_config, pci_ioport;
+
+    s = FROM_SYSBUS(APBState, dev);
+    /* apb_config */
     apb_config = cpu_register_io_memory(apb_config_read,
                                         apb_config_write, s);
-    pci_mem_data = cpu_register_io_memory(pci_apb_read,
-                                          pci_apb_write, s);
+    sysbus_init_mmio(dev, 0x40ULL, apb_config);
+    /* pci_ioport */
     pci_ioport = cpu_register_io_memory(pci_apb_ioread,
                                           pci_apb_iowrite, s);
+    sysbus_init_mmio(dev, 0x10000ULL, pci_ioport);
+    /* mem_config  */
+    pci_mem_config = cpu_register_io_memory(pci_apb_config_read,
+                                            pci_apb_config_write, s);
+    sysbus_init_mmio(dev, 0x10ULL, pci_mem_config);
+    /* mem_data */
+    pci_mem_data = cpu_register_io_memory(pci_apb_read,
+                                          pci_apb_write, s);
+    sysbus_init_mmio(dev, 0x10000000ULL, pci_mem_data);
+}

-    cpu_register_physical_memory(special_base + 0x2000ULL, 0x40, apb_config);
-    cpu_register_physical_memory(special_base + 0x1000000ULL, 0x10,
-                                 pci_mem_config);
-    cpu_register_physical_memory(special_base + 0x2000000ULL, 0x10000,
-                                 pci_ioport);
-    cpu_register_physical_memory(mem_base, 0x10000000,
-                                 pci_mem_data); // XXX size should be 4G-prom
-
-    d = pci_register_device(s->bus, "Advanced PCI Bus", sizeof(PCIDevice),
-                            0, NULL, NULL);
+static void pbm_pci_host_init(PCIDevice *d)
+{
     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_SUN);
     pci_config_set_device_id(d->config, PCI_DEVICE_ID_SUN_SABRE);
     d->config[0x04] = 0x06; // command = bus master, pci mem
@@ -264,13 +298,18 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
     pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
     d->config[0x0D] = 0x10; // latency_timer
     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,
-                            PCI_DEVICE_ID_SUN_SIMBA, pci_apb_map_irq,
-                            "Advanced PCI Bus secondary bridge 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");
-    return s->bus;
+static PCIDeviceInfo pbm_pci_host_info = {
+    .qdev.name = "pbm",
+    .qdev.size = sizeof(PCIDevice),
+    .init      = pbm_pci_host_init,
+};
+
+static void pbm_register_devices(void)
+{
+    sysbus_register_dev("pbm", sizeof(APBState), pci_pbm_init_device);
+    pci_qdev_register(&pbm_pci_host_info);
 }
+
+device_init(pbm_register_devices)
diff --git a/hw/pci.c b/hw/pci.c
index 3b5a947..b0a2d79 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -145,11 +145,13 @@ PCIBus *pci_register_bus(DeviceState *parent,
const char *name,
     return bus;
 }

-static PCIBus *pci_register_secondary_bus(PCIDevice *dev,
pci_map_irq_fn map_irq)
+static PCIBus *pci_register_secondary_bus(PCIDevice *dev,
+                                          pci_map_irq_fn map_irq,
+                                          const char *name)
 {
     PCIBus *bus;

-    bus = qemu_mallocz(sizeof(PCIBus));
+    bus = FROM_QBUS(PCIBus, qbus_create(&pci_bus_info, &dev->qdev, name));
     bus->map_irq = map_irq;
     bus->parent_dev = dev;
     bus->next = dev->bus->next;
@@ -891,7 +893,7 @@ PCIBus *pci_bridge_init(PCIBus *bus, int devfn,
uint16_t vid, uint16_t did,
         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);
+    s->bus = pci_register_secondary_bus(&s->dev, map_irq, name);
     return s->bus;
 }

-- 
1.6.2.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]