/*
 * QEMU ESP/NCR53C9x emulation
 *
 * Copyright (c) 2005-2006 Fabrice Bellard
 * Copyright (c) 2012 Herve Poussineau
 *
 * 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 "qemu/osdep.h"
#include "hw/pci/pci.h"
#include "hw/irq.h"
#include "hw/nvram/eeprom93xx.h"
#include "hw/scsi/esp.h"
#include "migration/vmstate.h"
#include "trace.h"
#include "qapi/error.h"
#include "qemu/log.h"
#include "qemu/module.h"
#include "qom/object.h"

#define TYPE_AM53C974_DEVICE "am53c974"

typedef struct PCIESPState PCIESPState;
DECLARE_INSTANCE_CHECKER(PCIESPState, PCI_ESP,
                         TYPE_AM53C974_DEVICE)

#define DMA_CMD   0x0
#define DMA_STC   0x1
#define DMA_SPA   0x2
#define DMA_WBC   0x3
#define DMA_WAC   0x4
#define DMA_STAT  0x5
#define DMA_SMDLA 0x6
#define DMA_WMAC  0x7

#define DMA_CMD_MASK   0x03
#define DMA_CMD_DIAG   0x04
#define DMA_CMD_MDL    0x10
#define DMA_CMD_INTE_P 0x20
#define DMA_CMD_INTE_D 0x40
#define DMA_CMD_DIR    0x80

#define DMA_STAT_PWDN    0x01
#define DMA_STAT_ERROR   0x02
#define DMA_STAT_ABORT   0x04
#define DMA_STAT_DONE    0x08
#define DMA_STAT_SCSIINT 0x10
#define DMA_STAT_BCMBLT  0x20

#define SBAC_STATUS (1 << 24)

struct PCIESPState {
    /*< private >*/
    PCIDevice parent_obj;
    /*< public >*/

    MemoryRegion io;
    uint32_t dma_regs[8];
    uint32_t sbac;
    ESPState esp;
};

static void esp_pci_handle_idle(PCIESPState *pci, uint32_t val)
{
    ESPState *s = ESP(&pci->esp);

    trace_esp_pci_dma_idle(val);
    esp_dma_enable(s, 0, 0);
}

static void esp_pci_handle_blast(PCIESPState *pci, uint32_t val)
{
    trace_esp_pci_dma_blast(val);
    qemu_log_mask(LOG_UNIMP, "am53c974: cmd BLAST not implemented\n");
}

static void esp_pci_handle_abort(PCIESPState *pci, uint32_t val)
{
    ESPState *s = ESP(&pci->esp);

    trace_esp_pci_dma_abort(val);
    if (s->current_req) {
        scsi_req_cancel(s->current_req);
    }
}

static void esp_pci_handle_start(PCIESPState *pci, uint32_t val)
{
    ESPState *s = ESP(&pci->esp);

    trace_esp_pci_dma_start(val);

    pci->dma_regs[DMA_WBC] = pci->dma_regs[DMA_STC];
    pci->dma_regs[DMA_WAC] = pci->dma_regs[DMA_SPA];
    pci->dma_regs[DMA_WMAC] = pci->dma_regs[DMA_SMDLA];

    pci->dma_regs[DMA_STAT] &= ~(DMA_STAT_BCMBLT | DMA_STAT_SCSIINT
                               | DMA_STAT_DONE | DMA_STAT_ABORT
                               | DMA_STAT_ERROR | DMA_STAT_PWDN);

    esp_dma_enable(s, 0, 1);
}

static void esp_pci_dma_write(PCIESPState *pci, uint32_t saddr, uint32_t val)
{
    trace_esp_pci_dma_write(saddr, pci->dma_regs[saddr], val);
    switch (saddr) {
    case DMA_CMD:
        pci->dma_regs[saddr] = val;
        switch (val & DMA_CMD_MASK) {
        case 0x0: /* IDLE */
            esp_pci_handle_idle(pci, val);
            break;
        case 0x1: /* BLAST */
            esp_pci_handle_blast(pci, val);
            break;
        case 0x2: /* ABORT */
            esp_pci_handle_abort(pci, val);
            break;
        case 0x3: /* START */
            esp_pci_handle_start(pci, val);
            break;
        default: /* can't happen */
            abort();
        }
        break;
    case DMA_STC:
    case DMA_SPA:
    case DMA_SMDLA:
        pci->dma_regs[saddr] = val;
        break;
    case DMA_STAT:
        if (pci->sbac & SBAC_STATUS) {
            /* clear some bits on write */
            uint32_t mask = DMA_STAT_ERROR | DMA_STAT_ABORT | DMA_STAT_DONE;
            pci->dma_regs[DMA_STAT] &= ~(val & mask);
        }
        break;
    default:
        trace_esp_pci_error_invalid_write_dma(val, saddr);
        return;
    }
}

