qemu/hw/pci-host/sh_pci.c
<<
>>
Prefs
   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
  37OBJECT_DECLARE_SIMPLE_TYPE(SHPCIState, SH_PCI_HOST_BRIDGE)
  38
  39struct 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
  52static 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
  77static 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
  97static 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
 107static int sh_pci_map_irq(PCIDevice *d, int irq_num)
 108{
 109    return PCI_SLOT(d->devfn);
 110}
 111
 112static 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
 119static 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
 148static 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
 155static 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
 170static 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
 181static 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
 188static 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
 195static 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
 201type_init(sh_pci_register_types)
 202