X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/fef395782d76fa497bfc89cea741173706669b2e..511b13e2c9b426b3c56060909693de5097f0b496:/hw/sh_pci.c diff --git a/hw/sh_pci.c b/hw/sh_pci.c index 072078be51..0cfac46f7f 100644 --- a/hw/sh_pci.c +++ b/hw/sh_pci.c @@ -21,24 +21,30 @@ * 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" +#include "exec-memory.h" -typedef struct { +typedef struct SHPCIState { + SysBusDevice busdev; PCIBus *bus; PCIDevice *dev; + qemu_irq irq[4]; + MemoryRegion memconfig_p4; + MemoryRegion memconfig_a7; + MemoryRegion isa; 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) +static void sh_pci_reg_write (void *p, target_phys_addr_t addr, uint64_t val, + unsigned size) { - SHPCIC *pcic = p; + SHPCIState *pcic = p; switch(addr) { case 0 ... 0xfc: cpu_to_le32w((uint32_t*)(pcic->dev->config + addr), val); @@ -51,10 +57,10 @@ static void sh_pci_reg_write (void *p, target_phys_addr_t addr, uint32_t val) break; case 0x1c8: if ((val & 0xfffc0000) != (pcic->iobr & 0xfffc0000)) { - cpu_register_physical_memory(pcic->iobr & 0xfffc0000, 0x40000, - IO_MEM_UNASSIGNED); + memory_region_del_subregion(get_system_memory(), &pcic->isa); pcic->iobr = val & 0xfffc0001; - isa_mmio_init(pcic->iobr & 0xfffc0000, 0x40000); + memory_region_add_subregion(get_system_memory(), + pcic->iobr & 0xfffc0000, &pcic->isa); } break; case 0x220: @@ -63,9 +69,10 @@ 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) +static uint64_t sh_pci_reg_read (void *p, target_phys_addr_t addr, + unsigned size) { - SHPCIC *pcic = p; + SHPCIState *pcic = p; switch(addr) { case 0 ... 0xfc: return le32_to_cpup((uint32_t*)(pcic->dev->config + addr)); @@ -81,42 +88,99 @@ static uint32_t sh_pci_reg_read (void *p, target_phys_addr_t addr) return 0; } -typedef struct { - CPUReadMemoryFunc * const r[3]; - CPUWriteMemoryFunc * const w[3]; -} MemOp; +static const MemoryRegionOps sh_pci_reg_ops = { + .read = sh_pci_reg_read, + .write = sh_pci_reg_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + +static int sh_pci_map_irq(PCIDevice *d, int irq_num) +{ + 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 int sh_pci_device_init(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, + get_system_memory(), + get_system_io(), + PCI_DEVFN(0, 0), 4); + memory_region_init_io(&s->memconfig_p4, &sh_pci_reg_ops, s, + "sh_pci", 0x224); + memory_region_init_alias(&s->memconfig_a7, "sh_pci.2", &s->memconfig_p4, + 0, 0x224); + isa_mmio_setup(&s->isa, 0x40000); + sysbus_init_mmio(dev, &s->memconfig_p4); + sysbus_init_mmio(dev, &s->memconfig_a7); + s->iobr = 0xfe240000; + memory_region_add_subregion(get_system_memory(), s->iobr, &s->isa); + + s->dev = pci_create_simple(s->bus, PCI_DEVFN(0, 0), "sh_pci_host"); + return 0; +} -static MemOp sh_pci_reg = { - { NULL, NULL, sh_pci_reg_read }, - { NULL, NULL, sh_pci_reg_write }, +static int sh_pci_host_init(PCIDevice *d) +{ + 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 void sh_pci_host_class_init(ObjectClass *klass, void *data) +{ + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->init = sh_pci_host_init; + k->vendor_id = PCI_VENDOR_ID_HITACHI; + k->device_id = PCI_DEVICE_ID_HITACHI_SH7751R; +} + +static TypeInfo sh_pci_host_info = { + .name = "sh_pci_host", + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(PCIDevice), + .class_init = sh_pci_host_class_init, }; -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 void sh_pci_device_class_init(ObjectClass *klass, void *data) { - 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; + SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); + + sdc->init = sh_pci_device_init; } + +static TypeInfo sh_pci_device_info = { + .name = "sh_pci", + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(SHPCIState), + .class_init = sh_pci_device_class_init, +}; + +static void sh_pci_register_types(void) +{ + type_register_static(&sh_pci_device_info); + type_register_static(&sh_pci_host_info); +} + +type_init(sh_pci_register_types)