static uint32_t esp_pci_dma_read(PCIESPState *pci, uint32_t saddr)
{
    ESPState *s = ESP(&pci->esp);
    uint32_t val;

    val = pci->dma_regs[saddr];
    if (saddr == DMA_STAT) {
        if (s->rregs[ESP_RSTAT] & STAT_INT) {
            val |= DMA_STAT_SCSIINT;
        }
        if (!(pci->sbac & SBAC_STATUS)) {
            pci->dma_regs[DMA_STAT] &= ~(DMA_STAT_ERROR | DMA_STAT_ABORT |
                                         DMA_STAT_DONE);
        }
    }

    trace_esp_pci_dma_read(saddr, val);
    return val;
}

static void esp_pci_io_write(void *opaque, hwaddr addr,
                             uint64_t val, unsigned int size)
{
    PCIESPState *pci = opaque;
    ESPState *s = ESP(&pci->esp);

    if (size < 4 || addr & 3) {
        /* need to upgrade request: we only support 4-bytes accesses */
        uint32_t current = 0, mask;
        int shift;

        if (addr < 0x40) {
            current = s->wregs[addr >> 2];
        } else if (addr < 0x60) {
            current = pci->dma_regs[(addr - 0x40) >> 2];
        } else if (addr < 0x74) {
            current = pci->sbac;
        }

        shift = (4 - size) * 8;
        mask = (~(uint32_t)0 << shift) >> shift;

        shift = ((4 - (addr & 3)) & 3) * 8;
        val <<= shift;
        val |= current & ~(mask << shift);
        addr &= ~3;
        size = 4;
    }
    g_assert(size >= 4);

    if (addr < 0x40) {
        /* SCSI core reg */
        esp_reg_write(s, addr >> 2, val);
    } else if (addr < 0x60) {
        /* PCI DMA CCB */
        esp_pci_dma_write(pci, (addr - 0x40) >> 2, val);
    } else if (addr == 0x70) {
        /* DMA SCSI Bus and control */
        trace_esp_pci_sbac_write(pci->sbac, val);
        pci->sbac = val;
    } else {
        trace_esp_pci_error_invalid_write((int)addr);
    }
}

static uint64_t esp_pci_io_read(void *opaque, hwaddr addr,
                                unsigned int size)
{
    PCIESPState *pci = opaque;
    ESPState *s = ESP(&pci->esp);
    uint32_t ret;

    if (addr < 0x40) {
        /* SCSI core reg */
        ret = esp_reg_read(s, addr >> 2);
    } else if (addr < 0x60) {
        /* PCI DMA CCB */
        ret = esp_pci_dma_read(pci, (addr - 0x40) >> 2);
    } else if (addr == 0x70) {
        /* DMA SCSI Bus and control */
        trace_esp_pci_sbac_read(pci->sbac);
        ret = pci->sbac;
    } else {
        /* Invalid region */
        trace_esp_pci_error_invalid_read((int)addr);
        ret = 0;
    }

    /* give only requested data */
    ret >>= (addr & 3) * 8;
    ret &= ~(~(uint64_t)0 << (8 * size));

    return ret;
}

static void esp_pci_dma_memory_rw(PCIESPState *pci, uint8_t *buf, int len,
                                  DMADirection dir)
{
    dma_addr_t addr;
    DMADirection expected_dir;

    if (pci->dma_regs[DMA_CMD] & DMA_CMD_DIR) {
        expected_dir = DMA_DIRECTION_FROM_DEVICE;
    } else {
        expected_dir = DMA_DIRECTION_TO_DEVICE;
    }

    if (dir != expected_dir) {
        trace_esp_pci_error_invalid_dma_direction();
        return;
    }

    if (pci->dma_regs[DMA_STAT] & DMA_CMD_MDL) {
        qemu_log_mask(LOG_UNIMP, "am53c974: MDL transfer not implemented\n");
    }

    addr = pci->dma_regs[DMA_SPA];
    if (pci->dma_regs[DMA_WBC] < len) {
        len = pci->dma_regs[DMA_WBC];
    }

    pci_dma_rw(PCI_DEVICE(pci), addr, buf, len, dir, MEMTXATTRS_UNSPECIFIED);

    /* update status registers */
    pci->dma_regs[DMA_WBC] -= len;
    pci->dma_regs[DMA_WAC] += len;
    if (pci->dma_regs[DMA_WBC] == 0) {
        pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE;
    }
}

static void esp_pci_dma_memory_read(void *opaque, uint8_t *buf, int len)
{
    PCIESPState *pci = opaque;
    esp_pci_dma_memory_rw(pci, buf, len, DMA_DIRECTION_TO_DEVICE);
}

