// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <assert.h>
#include <fbl/auto_lock.h>
#include <hw/inout.h>
#include <hwreg/bitfields.h>
#include <pci/pio.h>
#include <zircon/hw/pci.h>
#include <zircon/types.h>

#ifdef __x86_64__

static constexpr uint16_t kPciConfigAddrPort = 0xCF8;
static constexpr uint16_t kPciConfigDataPort = 0xCFC;

fbl::Mutex pio_port_lock;

typedef struct {
    uint32_t value;
    DEF_SUBBIT(value, 31, enable);
    DEF_SUBFIELD(value, 23, 16, bus);
    DEF_SUBFIELD(value, 15, 11, device);
    DEF_SUBFIELD(value, 10, 8, function);
    DEF_SUBFIELD(value, 7, 0, reg_num);
} config_address_t;

// This library assumes the calling process already has the io bitmap permissions
// set to access cf8/cfc. Any processes with that permission will be synchronizing
// with each other by means of the PCI Root protocol.

static zx_status_t pci_pio_read(pci_bdf_t bdf, uint8_t offset, uint32_t* val) {
    fbl::AutoLock lock(&pio_port_lock);

    config_address_t addr = {};
    addr.set_enable(true);
    addr.set_bus(bdf.bus_id);
    addr.set_device(bdf.device_id);
    addr.set_function(bdf.function_id);
    addr.set_reg_num(offset & ~0x3); // Lowest 2 bits must be zero, all reads are 32 bit

    outpd(kPciConfigAddrPort, addr.value);
    *val = inpd(kPciConfigDataPort);
    return ZX_OK;
}

zx_status_t pci_pio_read32(pci_bdf_t bdf, uint8_t offset, uint32_t* val) {
    // Only 32 bit alignment allowed for 32 bit reads.
    if (offset & 0x3) {
        printf("invalid args read32\n");
        return ZX_ERR_INVALID_ARGS;
    }
    uint32_t _val = 0;
    zx_status_t status = pci_pio_read(bdf, offset, val);
    if (status == ZX_OK) {
        *val = _val;
    }
    return status;
}

zx_status_t pci_pio_read16(pci_bdf_t bdf, uint8_t offset, uint16_t* val) {
    // Only 16 bit alignment allowed for 16 bit reads
    if (offset & 0x1) {
        printf("invalid args read16\n");
        return ZX_ERR_INVALID_ARGS;
    }

    uint32_t _val = 0;
    zx_status_t status = pci_pio_read(bdf, offset, &_val);
    if (status == ZX_OK) {
        // Shift the top 16 over if requested
        *val = static_cast<uint16_t>(_val >> (8u * (offset & 0x2)));
    }
    return status;
}

zx_status_t pci_pio_read8(pci_bdf_t bdf, uint8_t offset, uint8_t* val) {
    uint32_t _val = 0;
    zx_status_t status = pci_pio_read(bdf, offset, &_val);
    if (status == ZX_OK) {
        *val = static_cast<uint8_t>(_val >> (8u * (offset & 0x3)));
    }
    return status;
}

// Generates an unshifted mask to match the width of the write we're making.
static constexpr uint32_t rmw_mask(size_t width) {
    return (width == 32) ? 0xffffffff : (1u << width) - 1u;
}

// Figure out the shift to align the bytes in the right. Valid offsets are already
// checked by the pci_pio_write calls themselves.
static constexpr int calculate_shift(uint8_t offset) {
    return (offset & 0x3) * 8u;
}

static zx_status_t pci_pio_write(pci_bdf_t bdf, uint8_t offset, uint32_t mask, uint32_t val) {
    fbl::AutoLock lock(&pio_port_lock);

    config_address_t addr = {};
    addr.set_enable(true);
    addr.set_bus(bdf.bus_id);
    addr.set_device(bdf.device_id);
    addr.set_function(bdf.function_id);
    addr.set_reg_num(offset & ~0x3); // Lowest 3 bits must be zero, all reads are 32 bit

    outpd(kPciConfigAddrPort, addr.value);
    // Zero out the bytes we're going to write and then OR them in.
    uint32_t old_val = inpd(kPciConfigDataPort);
    old_val &= ~mask;
    old_val |= val;
    outpd(kPciConfigDataPort, old_val);

    return ZX_OK;
}

zx_status_t pci_pio_write32(pci_bdf_t bdf, uint8_t offset, uint32_t val) {
    // Only 32 bit alignment allowed for 32 bit reads
    if (offset & 0x3) {
        return ZX_ERR_INVALID_ARGS;
    }
    return pci_pio_write(bdf, offset, rmw_mask(32), val);
}

// These functions both create a shifted mask and shifted value to call the main write
// function so that its body can be as simple as possible.
zx_status_t pci_pio_write16(pci_bdf_t bdf, uint8_t offset, uint16_t val) {
    // Only 16 bit alignment allowed for 16 bit reads
    if (offset & 0x1) {
        return ZX_ERR_INVALID_ARGS;
    }
    int shift = calculate_shift(offset);
    return pci_pio_write(bdf, offset, rmw_mask(16) << shift, val << shift);
}

zx_status_t pci_pio_write8(pci_bdf_t bdf, uint8_t offset, uint8_t val) {
    int shift = calculate_shift(offset);
    return pci_pio_write(bdf, offset, rmw_mask(8) << shift, val << shift);
}

#endif // __x86_64__
