/*
 * Copyright 2014, NICTA
 *
 * This software may be distributed and modified according to the terms of
 * the GNU General Public License version 2. Note that NO WARRANTY is provided.
 * See "LICENSE_GPLv2.txt" for details.
 *
 * @TAG(NICTA_GPL)
 */
/* x86 VMM PCI Driver, which manages the host's PCI devices, and handles guest OS PCI config space
 * read & writes.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sel4/sel4.h>
#include <pci/pci.h>
#include <pci/helper.h>

#include "vmm/debug.h"
#include "vmm/vmm.h"
#include "vmm/driver/pci.h"
#include "vmm/driver/pci_helper.h"

int vmm_pci_init(vmm_pci_space_t *space) {
    for (int i = 0; i < 32; i++) {
        for(int j = 0; j < 8; j++) {
            space->bus0[i][j] = NULL;
        }
    }
    space->conf_port_addr = 0;
    /* Define the initial PCI bridge */
    vmm_pci_device_def_t *bridge = malloc(sizeof(*bridge));
    if (!bridge) {
        LOG_ERROR("Failed to malloc memory for pci bridge");
        return -1;
    }
    define_pci_host_bridge(bridge);
    return vmm_pci_add_entry(space, (vmm_pci_entry_t){.cookie = bridge, .ioread = vmm_pci_mem_device_read, .iowrite = vmm_pci_entry_ignore_write}, NULL);
}

int vmm_pci_add_entry(vmm_pci_space_t *space, vmm_pci_entry_t entry, vmm_pci_address_t *addr) {
    /* Find empty dev */
    for (int i = 0; i < 32; i++) {
        if (!space->bus0[i][0]) {
            /* Allocate an entry */
            space->bus0[i][0] = malloc(sizeof(entry));
            *space->bus0[i][0] = entry;
            /* Report addr if reqeusted */
            if (addr) {
                *addr = (vmm_pci_address_t){.bus = 0, .dev = i, .fun = 0};
            }
            LOG_INFO("Adding virtual PCI device at %02x:%02x.%d", 0, i, 0);
            return 0;
        }
    }
    LOG_ERROR("No free device slot on bus 0 to add virtual pci device");
    return -1;
}

static void make_addr_reg_from_config(uint32_t conf, vmm_pci_address_t *addr, uint8_t *reg) {
    addr->bus = (conf >> 16) & MASK(8);
    addr->dev = (conf >> 11) & MASK(5);
    addr->fun = (conf >> 8) & MASK(3);
    *reg = conf & MASK(8);
}

static vmm_pci_entry_t *find_device(vmm_pci_space_t *self, vmm_pci_address_t addr) {
    if (addr.bus != 0 || addr.dev >= 32 || addr.fun >= 8) {
        return NULL;
    }
    return self->bus0[addr.dev][addr.fun];
}

int vmm_pci_io_port_in(void *cookie, unsigned int port_no, unsigned int size, unsigned int *result) {
    vmm_pci_space_t *self = (vmm_pci_space_t*)cookie;
    uint8_t offset;

    if (port_no >= PCI_CONF_PORT_ADDR && port_no < PCI_CONF_PORT_ADDR_END) {
        offset = port_no - PCI_CONF_PORT_ADDR;
        assert(port_no + size <= PCI_CONF_PORT_ADDR_END);
        /* Emulate read addr. */
        *result = 0;
        memcpy(result, ((char*)&self->conf_port_addr) + offset, size);
        return 0;
    }
    assert(port_no >= PCI_CONF_PORT_DATA && port_no + size <= PCI_CONF_PORT_DATA_END);
    offset = port_no - PCI_CONF_PORT_DATA;

    /* construct a pci address from the current value in the config port */
    vmm_pci_address_t addr;
    uint8_t reg;
    make_addr_reg_from_config(self->conf_port_addr, &addr, &reg);
    reg += offset;

    /* Check if this device exists */
    vmm_pci_entry_t *dev = find_device(self, addr);
    if (!dev) {
        /* if the guest strayed from bus 0 then somethign went wrong. otherwise random reads
         * could just be it probing for devices */
        if (addr.bus != 0) {
            LOG_INFO("Guest attempted access to non existent device %02x:%02x.%d register 0x%x", addr.bus, addr.dev, addr.fun, reg);
        } else {
            DPRINTF(3, "Ignoring guest probe for device %02x:%02x.%d register 0x%x\n", addr.bus, addr.dev, addr.fun, reg);
        }
        *result = -1;
        return 0;
    }
    int error = dev->ioread(dev->cookie, reg, size, result);
    if (error) {
        return error;
    }
    /* Strip out any multi function reporting */
    if (reg + size > PCI_HEADER_TYPE && reg <= PCI_HEADER_TYPE) {
        /* This read overlapped with the header type, work out where it is and mask
         * the MF bit out */
        int header_offset = PCI_HEADER_TYPE - reg;
        unsigned int mf_mask = ~(BIT(7) << (header_offset * 8));
        (*result) &= mf_mask;
    }
    return 0;
}

int vmm_pci_io_port_out(void *cookie, unsigned int port_no, unsigned int size, unsigned int value) {
    vmm_pci_space_t *self = (vmm_pci_space_t*)cookie;
    uint8_t offset;

    if (port_no >= PCI_CONF_PORT_ADDR && port_no < PCI_CONF_PORT_ADDR_END) {
        offset = port_no - PCI_CONF_PORT_ADDR;
        assert(port_no + size <= PCI_CONF_PORT_ADDR_END);
        /* Emulated set addr. First mask out the bottom two bits of the address that
         * should never be used*/
        value &= ~MASK(2);
        memcpy(((char*)&self->conf_port_addr) + offset, &value, size);
        return 0;
    }
    assert(port_no >= PCI_CONF_PORT_DATA && port_no + size <= PCI_CONF_PORT_DATA_END);
    offset = port_no - PCI_CONF_PORT_DATA;

    /* construct a pci address from the current value in the config port */
    vmm_pci_address_t addr;
    uint8_t reg;
    make_addr_reg_from_config(self->conf_port_addr, &addr, &reg);
    reg += offset;

    /* Check if this device exists */
    vmm_pci_entry_t *dev = find_device(self, addr);
    if (!dev) {
        LOG_INFO("Guest attempted access to non existent device %02x:%02x.%d register 0x%x", addr.bus, addr.dev, addr.fun, reg);
        return 0;
    }
    return dev->iowrite(dev->cookie, reg + offset, size, value);
}

