// Copyright 2016 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 <efi/types.h>
#include <efi/protocol/pci-root-bridge-io.h>

#include <stdio.h>
#include <xefi.h>

typedef struct {
    uint8_t descriptor;
    uint16_t len;
    uint8_t res_type;
    uint8_t gen_flags;
    uint8_t specific_flags;
    uint64_t addrspace_granularity;
    uint64_t addrrange_minimum;
    uint64_t addrrange_maximum;
    uint64_t addr_tr_offset;
    uint64_t addr_len;
} __attribute__((packed)) acpi_addrspace_desc64_t;

#define ACPI_ADDRESS_SPACE_DESCRIPTOR 0x8A
#define ACPI_END_TAG_DESCRIPTOR       0x79

#define ACPI_ADDRESS_SPACE_TYPE_BUS   0x02

typedef struct {
    uint16_t vid;
    uint16_t did;
    uint16_t cmd;
    uint16_t status;
    uint8_t rev_id;
    uint8_t class_code[3];
    uint8_t cache_line_size;
    uint8_t primary_lat_timer;
    uint8_t hdr_type;
    uint8_t bist;
    uint32_t bar[6];
    uint32_t cardbus_cis;
    uint16_t subid;
    uint16_t subvid;
    uint32_t exprom_bar;
    uint8_t cap_ptr;
    uint8_t reserved[7];
    uint8_t irq_line;
    uint8_t irq_pin;
    uint8_t min_grant;
    uint8_t max_lat;
} __attribute__((packed)) pci_common_header_t;

#define PCI_MAX_DEVICES 32
#define PCI_MAX_FUNCS 8

efi_status xefi_find_pci_mmio(efi_boot_services* bs, uint8_t cls, uint8_t sub, uint8_t ifc, uint64_t* mmio) {
    size_t num_handles;
    efi_handle* handles;
    efi_status status = bs->LocateHandleBuffer(ByProtocol, &PciRootBridgeIoProtocol,
            NULL, &num_handles, &handles);
    if (EFI_ERROR(status)) {
        printf("Could not find PCI root bridge IO protocol: %s\n", xefi_strerror(status));
        return status;
    }

    for (int i = 0; i < num_handles; i++) {
        printf("handle %d\n", i);
        efi_pci_root_bridge_io_protocol* iodev;
        status = bs->HandleProtocol(handles[i], &PciRootBridgeIoProtocol, (void**)&iodev);
        if (EFI_ERROR(status)) {
            printf("Could not get protocol for handle %d: %s\n", i, xefi_strerror(status));
            continue;
        }
        acpi_addrspace_desc64_t* descriptors;
        status = iodev->Configuration(iodev, (void**)&descriptors);
        if (EFI_ERROR(status)) {
            printf("Could not get configuration for handle %d: %s\n", i, xefi_strerror(status));
            continue;
        }

        uint16_t min_bus, max_bus;
        while (descriptors->descriptor != ACPI_END_TAG_DESCRIPTOR) {
            min_bus = (uint16_t)descriptors->addrrange_minimum;
            max_bus = (uint16_t)descriptors->addrrange_maximum;

            if (descriptors->res_type != ACPI_ADDRESS_SPACE_TYPE_BUS) {
                descriptors++;
                continue;
            }

            for (int bus = min_bus; bus <= max_bus; bus++) {
                for (int dev = 0; dev < PCI_MAX_DEVICES; dev++) {
                    for (int func = 0; func < PCI_MAX_FUNCS; func++) {
                        pci_common_header_t pci_hdr;
                        bs->SetMem(&pci_hdr, sizeof(pci_hdr), 0);
                        uint64_t address = (uint64_t)((bus << 24) + (dev << 16) + (func << 8));
                        status = iodev->Pci.Read(iodev, EfiPciWidthUint16, address, sizeof(pci_hdr) / 2, &pci_hdr);
                        if (EFI_ERROR(status)) {
                            printf("could not read pci configuration for bus %d dev %d func %d: %s\n",
                                    bus, dev, func, xefi_strerror(status));
                            continue;
                        }
                        if (pci_hdr.vid == 0xffff) break;
                        if ((pci_hdr.class_code[2] == cls) &&
                            (pci_hdr.class_code[1] == sub) &&
                            (pci_hdr.class_code[0] == ifc)) {
                            uint64_t n = ((uint64_t) pci_hdr.bar[0]) |
                                         ((uint64_t) pci_hdr.bar[1]) << 32UL;
                            *mmio = n & 0xFFFFFFFFFFFFFFF0UL;
                            status = EFI_SUCCESS;
                            goto found_it;
                        }
#if 0
                        printf("bus %04x dev %02x func %02x: ", bus, dev, func);
                        printf("VID: 0x%04x  DID: 0x%04x  Class: 0x%02x  Subclass: 0x%02x  Intf: 0x%02x\n",
                                pci_hdr.vid, pci_hdr.did, pci_hdr.class_code[2], pci_hdr.class_code[1],
                                pci_hdr.class_code[0]);
                        printf("     hdr_type: %02x\n", pci_hdr.hdr_type);
                        if ((pci_hdr.hdr_type & 0x7f) == 0x00) {
                            for (int bar = 0; bar < 6; bar++) {
                                if (pci_hdr.bar[bar]) {
                                    printf("     bar[%d]: 0x%08x\n", bar, pci_hdr.bar[bar]);
                                }
                                bool is64bit = (pci_hdr.bar[bar] & 0x06) == 0x04;
                                if (is64bit) {
                                    printf("     bar[%d]: 0x%08x\n", bar+1, pci_hdr.bar[bar+1]);
                                    bar++;
                                }
                                // TODO: get the BAR size
                                //   - disable IO
                                //   - write 1s
                                //   - read it back
                                //   - reset or map to somewhere else(?)
                            }
                        }
#endif
                        if (!(pci_hdr.hdr_type & 0x80) && func == 0) {
                            break;
                        }
                    }
                }
            }
            descriptors++;
        }
    }

    status = EFI_NOT_FOUND;
found_it:
    bs->FreePool(handles);
    return status;
}
