qemu/hw/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#include "hw.h"
  25#include "sh.h"
  26#include "pci.h"
  27#include "pci_host.h"
  28#include "sh_pci.h"
  29#include "bswap.h"
  30
  31typedef struct {
  32    PCIBus *bus;
  33    PCIDevice *dev;
  34    uint32_t par;
  35    uint32_t mbr;
  36    uint32_t iobr;
  37} SHPCIC;
  38
  39static void sh_pci_reg_write (void *p, target_phys_addr_t addr, uint32_t val)
  40{
  41    SHPCIC *pcic = p;
  42    switch(addr) {
  43    case 0 ... 0xfc:
  44        cpu_to_le32w((uint32_t*)(pcic->dev->config + addr), val);
  45        break;
  46    case 0x1c0:
  47        pcic->par = val;
  48        break;
  49    case 0x1c4:
  50        pcic->mbr = val;
  51        break;
  52    case 0x1c8:
  53        pcic->iobr = val;
  54        break;
  55    case 0x220:
  56        pci_data_write(pcic->bus, pcic->par, val, 4);
  57        break;
  58    }
  59}
  60
  61static uint32_t sh_pci_reg_read (void *p, target_phys_addr_t addr)
  62{
  63    SHPCIC *pcic = p;
  64    switch(addr) {
  65    case 0 ... 0xfc:
  66        return le32_to_cpup((uint32_t*)(pcic->dev->config + addr));
  67    case 0x1c0:
  68        return pcic->par;
  69    case 0x220:
  70        return pci_data_read(pcic->bus, pcic->par, 4);
  71    }
  72    return 0;
  73}
  74
  75static void sh_pci_data_write (SHPCIC *pcic, target_phys_addr_t addr,
  76                               uint32_t val, int size)
  77{
  78    pci_data_write(pcic->bus, addr + pcic->mbr, val, size);
  79}
  80
  81static uint32_t sh_pci_mem_read (SHPCIC *pcic, target_phys_addr_t addr,
  82                                 int size)
  83{
  84    return pci_data_read(pcic->bus, addr + pcic->mbr, size);
  85}
  86
  87static void sh_pci_writeb (void *p, target_phys_addr_t addr, uint32_t val)
  88{
  89    sh_pci_data_write(p, addr, val, 1);
  90}
  91
  92static void sh_pci_writew (void *p, target_phys_addr_t addr, uint32_t val)
  93{
  94    sh_pci_data_write(p, addr, val, 2);
  95}
  96
  97static void sh_pci_writel (void *p, target_phys_addr_t addr, uint32_t val)
  98{
  99    sh_pci_data_write(p, addr, val, 4);
 100}
 101
 102static uint32_t sh_pci_readb (void *p, target_phys_addr_t addr)
 103{
 104    return sh_pci_mem_read(p, addr, 1);
 105}
 106
 107static uint32_t sh_pci_readw (void *p, target_phys_addr_t addr)
 108{
 109    return sh_pci_mem_read(p, addr, 2);
 110}
 111
 112static uint32_t sh_pci_readl (void *p, target_phys_addr_t addr)
 113{
 114    return sh_pci_mem_read(p, addr, 4);
 115}
 116
 117static int sh_pci_addr2port(SHPCIC *pcic, target_phys_addr_t addr)
 118{
 119    return addr + pcic->iobr;
 120}
 121
 122static void sh_pci_outb (void *p, target_phys_addr_t addr, uint32_t val)
 123{
 124    cpu_outb(sh_pci_addr2port(p, addr), val);
 125}
 126
 127static void sh_pci_outw (void *p, target_phys_addr_t addr, uint32_t val)
 128{
 129    cpu_outw(sh_pci_addr2port(p, addr), val);
 130}
 131
 132static void sh_pci_outl (void *p, target_phys_addr_t addr, uint32_t val)
 133{
 134    cpu_outl(sh_pci_addr2port(p, addr), val);
 135}
 136
 137static uint32_t sh_pci_inb (void *p, target_phys_addr_t addr)
 138{
 139    return cpu_inb(sh_pci_addr2port(p, addr));
 140}
 141
 142static uint32_t sh_pci_inw (void *p, target_phys_addr_t addr)
 143{
 144    return cpu_inw(sh_pci_addr2port(p, addr));
 145}
 146
 147static uint32_t sh_pci_inl (void *p, target_phys_addr_t addr)
 148{
 149    return cpu_inl(sh_pci_addr2port(p, addr));
 150}
 151
 152typedef struct {
 153    CPUReadMemoryFunc * const r[3];
 154    CPUWriteMemoryFunc * const w[3];
 155} MemOp;
 156
 157static MemOp sh_pci_reg = {
 158    { NULL, NULL, sh_pci_reg_read },
 159    { NULL, NULL, sh_pci_reg_write },
 160};
 161
 162static MemOp sh_pci_mem = {
 163    { sh_pci_readb, sh_pci_readw, sh_pci_readl },
 164    { sh_pci_writeb, sh_pci_writew, sh_pci_writel },
 165};
 166
 167static MemOp sh_pci_iop = {
 168    { sh_pci_inb, sh_pci_inw, sh_pci_inl },
 169    { sh_pci_outb, sh_pci_outw, sh_pci_outl },
 170};
 171
 172PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
 173                            void *opaque, int devfn_min, int nirq)
 174{
 175    SHPCIC *p;
 176    int mem, reg, iop;
 177
 178    p = qemu_mallocz(sizeof(SHPCIC));
 179    p->bus = pci_register_bus(NULL, "pci",
 180                              set_irq, map_irq, opaque, devfn_min, nirq);
 181
 182    p->dev = pci_register_device(p->bus, "SH PCIC", sizeof(PCIDevice),
 183                                 -1, NULL, NULL);
 184    reg = cpu_register_io_memory(sh_pci_reg.r, sh_pci_reg.w, p);
 185    iop = cpu_register_io_memory(sh_pci_iop.r, sh_pci_iop.w, p);
 186    mem = cpu_register_io_memory(sh_pci_mem.r, sh_pci_mem.w, p);
 187    cpu_register_physical_memory(0x1e200000, 0x224, reg);
 188    cpu_register_physical_memory(0x1e240000, 0x40000, iop);
 189    cpu_register_physical_memory(0x1d000000, 0x1000000, mem);
 190    cpu_register_physical_memory(0xfe200000, 0x224, reg);
 191    cpu_register_physical_memory(0xfe240000, 0x40000, iop);
 192    cpu_register_physical_memory(0xfd000000, 0x1000000, mem);
 193
 194    pci_config_set_vendor_id(p->dev->config, PCI_VENDOR_ID_HITACHI);
 195    pci_config_set_device_id(p->dev->config, PCI_DEVICE_ID_HITACHI_SH7751R);
 196    p->dev->config[0x04] = 0x80;
 197    p->dev->config[0x05] = 0x00;
 198    p->dev->config[0x06] = 0x90;
 199    p->dev->config[0x07] = 0x02;
 200
 201    return p->bus;
 202}
 203