static void esp_pci_dma_memory_write(void *opaque, uint8_t *buf, int len)
{
    PCIESPState *pci = opaque;
    esp_pci_dma_memory_rw(pci, buf, len, DMA_DIRECTION_FROM_DEVICE);
}

static const MemoryRegionOps esp_pci_io_ops = {
    .read = esp_pci_io_read,
    .write = esp_pci_io_write,
    .endianness = DEVICE_LITTLE_ENDIAN,
    .impl = {
        .min_access_size = 1,
        .max_access_size = 4,
    },
};

static void esp_pci_hard_reset(DeviceState *dev)
{
    PCIESPState *pci = PCI_ESP(dev);
    ESPState *s = ESP(&pci->esp);

    esp_hard_reset(s);
    pci->dma_regs[DMA_CMD] &= ~(DMA_CMD_DIR | DMA_CMD_INTE_D | DMA_CMD_INTE_P
                              | DMA_CMD_MDL | DMA_CMD_DIAG | DMA_CMD_MASK);
    pci->dma_regs[DMA_WBC] &= ~0xffff;
    pci->dma_regs[DMA_WAC] = 0xffffffff;
    pci->dma_regs[DMA_STAT] &= ~(DMA_STAT_BCMBLT | DMA_STAT_SCSIINT
                               | DMA_STAT_DONE | DMA_STAT_ABORT
                               | DMA_STAT_ERROR);
    pci->dma_regs[DMA_WMAC] = 0xfffffffd;
}

static const VMStateDescription vmstate_esp_pci_scsi = {
    .name = "pciespscsi",
    .version_id = 2,
    .minimum_version_id = 1,
    .pre_save = esp_pre_save,
    .fields = (VMStateField[]) {
        VMSTATE_PCI_DEVICE(parent_obj, PCIESPState),
        VMSTATE_BUFFER_UNSAFE(dma_regs, PCIESPState, 0, 8 * sizeof(uint32_t)),
        VMSTATE_UINT8_V(esp.mig_version_id, PCIESPState, 2),
        VMSTATE_STRUCT(esp, PCIESPState, 0, vmstate_esp, ESPState),
        VMSTATE_END_OF_LIST()
    }
};

static void esp_pci_command_complete(SCSIRequest *req, size_t resid)
{
    ESPState *s = req->hba_private;
    PCIESPState *pci = container_of(s, PCIESPState, esp);

    esp_command_complete(req, resid);
    pci->dma_regs[DMA_WBC] = 0;
    pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE;
}

static const struct SCSIBusInfo esp_pci_scsi_info = {
    .tcq = false,
    .max_target = ESP_MAX_DEVS,
    .max_lun = 7,

    .transfer_data = esp_transfer_data,
    .complete = esp_pci_command_complete,
    .cancel = esp_request_cancelled,
};

static void esp_pci_scsi_realize(PCIDevice *dev, Error **errp)
{
    PCIESPState *pci = PCI_ESP(dev);
    DeviceState *d = DEVICE(dev);
    ESPState *s = ESP(&pci->esp);
    uint8_t *pci_conf;

    if (!qdev_realize(DEVICE(s), NULL, errp)) {
        return;
    }

    pci_conf = dev->config;

    /* Interrupt pin A */
    pci_conf[PCI_INTERRUPT_PIN] = 0x01;

    s->dma_memory_read = esp_pci_dma_memory_read;
    s->dma_memory_write = esp_pci_dma_memory_write;
    s->dma_opaque = pci;
    s->chip_id = TCHI_AM53C974;
    memory_region_init_io(&pci->io, OBJECT(pci), &esp_pci_io_ops, pci,
                          "esp-io", 0x80);

    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->io);
    s->irq = pci_allocate_irq(dev);

    scsi_bus_init(&s->bus, sizeof(s->bus), d, &esp_pci_scsi_info);
}

static void esp_pci_scsi_exit(PCIDevice *d)
{
    PCIESPState *pci = PCI_ESP(d);
    ESPState *s = ESP(&pci->esp);

    qemu_free_irq(s->irq);
}

static void esp_pci_init(Object *obj)
{
    PCIESPState *pci = PCI_ESP(obj);

    object_initialize_child(obj, "esp", &pci->esp, TYPE_ESP);
}

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

    k->realize = esp_pci_scsi_realize;
    k->exit = esp_pci_scsi_exit;
    k->vendor_id = PCI_VENDOR_ID_AMD;
    k->device_id = PCI_DEVICE_ID_AMD_SCSI;
    k->revision = 0x10;
    k->class_id = PCI_CLASS_STORAGE_SCSI;
    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
    dc->desc = "AMD Am53c974 PCscsi-PCI SCSI adapter";
    dc->reset = esp_pci_hard_reset;
    dc->vmsd = &vmstate_esp_pci_scsi;
}

