/*
 * QEMU Intel i82378 emulation (PCI to ISA bridge)
 *
 * Copyright (c) 2010-2011 Hervé Poussineau
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */

#include "pci.h"
#include "pc.h"
#include "i8254.h"
#include "pcspk.h"

//#define DEBUG_I82378

#ifdef DEBUG_I82378
#define DPRINTF(fmt, ...) \
do { fprintf(stderr, "i82378: " fmt , ## __VA_ARGS__); } while (0)
#else
#define DPRINTF(fmt, ...) \
do {} while (0)
#endif

#define BADF(fmt, ...) \
do { fprintf(stderr, "i82378 ERROR: " fmt , ## __VA_ARGS__); } while (0)

typedef struct I82378State {
    qemu_irq out[2];
    qemu_irq *i8259;
    MemoryRegion io;
    MemoryRegion mem;
} I82378State;

typedef struct PCIi82378State {
    PCIDevice pci_dev;
    uint32_t isa_io_base;
    uint32_t isa_mem_base;
    I82378State state;
} PCIi82378State;

static const VMStateDescription vmstate_pci_i82378 = {
    .name = "pci-i82378",
    .version_id = 0,
    .minimum_version_id = 0,
    .fields = (VMStateField[]) {
        VMSTATE_PCI_DEVICE(pci_dev, PCIi82378State),
        VMSTATE_END_OF_LIST()
    },
};

static void i82378_io_write(void *opaque, target_phys_addr_t addr,
                            uint64_t value, unsigned int size)
{
    switch (size) {
    case 1:
        DPRINTF("%s: " TARGET_FMT_plx "=%02" PRIx64 "\n", __func__,
                addr, value);
        cpu_outb(addr, value);
        break;
    case 2:
        DPRINTF("%s: " TARGET_FMT_plx "=%04" PRIx64 "\n", __func__,
                addr, value);
        cpu_outw(addr, value);
        break;
    case 4:
        DPRINTF("%s: " TARGET_FMT_plx "=%08" PRIx64 "\n", __func__,
                addr, value);
        cpu_outl(addr, value);
        break;
    default:
        abort();
    }
}

static uint64_t i82378_io_read(void *opaque, target_phys_addr_t addr,
                               unsigned int size)
{
    DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr);
    switch (size) {
    case 1:
        return cpu_inb(addr);
    case 2:
        return cpu_inw(addr);
    case 4:
        return cpu_inl(addr);
    default:
        abort();
    }
}

static const MemoryRegionOps i82378_io_ops = {
    .read = i82378_io_read,
    .write = i82378_io_write,
    .endianness = DEVICE_LITTLE_ENDIAN,
};

static void i82378_mem_write(void *opaque, target_phys_addr_t addr,
                             uint64_t value, unsigned int size)
{
    switch (size) {
    case 1:
        DPRINTF("%s: " TARGET_FMT_plx "=%02" PRIx64 "\n", __func__,
                addr, value);
        cpu_outb(addr, value);
        break;
    case 2:
        DPRINTF("%s: " TARGET_FMT_plx "=%04" PRIx64 "\n", __func__,
                addr, value);
        cpu_outw(addr, value);
        break;
    case 4:
        DPRINTF("%s: " TARGET_FMT_plx "=%08" PRIx64 "\n", __func__,
                addr, value);
        cpu_outl(addr, value);
        break;
    default:
        abort();
    }
}

static uint64_t i82378_mem_read(void *opaque, target_phys_addr_t addr,
                                unsigned int size)
{
    DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr);
    switch (size) {
    case 1:
        return cpu_inb(addr);
    case 2:
        return cpu_inw(addr);
    case 4:
        return cpu_inl(addr);
    default:
        abort();
    }
}

static const MemoryRegionOps i82378_mem_ops = {
    .read = i82378_mem_read,
    .write = i82378_mem_write,
    .endianness = DEVICE_LITTLE_ENDIAN,
};

static void i82378_request_out0_irq(void *opaque, int irq, int level)
{
    I82378State *s = opaque;
    qemu_set_irq(s->out[0], level);
}

static void i82378_request_pic_irq(void *opaque, int irq, int level)
{
    DeviceState *dev = opaque;
    PCIDevice *pci = DO_UPCAST(PCIDevice, qdev, dev);
    PCIi82378State *s = DO_UPCAST(PCIi82378State, pci_dev, pci);

    qemu_set_irq(s->state.i8259[irq], level);
}

static void i82378_init(DeviceState *dev, I82378State *s)
{
    ISABus *isabus = DO_UPCAST(ISABus, qbus, qdev_get_child_bus(dev, "isa.0"));
    ISADevice *pit;
    ISADevice *isa;
    qemu_irq *out0_irq;

    /* This device has:
       2 82C59 (irq)
       1 82C54 (pit)
       2 82C37 (dma)
       NMI
       Utility Bus Support Registers

       All devices accept byte access only, except timer
     */

    qdev_init_gpio_out(dev, s->out, 2);
    qdev_init_gpio_in(dev, i82378_request_pic_irq, 16);

    /* Workaround the fact that i8259 is not qdev'ified... */
    out0_irq = qemu_allocate_irqs(i82378_request_out0_irq, s, 1);

    /* 2 82C59 (irq) */
    s->i8259 = i8259_init(isabus, *out0_irq);
    isa_bus_irqs(isabus, s->i8259);

    /* 1 82C54 (pit) */
    pit = pit_init(isabus, 0x40, 0, NULL);

    /* speaker */
    pcspk_init(isabus, pit);

    /* 2 82C37 (dma) */
    isa = isa_create_simple(isabus, "i82374");
    qdev_connect_gpio_out(&isa->qdev, 0, s->out[1]);

    /* timer */
    isa_create_simple(isabus, "mc146818rtc");
}

static int pci_i82378_init(PCIDevice *dev)
{
    PCIi82378State *pci = DO_UPCAST(PCIi82378State, pci_dev, dev);
    I82378State *s = &pci->state;
    uint8_t *pci_conf;

    pci_conf = dev->config;
    pci_set_word(pci_conf + PCI_COMMAND,
                 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
    pci_set_word(pci_conf + PCI_STATUS,
                 PCI_STATUS_DEVSEL_MEDIUM);

    pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin 0 */

    memory_region_init_io(&s->io, &i82378_io_ops, s, "i82378-io", 0x00010000);
    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io);

    memory_region_init_io(&s->mem, &i82378_mem_ops, s, "i82378-mem", 0x01000000);
    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem);

    /* Make I/O address read only */
    pci_set_word(dev->wmask + PCI_COMMAND, PCI_COMMAND_SPECIAL);
    pci_set_long(dev->wmask + PCI_BASE_ADDRESS_0, 0);
    pci_set_long(pci_conf + PCI_BASE_ADDRESS_0, pci->isa_io_base);

    isa_mem_base = pci->isa_mem_base;
    isa_bus_new(&dev->qdev, pci_address_space_io(dev));

    i82378_init(&dev->qdev, s);

    return 0;
}

static Property i82378_properties[] = {
    DEFINE_PROP_HEX32("iobase", PCIi82378State, isa_io_base, 0x80000000),
    DEFINE_PROP_HEX32("membase", PCIi82378State, isa_mem_base, 0xc0000000),
    DEFINE_PROP_END_OF_LIST()
};

static void pci_i82378_class_init(ObjectClass *klass, void *data)
{
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
    DeviceClass *dc = DEVICE_CLASS(klass);

    k->init = pci_i82378_init;
    k->vendor_id = PCI_VENDOR_ID_INTEL;
    k->device_id = PCI_DEVICE_ID_INTEL_82378;
    k->revision = 0x03;
    k->class_id = PCI_CLASS_BRIDGE_ISA;
    k->subsystem_vendor_id = 0x0;
    k->subsystem_id = 0x0;
    dc->vmsd = &vmstate_pci_i82378;
    dc->props = i82378_properties;
}

static TypeInfo pci_i82378_info = {
    .name = "i82378",
    .parent = TYPE_PCI_DEVICE,
    .instance_size = sizeof(PCIi82378State),
    .class_init = pci_i82378_class_init,
};

static void i82378_register_types(void)
{
    type_register_static(&pci_i82378_info);
}

type_init(i82378_register_types)
