diff --git a/hw/r2d.c b/hw/r2d.c index 90d1af2b1a..a0f8c1f201 100644 --- a/hw/r2d.c +++ b/hw/r2d.c @@ -23,13 +23,13 @@ * THE SOFTWARE. */ +#include "sysbus.h" #include "hw.h" #include "sh.h" #include "devices.h" #include "sysemu.h" #include "boards.h" #include "pci.h" -#include "sh_pci.h" #include "net.h" #include "sh7750_regs.h" #include "ide.h" @@ -195,19 +195,6 @@ static qemu_irq *r2d_fpga_init(target_phys_addr_t base, qemu_irq irl) return qemu_allocate_irqs(r2d_fpga_irq_set, s, NR_IRQS); } -static void r2d_pci_set_irq(void *opaque, int n, int l) -{ - qemu_irq *p = opaque; - - qemu_set_irq(p[n], l); -} - -static int r2d_pci_map_irq(PCIDevice *d, int irq_num) -{ - const int intx[] = { PCI_INTA, PCI_INTB, PCI_INTC, PCI_INTD }; - return intx[d->devfn >> 3]; -} - typedef struct ResetData { CPUState *env; uint32_t vector; @@ -268,7 +255,8 @@ static void r2d_init(ram_addr_t ram_size, /* Register peripherals */ s = sh7750_init(env); irq = r2d_fpga_init(0x04000000, sh7750_irl(s)); - sh_pci_register_bus(r2d_pci_set_irq, r2d_pci_map_irq, irq, 0, 4); + sysbus_create_varargs("sh_pci", 0x1e200000, irq[PCI_INTA], irq[PCI_INTB], + irq[PCI_INTC], irq[PCI_INTD], NULL); sm501_init(0x10000000, SM501_VRAM_SIZE, irq[SM501], serial_hds[2]); diff --git a/hw/sh_pci.c b/hw/sh_pci.c index 072078be51..e99d8dbfb5 100644 --- a/hw/sh_pci.c +++ b/hw/sh_pci.c @@ -21,24 +21,26 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "hw.h" +#include "sysbus.h" #include "sh.h" #include "pci.h" #include "pci_host.h" -#include "sh_pci.h" #include "bswap.h" -typedef struct { +typedef struct SHPCIState { + SysBusDevice busdev; PCIBus *bus; PCIDevice *dev; + qemu_irq irq[4]; + int memconfig; uint32_t par; uint32_t mbr; uint32_t iobr; -} SHPCIC; +} SHPCIState; static void sh_pci_reg_write (void *p, target_phys_addr_t addr, uint32_t val) { - SHPCIC *pcic = p; + SHPCIState *pcic = p; switch(addr) { case 0 ... 0xfc: cpu_to_le32w((uint32_t*)(pcic->dev->config + addr), val); @@ -65,7 +67,7 @@ static void sh_pci_reg_write (void *p, target_phys_addr_t addr, uint32_t val) static uint32_t sh_pci_reg_read (void *p, target_phys_addr_t addr) { - SHPCIC *pcic = p; + SHPCIState *pcic = p; switch(addr) { case 0 ... 0xfc: return le32_to_cpup((uint32_t*)(pcic->dev->config + addr)); @@ -91,32 +93,69 @@ static MemOp sh_pci_reg = { { NULL, NULL, sh_pci_reg_write }, }; -PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, - void *opaque, int devfn_min, int nirq) +static int sh_pci_map_irq(PCIDevice *d, int irq_num) { - SHPCIC *p; - int reg; - - p = qemu_mallocz(sizeof(SHPCIC)); - p->bus = pci_register_bus(NULL, "pci", - set_irq, map_irq, opaque, devfn_min, nirq); - - p->dev = pci_register_device(p->bus, "SH PCIC", sizeof(PCIDevice), - -1, NULL, NULL); - reg = cpu_register_io_memory(sh_pci_reg.r, sh_pci_reg.w, p, - DEVICE_NATIVE_ENDIAN); - cpu_register_physical_memory(0x1e200000, 0x224, reg); - cpu_register_physical_memory(0xfe200000, 0x224, reg); - - p->iobr = 0xfe240000; - isa_mmio_init(p->iobr, 0x40000); - - pci_config_set_vendor_id(p->dev->config, PCI_VENDOR_ID_HITACHI); - pci_config_set_device_id(p->dev->config, PCI_DEVICE_ID_HITACHI_SH7751R); - p->dev->config[0x04] = 0x80; - p->dev->config[0x05] = 0x00; - p->dev->config[0x06] = 0x90; - p->dev->config[0x07] = 0x02; - - return p->bus; + return (d->devfn >> 3); } + +static void sh_pci_set_irq(void *opaque, int irq_num, int level) +{ + qemu_irq *pic = opaque; + + qemu_set_irq(pic[irq_num], level); +} + +static void sh_pci_map(SysBusDevice *dev, target_phys_addr_t base) +{ + SHPCIState *s = FROM_SYSBUS(SHPCIState, dev); + + cpu_register_physical_memory(P4ADDR(base), 0x224, s->memconfig); + cpu_register_physical_memory(A7ADDR(base), 0x224, s->memconfig); + + s->iobr = 0xfe240000; + isa_mmio_init(s->iobr, 0x40000); +} + +static int sh_pci_init_device(SysBusDevice *dev) +{ + SHPCIState *s; + int i; + + s = FROM_SYSBUS(SHPCIState, dev); + for (i = 0; i < 4; i++) { + sysbus_init_irq(dev, &s->irq[i]); + } + s->bus = pci_register_bus(&s->busdev.qdev, "pci", + sh_pci_set_irq, sh_pci_map_irq, + s->irq, PCI_DEVFN(0, 0), 4); + s->memconfig = cpu_register_io_memory(sh_pci_reg.r, sh_pci_reg.w, + s, DEVICE_NATIVE_ENDIAN); + sysbus_init_mmio_cb(dev, 0x224, sh_pci_map); + s->dev = pci_create_simple(s->bus, PCI_DEVFN(0, 0), "sh_pci_host"); + return 0; +} + +static int sh_pci_host_init(PCIDevice *d) +{ + pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_HITACHI); + pci_config_set_device_id(d->config, PCI_DEVICE_ID_HITACHI_SH7751R); + pci_set_word(d->config + PCI_COMMAND, PCI_COMMAND_WAIT); + pci_set_word(d->config + PCI_STATUS, PCI_STATUS_CAP_LIST | + PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM); + return 0; +} + +static PCIDeviceInfo sh_pci_host_info = { + .qdev.name = "sh_pci_host", + .qdev.size = sizeof(PCIDevice), + .init = sh_pci_host_init, +}; + +static void sh_pci_register_devices(void) +{ + sysbus_register_dev("sh_pci", sizeof(SHPCIState), + sh_pci_init_device); + pci_qdev_register(&sh_pci_host_info); +} + +device_init(sh_pci_register_devices) diff --git a/hw/sh_pci.h b/hw/sh_pci.h deleted file mode 100644 index b1a5ec37c3..0000000000 --- a/hw/sh_pci.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef QEMU_SH_PCI_H -#define QEMU_SH_PCI_H - -#include "qemu-common.h" - -PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, - void *pic, int devfn_min, int nirq); - -#endif