static const TypeInfo esp_pci_info = {
    .name = TYPE_AM53C974_DEVICE,
    .parent = TYPE_PCI_DEVICE,
    .instance_init = esp_pci_init,
    .instance_size = sizeof(PCIESPState),
    .class_init = esp_pci_class_init,
    .interfaces = (InterfaceInfo[]) {
        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
        { },
    },
};

struct DC390State {
    PCIESPState pci;
    eeprom_t *eeprom;
};
typedef struct DC390State DC390State;

#define TYPE_DC390_DEVICE "dc390"
DECLARE_INSTANCE_CHECKER(DC390State, DC390,
                         TYPE_DC390_DEVICE)

#define EE_ADAPT_SCSI_ID 64
#define EE_MODE2         65
#define EE_DELAY         66
#define EE_TAG_CMD_NUM   67
#define EE_ADAPT_OPTIONS 68
#define EE_BOOT_SCSI_ID  69
#define EE_BOOT_SCSI_LUN 70
#define EE_CHKSUM1       126
#define EE_CHKSUM2       127

#define EE_ADAPT_OPTION_F6_F8_AT_BOOT   0x01
#define EE_ADAPT_OPTION_BOOT_FROM_CDROM 0x02
#define EE_ADAPT_OPTION_INT13           0x04
#define EE_ADAPT_OPTION_SCAM_SUPPORT    0x08


static uint32_t dc390_read_config(PCIDevice *dev, uint32_t addr, int l)
{
    DC390State *pci = DC390(dev);
    uint32_t val;

    val = pci_default_read_config(dev, addr, l);

    if (addr == 0x00 && l == 1) {
        /* First byte of address space is AND-ed with EEPROM DO line */
        if (!eeprom93xx_read(pci->eeprom)) {
            val &= ~0xff;
        }
    }

    return val;
}

static void dc390_write_config(PCIDevice *dev,
                               uint32_t addr, uint32_t val, int l)
{
    DC390State *pci = DC390(dev);
    if (addr == 0x80) {
        /* EEPROM write */
        int eesk = val & 0x80 ? 1 : 0;
        int eedi = val & 0x40 ? 1 : 0;
        eeprom93xx_write(pci->eeprom, 1, eesk, eedi);
    } else if (addr == 0xc0) {
        /* EEPROM CS low */
        eeprom93xx_write(pci->eeprom, 0, 0, 0);
    } else {
        pci_default_write_config(dev, addr, val, l);
    }
}

static void dc390_scsi_realize(PCIDevice *dev, Error **errp)
{
    DC390State *pci = DC390(dev);
    Error *err = NULL;
    uint8_t *contents;
    uint16_t chksum = 0;
    int i;

    /* init base class */
    esp_pci_scsi_realize(dev, &err);
    if (err) {
        error_propagate(errp, err);
        return;
    }

    /* EEPROM */
    pci->eeprom = eeprom93xx_new(DEVICE(dev), 64);

    /* set default eeprom values */
    contents = (uint8_t *)eeprom93xx_data(pci->eeprom);

    for (i = 0; i < 16; i++) {
        contents[i * 2] = 0x57;
        contents[i * 2 + 1] = 0x00;
    }
    contents[EE_ADAPT_SCSI_ID] = 7;
    contents[EE_MODE2] = 0x0f;
    contents[EE_TAG_CMD_NUM] = 0x04;
    contents[EE_ADAPT_OPTIONS] = EE_ADAPT_OPTION_F6_F8_AT_BOOT
                               | EE_ADAPT_OPTION_BOOT_FROM_CDROM
                               | EE_ADAPT_OPTION_INT13;

    /* update eeprom checksum */
    for (i = 0; i < EE_CHKSUM1; i += 2) {
        chksum += contents[i] + (((uint16_t)contents[i + 1]) << 8);
    }
    chksum = 0x1234 - chksum;
    contents[EE_CHKSUM1] = chksum & 0xff;
    contents[EE_CHKSUM2] = chksum >> 8;
}

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

    k->realize = dc390_scsi_realize;
    k->config_read = dc390_read_config;
    k->config_write = dc390_write_config;
    set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
    dc->desc = "Tekram DC-390 SCSI adapter";
}

static const TypeInfo dc390_info = {
    .name = TYPE_DC390_DEVICE,
    .parent = TYPE_AM53C974_DEVICE,
    .instance_size = sizeof(DC390State),
    .class_init = dc390_class_init,
};

static void esp_pci_register_types(void)
{
    type_register_static(&esp_pci_info);
    type_register_static(&dc390_info);
}

type_init(esp_pci_register_types)
