/*
 * Copyright 2020 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "pci.hpp"

#include "tool_errors.hpp"

extern "C"
{
#include <pciaccess.h>
} // extern "C"

#include "helper.hpp"

#include <stdplus/handle/managed.hpp>

#include <cstring>
#include <format>
#include <span>
#include <system_error>

namespace host_tool
{

namespace
{

/** @brief RAII wrapper and its destructor for creating a pci_device_iterator */
static void closeIt(struct pci_device_iterator*&& it,
                    const PciAccess* const& pci)
{
    pci->pci_iterator_destroy(it);
}
using It = stdplus::Managed<struct pci_device_iterator*,
                            const PciAccess* const>::Handle<closeIt>;

} // namespace

PciAccessBridge::PciAccessBridge(const struct pci_id_match* match, int bar,
                                 std::size_t dataOffset, std::size_t dataLength,
                                 const PciAccess* pci) :
    dataOffset(dataOffset),
    dataLength(dataLength), pci(pci)
{
    It it(pci->pci_id_match_iterator_create(match), pci);

    while ((dev = pci->pci_device_next(*it)))
    {
        int ret = pci->pci_device_probe(dev);
        if (ret)
        {
            throw std::system_error(ret, std::generic_category(),
                                    "Error probing PCI device");
        }

        /* Verify it's a memory-based bar. */
        if (!dev->regions[bar].is_IO)
            break;
    }

    if (!dev)
    {
        throw NotFoundException(std::format(
            "PCI device {:#04x}:{:#04x}", match->vendor_id, match->device_id));
    }

    std::fprintf(stderr, "Find [0x%x 0x%x] \n", match->vendor_id,
                 match->device_id);
    std::fprintf(stderr, "bar%d[0x%x] \n", bar,
                 static_cast<unsigned int>(dev->regions[bar].base_addr));

    size = dev->regions[bar].size;
    int ret = pci->pci_device_map_range(
        dev, dev->regions[bar].base_addr, dev->regions[bar].size,
        PCI_DEV_MAP_FLAG_WRITABLE, reinterpret_cast<void**>(&addr));
    if (ret)
    {
        throw std::system_error(ret, std::generic_category(),
                                "Error mapping PCI device memory");
    }
}

PciAccessBridge::~PciAccessBridge()
{
    int ret = pci->pci_device_unmap_range(dev, addr, size);

    if (ret)
    {
        std::fprintf(stderr, "Error while unmapping PCI device memory: %s\n",
                     std::strerror(ret));
    }
}

void PciAccessBridge::write(const std::span<const std::uint8_t> data)
{
    if (data.size() > dataLength)
    {
        throw ToolException(
            std::format("Write of {} bytes exceeds maximum of {}", data.size(),
                        dataLength));
    }

    memcpyAligned(addr + dataOffset, data.data(), data.size());
}

void NuvotonPciBridge::enableBridge()
{
    std::uint8_t value;
    int ret;

    /* TODO: pci_device_disable support is missing in libpciaccess. Add it
     * to the disableBridge() once it is available.
     * https://gitlab.freedesktop.org/xorg/lib/libpciaccess/-/merge_requests/17
     */

    pci->pci_device_enable(dev);

    /* We need to retain this direct write to config space even though
     * pci_device_enable() should do it. Because currently disabling is done
     * through write to config space and not done through the proper api.
     * So libpciaccess ref count does not reset on disable. The
     * pci_device_enable() above will not do anything the second time.
     */
    ret = pci->pci_device_cfg_read_u8(dev, &value, bridge);
    if (ret)
    {
        throw std::system_error(ret, std::generic_category(),
                                "Error reading bridge status");
    }

    if (value & bridgeEnabled)
    {
        std::fprintf(stderr, "Bridge already enabled\n");
        return;
    }

    value |= bridgeEnabled;

    ret = pci->pci_device_cfg_write_u8(dev, value, bridge);
    if (ret)
    {
        throw std::system_error(ret, std::generic_category(),
                                "Error enabling bridge");
    }
}

void NuvotonPciBridge::disableBridge()
{
    std::uint8_t value;
    int ret;

    ret = pci->pci_device_cfg_read_u8(dev, &value, bridge);
    if (ret)
    {
        std::fprintf(stderr, "Error reading bridge status: %s\n",
                     std::strerror(ret));
        return;
    }
    value &= ~bridgeEnabled;

    ret = pci->pci_device_cfg_write_u8(dev, value, bridge);
    if (ret)
    {
        std::fprintf(stderr, "Error disabling bridge: %s\n",
                     std::strerror(ret));
    }
}

void AspeedPciBridge::enableBridge()
{
    /* We sent the open command before this, so the window should be open and
     * the bridge enabled on the BMC.
     */
    std::uint32_t value;

    /* TODO: pci_device_disable support is missing in libpciaccess. Add it
     * to the disableBridge() once it is available.
     * https://gitlab.freedesktop.org/xorg/lib/libpciaccess/-/merge_requests/17
     */

    pci->pci_device_enable(dev);

    /* We need to retain this direct write to config space even though
     * pci_device_enable() should do it. Because currently disabling is done
     * through write to config space and not done through the proper api.
     * So libpciaccess ref count does not reset on disable. The
     * pci_device_enable() above will not do anything the second time.
     */

    std::memcpy(&value, addr + config, sizeof(value));

    if (0 == (value & bridgeEnabled))
    {
        std::fprintf(stderr, "Bridge not enabled - Enabling from host\n");

        value |= bridgeEnabled;
        std::memcpy(addr + config, &value, sizeof(value));
    }

    std::fprintf(stderr, "The bridge is enabled!\n");
}

void AspeedPciBridge::disableBridge()
{
    /* addr is valid if the constructor completed */

    /* Read current value, and just blindly unset the bit. */
    std::uint32_t value;
    std::memcpy(&value, addr + config, sizeof(value));

    value &= ~bridgeEnabled;
    std::memcpy(addr + config, &value, sizeof(value));
}

void AspeedPciBridge::configure(const ipmi_flash::PciConfigResponse& configResp)
{
    std::fprintf(stderr, "Received address: 0x%x\n", configResp.address);

    /* Configure the mmio to point there. */
    std::memcpy(addr + bridge, &configResp.address, sizeof(configResp.address));
}

} // namespace host_tool
