/*
 * SuperH on-chip PCIC emulation.
 *
 * Copyright (c) 2008 Takashi YOSHII
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "sysbus.h"
#include "sh.h"
#include "pci.h"
#include "pci_host.h"
#include "bswap.h"

typedef struct SHPCIState {
    SysBusDevice busdev;
    PCIBus *bus;
    PCIDevice *dev;
    qemu_irq irq[4];
    int memconfig;
    uint32_t par;
    uint32_t mbr;
    uint32_t iobr;
} SHPCIState;

static void sh_pci_reg_write (void *p, target_phys_addr_t addr, uint32_t val)
{
    SHPCIState *pcic = p;
    switch(addr) {
    case 0 ... 0xfc:
        cpu_to_le32w((uint32_t*)(pcic->dev->config + addr), val);
        break;
    case 0x1c0:
        pcic->par = val;
        break;
    case 0x1c4:
        pcic->mbr = val & 0xff000001;
        break;
    case 0x1c8:
        if ((val & 0xfffc0000) != (pcic->iobr & 0xfffc0000)) {
            cpu_register_physical_memory(pcic->iobr & 0xfffc0000, 0x40000,
                                         IO_MEM_UNASSIGNED);
            pcic->iobr = val & 0xfffc0001;
            isa_mmio_init(pcic->iobr & 0xfffc0000, 0x40000);
        }
        break;
    case 0x220:
        pci_data_write(pcic->bus, pcic->par, val, 4);
        break;
    }
}

static uint32_t sh_pci_reg_read (void *p, target_phys_addr_t addr)
{
    SHPCIState *pcic = p;
    switch(addr) {
    case 0 ... 0xfc:
        return le32_to_cpup((uint32_t*)(pcic->dev->config + addr));
    case 0x1c0:
        return pcic->par;
    case 0x1c4:
        return pcic->mbr;
    case 0x1c8:
        return pcic->iobr;
    case 0x220:
        return pci_data_read(pcic->bus, pcic->par, 4);
    }
    return 0;
}

typedef struct {
    CPUReadMemoryFunc * const r[3];
    CPUWriteMemoryFunc * const w[3];
} MemOp;

static MemOp sh_pci_reg = {
    { NULL, NULL, sh_pci_reg_read },
    { NULL, NULL, sh_pci_reg_write },
};

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 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)
