qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

sh_pci.c (6088B)


      1 /*
      2  * SuperH on-chip PCIC emulation.
      3  *
      4  * Copyright (c) 2008 Takashi YOSHII
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a copy
      7  * of this software and associated documentation files (the "Software"), to deal
      8  * in the Software without restriction, including without limitation the rights
      9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10  * copies of the Software, and to permit persons to whom the Software is
     11  * furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22  * THE SOFTWARE.
     23  */
     24 
     25 #include "qemu/osdep.h"
     26 #include "hw/sysbus.h"
     27 #include "hw/sh4/sh.h"
     28 #include "hw/irq.h"
     29 #include "hw/pci/pci.h"
     30 #include "hw/pci/pci_host.h"
     31 #include "qemu/bswap.h"
     32 #include "qemu/module.h"
     33 #include "qom/object.h"
     34 
     35 #define TYPE_SH_PCI_HOST_BRIDGE "sh_pci"
     36 
     37 OBJECT_DECLARE_SIMPLE_TYPE(SHPCIState, SH_PCI_HOST_BRIDGE)
     38 
     39 struct SHPCIState {
     40     PCIHostState parent_obj;
     41 
     42     PCIDevice *dev;
     43     qemu_irq irq[4];
     44     MemoryRegion memconfig_p4;
     45     MemoryRegion memconfig_a7;
     46     MemoryRegion isa;
     47     uint32_t par;
     48     uint32_t mbr;
     49     uint32_t iobr;
     50 };
     51 
     52 static void sh_pci_reg_write(void *p, hwaddr addr, uint64_t val, unsigned size)
     53 {
     54     SHPCIState *pcic = p;
     55     PCIHostState *phb = PCI_HOST_BRIDGE(pcic);
     56 
     57     switch (addr) {
     58     case 0 ... 0xfc:
     59         stl_le_p(pcic->dev->config + addr, val);
     60         break;
     61     case 0x1c0:
     62         pcic->par = val;
     63         break;
     64     case 0x1c4:
     65         pcic->mbr = val & 0xff000001;
     66         break;
     67     case 0x1c8:
     68         pcic->iobr = val & 0xfffc0001;
     69         memory_region_set_alias_offset(&pcic->isa, val & 0xfffc0000);
     70         break;
     71     case 0x220:
     72         pci_data_write(phb->bus, pcic->par, val, 4);
     73         break;
     74     }
     75 }
     76 
     77 static uint64_t sh_pci_reg_read(void *p, hwaddr addr, unsigned size)
     78 {
     79     SHPCIState *pcic = p;
     80     PCIHostState *phb = PCI_HOST_BRIDGE(pcic);
     81 
     82     switch (addr) {
     83     case 0 ... 0xfc:
     84         return ldl_le_p(pcic->dev->config + addr);
     85     case 0x1c0:
     86         return pcic->par;
     87     case 0x1c4:
     88         return pcic->mbr;
     89     case 0x1c8:
     90         return pcic->iobr;
     91     case 0x220:
     92         return pci_data_read(phb->bus, pcic->par, 4);
     93     }
     94     return 0;
     95 }
     96 
     97 static const MemoryRegionOps sh_pci_reg_ops = {
     98     .read = sh_pci_reg_read,
     99     .write = sh_pci_reg_write,
    100     .endianness = DEVICE_NATIVE_ENDIAN,
    101     .valid = {
    102         .min_access_size = 4,
    103         .max_access_size = 4,
    104     },
    105 };
    106 
    107 static int sh_pci_map_irq(PCIDevice *d, int irq_num)
    108 {
    109     return PCI_SLOT(d->devfn);
    110 }
    111 
    112 static void sh_pci_set_irq(void *opaque, int irq_num, int level)
    113 {
    114     qemu_irq *pic = opaque;
    115 
    116     qemu_set_irq(pic[irq_num], level);
    117 }
    118 
    119 static void sh_pci_device_realize(DeviceState *dev, Error **errp)
    120 {
    121     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
    122     SHPCIState *s = SH_PCI_HOST_BRIDGE(dev);
    123     PCIHostState *phb = PCI_HOST_BRIDGE(s);
    124     int i;
    125 
    126     for (i = 0; i < 4; i++) {
    127         sysbus_init_irq(sbd, &s->irq[i]);
    128     }
    129     phb->bus = pci_register_root_bus(dev, "pci",
    130                                      sh_pci_set_irq, sh_pci_map_irq,
    131                                      s->irq,
    132                                      get_system_memory(),
    133                                      get_system_io(),
    134                                      PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS);
    135     memory_region_init_io(&s->memconfig_p4, OBJECT(s), &sh_pci_reg_ops, s,
    136                           "sh_pci", 0x224);
    137     memory_region_init_alias(&s->memconfig_a7, OBJECT(s), "sh_pci.2",
    138                              &s->memconfig_p4, 0, 0x224);
    139     memory_region_init_alias(&s->isa, OBJECT(s), "sh_pci.isa",
    140                              get_system_io(), 0, 0x40000);
    141     sysbus_init_mmio(sbd, &s->memconfig_p4);
    142     sysbus_init_mmio(sbd, &s->memconfig_a7);
    143     memory_region_add_subregion(get_system_memory(), 0xfe240000, &s->isa);
    144 
    145     s->dev = pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "sh_pci_host");
    146 }
    147 
    148 static void sh_pci_host_realize(PCIDevice *d, Error **errp)
    149 {
    150     pci_set_word(d->config + PCI_COMMAND, PCI_COMMAND_WAIT);
    151     pci_set_word(d->config + PCI_STATUS, PCI_STATUS_CAP_LIST |
    152                  PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM);
    153 }
    154 
    155 static void sh_pci_host_class_init(ObjectClass *klass, void *data)
    156 {
    157     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
    158     DeviceClass *dc = DEVICE_CLASS(klass);
    159 
    160     k->realize = sh_pci_host_realize;
    161     k->vendor_id = PCI_VENDOR_ID_HITACHI;
    162     k->device_id = PCI_DEVICE_ID_HITACHI_SH7751R;
    163     /*
    164      * PCI-facing part of the host bridge, not usable without the
    165      * host-facing part, which can't be device_add'ed, yet.
    166      */
    167     dc->user_creatable = false;
    168 }
    169 
    170 static const TypeInfo sh_pci_host_info = {
    171     .name          = "sh_pci_host",
    172     .parent        = TYPE_PCI_DEVICE,
    173     .instance_size = sizeof(PCIDevice),
    174     .class_init    = sh_pci_host_class_init,
    175     .interfaces = (InterfaceInfo[]) {
    176         { INTERFACE_CONVENTIONAL_PCI_DEVICE },
    177         { },
    178     },
    179 };
    180 
    181 static void sh_pci_device_class_init(ObjectClass *klass, void *data)
    182 {
    183     DeviceClass *dc = DEVICE_CLASS(klass);
    184 
    185     dc->realize = sh_pci_device_realize;
    186 }
    187 
    188 static const TypeInfo sh_pci_device_info = {
    189     .name          = TYPE_SH_PCI_HOST_BRIDGE,
    190     .parent        = TYPE_PCI_HOST_BRIDGE,
    191     .instance_size = sizeof(SHPCIState),
    192     .class_init    = sh_pci_device_class_init,
    193 };
    194 
    195 static void sh_pci_register_types(void)
    196 {
    197     type_register_static(&sh_pci_device_info);
    198     type_register_static(&sh_pci_host_info);
    199 }
    200 
    201 type_init(sh_pci_register_types)