/*
 * Copyright (C) Jan 2013 Mellanox Technologies Ltd. All rights reserved.
 * Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
 * General Public License (GPL) Version 2, available from the file
 * COPYING in the main directory of this source tree, or the
 * OpenIB.org BSD license below:
 *
 *     Redistribution and use in source and binary forms, with or
 *     without modification, are permitted provided that the following
 *     conditions are met:
 *
 *      - Redistributions of source code must retain the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer.
 *
 *      - Redistributions in binary form must reproduce the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *
 * 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.
 *
 */

#ifndef _MTCR_COM_DEFS_H
#define _MTCR_COM_DEFS_H

// Flash and TLV register access definitions
#define FLASH_REG_ACCESS 0x9001
#define REG_ACCESS_STRING_TLV 0x9003
#define ICMD_MAX_CMD_SIZE 0x340 // max mailbox size

// Max register size definitions
#define REGISTER_HEADERS_SIZE 20
#define INBAND_MAX_REG_SIZE 44
#define INBAND_MAX_REG_SIZE_CLS_A 204
#define INBAND_MAX_GMP_DWORDS_NUM 55
#define INBAND_MAX_GMP_BLOCKS 16
#define INBAND_MAX_GMP_REG_SIZE INBAND_MAX_GMP_BLOCKS* INBAND_MAX_GMP_DWORDS_NUM * 4
#define ICMD_MAX_REG_SIZE (ICMD_MAX_CMD_SIZE - REGISTER_HEADERS_SIZE)
#define FWCTX_MAX_REG_SIZE        16
#define TOOLS_HCR_MAX_REG_SIZE (TOOLS_HCR_MAX_MBOX - REGISTER_HEADERS_SIZE)


enum {
    MAD_CLASS_1_REG_ACCESS   = 1,
    MAD_CLASS_A_REG_ACCESS = 0x0A,
};

#ifdef __WIN__

#include <winsock2.h>
#include <windows.h>

#ifdef __AARCH64EL__
#define MTCR_API
#else
#ifdef MTCR_EXPORTS
#define MTCR_API __declspec(dllexport)
#else
#define MTCR_API __declspec(dllimport)
#endif
#endif

#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)
#include <stdint.h>
#else
typedef __int8 int8_t;
typedef __int16 int16_t;
typedef __int32 int32_t;
typedef __int64 int64_t;
#endif /* !_MSC_VER */
typedef unsigned __int8 u_int8_t;
typedef unsigned __int16 u_int16_t;
typedef unsigned __int32 u_int32_t;
typedef unsigned __int64 u_int64_t;

#if defined(_WIN64)
typedef __int64 MT_long_ptr_t;
typedef unsigned __int64 MT_ulong_ptr_t;
#else
typedef _W64 long MT_long_ptr_t;
typedef _W64 unsigned long MT_ulong_ptr_t;
#endif

#elif defined(__DJGPP__)

typedef unsigned char u_int8_t;
typedef char int8_t;
typedef unsigned short u_int16_t;
typedef short int16_t;
typedef unsigned int u_int32_t;
typedef long int32_t;
typedef unsigned long long u_int64_t;
typedef long long int64_t;

#define bswap_32(x) ntohl(x)
#define MTCR_API

#else /* UNIX */

#include <sys/types.h>
#define MTCR_API
#define LOCK_FILE_DIR "/tmp/mstflint_lockfiles"
#define LOCK_FILE_FORMAT "/tmp/mstflint_lockfiles/%04x:%02x:%02x.%x_%s"
#define LOCK_VIRTUAL_PCI_FILE_FORMAT "/tmp/mstflint_lockfiles/%s_%s"
#define MAX_RETRY_CNT 4096
#endif /* ifdef __WIN__ */

#define DEV_NAME_SZ 512
#define MAX_PAGES_SIZE 8
#define SMP_SEMAPHOE_LOCK_CMD 0xff53
#define ADDRESS_OUT_OF_RANGE 0x3 /* syndrome_code value */

/*
 * MST <--> MTCR API defines
 */
#define MST_HEADER_VERSION 1
#define MST_META_DATA_MAJOR 1
#define MST_META_DATA_MINOR 0
#define MTCR_SUPP_MST_API_MAJOR_VERSION 1

/* Service name. */
#define MST_PREFIX_64_BIT "mst64_"
#define MST_PREFIX_32_BIT "mst32_"
#define MST_SUFFIX_MAXLEN 11
#define MST_SERVICE_NAME_SIZE (sizeof(MST_PREFIX_64_BIT) + sizeof(MFT_VERSION_STR) + MST_SUFFIX_MAXLEN + 9) /* 9 is just in case reserve */

/*#ifndef USE_IB_MGT */
typedef struct mib_private_t
{
    int dummy;
} MIB_Private;
/*#else */
/*#include "mtcr_ib_private.h" */
/*#endif */

#define MTCR_I2C_secondary_ADDRESS 0x48
#define SLV_ADDRS_NUM 128

typedef enum
{
    SEM_LOCK_GET = 0x0,
    SEM_LOCK_SET = 0x1
} sem_lock_method_t;

/* PCI operation enum(read or write)*/
typedef enum
{
    READ_OP = 0,
    WRITE_OP = 1,
} rw_op_t;

typedef enum MError
{
    ME_OK = 0,
    ME_ERROR,
    ME_BAD_PARAMS,
    ME_CR_ERROR,
    ME_NOT_IMPLEMENTED,
    ME_SEM_LOCKED,
    ME_MEM_ERROR,
    ME_TIMEOUT,
    ME_ADDRESS_OUT_OF_RANGE,

    ME_MAD_SEND_FAILED,
    ME_UNKOWN_ACCESS_TYPE,
    ME_UNSUPPORTED_DEVICE,
    ME_REG_NOT_SUPPORTED,

    ME_PCI_READ_ERROR,
    ME_PCI_WRITE_ERROR,
    ME_PCI_SPACE_NOT_SUPPORTED,
    ME_PCI_IFC_TOUT,

    ME_UNSUPPORTED_OPERATION,
    ME_UNSUPPORTED_ACCESS_TYPE,
    ME_GMP_MAD_UNSUPPORTED_OPERATION,

    /* errors regarding REG_ACCESS */
    ME_REG_ACCESS_OK = 0,
    ME_REG_ACCESS_BAD_STATUS_ERR = 0x100,
    ME_REG_ACCESS_BAD_METHOD,
    ME_REG_ACCESS_NOT_SUPPORTED,
    ME_REG_ACCESS_DEV_BUSY,
    ME_REG_ACCESS_VER_NOT_SUPP,
    ME_REG_ACCESS_UNKNOWN_TLV,
    ME_REG_ACCESS_REG_NOT_SUPP,
    ME_REG_ACCESS_CLASS_NOT_SUPP,
    ME_REG_ACCESS_METHOD_NOT_SUPP,
    ME_REG_ACCESS_BAD_PARAM,
    ME_REG_ACCESS_RES_NOT_AVLBL,
    ME_REG_ACCESS_MSG_RECPT_ACK,
    ME_REG_ACCESS_UNKNOWN_ERR,
    ME_REG_ACCESS_SIZE_EXCEEDS_LIMIT,
    ME_REG_ACCESS_CONF_CORRUPT,
    ME_REG_ACCESS_LEN_TOO_SMALL,
    ME_REG_ACCESS_BAD_CONFIG,
    ME_REG_ACCESS_ERASE_EXCEEDED,
    ME_REG_ACCESS_INTERNAL_ERROR,
    ME_REG_ACCESS_NOT_SUPPORTED_BY_SECONDARY,
    ME_REG_ACCESS_INSUFFICIENT_PERMISSIONS,
    ME_REG_ACCESS_NOT_READY,
    ME_REG_ACCESS_BAD_QP_STATE,
    ME_REG_ACCESS_BAD_PKT,
    ME_REG_ACCESS_BAD_SIZE_OUTS_CQES,
    ME_REG_ACCESS_BAD_SYS_STATE,
    ME_REG_ACCESS_EXCEED_LIM,
    ME_REG_ACCESS_BAD_RES_STATE,
    ME_REG_ACCESS_BAD_INDEX,
    ME_REG_ACCESS_BAD_INPUT_LEN,
    ME_REG_ACCESS_BAD_OUTPUT_LEN,

    /* errors regarding ICMD */
    ME_ICMD_STATUS_CR_FAIL = 0x200, /* cr-space access failure */
    ME_ICMD_INVALID_OPCODE,
    ME_ICMD_INVALID_CMD,
    ME_ICMD_OPERATIONAL_ERROR,
    ME_ICMD_BAD_PARAM,
    ME_ICMD_BUSY,
    ME_ICMD_INIT_FAILED,
    ME_ICMD_NOT_SUPPORTED,
    ME_ICMD_STATUS_SEMAPHORE_TO, /* timed out while trying to take semaphore */
    ME_ICMD_STATUS_EXECUTE_TO,   /* timed out while waiting for command to execute */
    ME_ICMD_STATUS_IFC_BUSY,
    ME_ICMD_STATUS_ICMD_NOT_READY,
    ME_ICMD_UNSUPPORTED_ICMD_VERSION,
    ME_ICMD_UNKNOWN_STATUS,
    ME_ICMD_ICM_NOT_AVAIL,
    ME_ICMD_WRITE_PROTECT,
    ME_ICMD_SIZE_EXCEEDS_LIMIT,
    ME_ICMD_UNABLE_TO_TAKE_SEMAOHORE,

    /* errors regarding Tools CMDIF */
    ME_CMDIF_BUSY = 0x300,
    ME_CMDIF_TOUT,
    ME_CMDIF_BAD_STATUS,
    ME_CMDIF_BAD_OP,
    ME_CMDIF_NOT_SUPP,
    ME_CMDIF_BAD_SYS,
    ME_CMDIF_UNKN_TLV,
    ME_CMDIF_RES_STATE,
    ME_CMDIF_UNKN_STATUS,

    /* errors regarding MAD IF */
    ME_MAD_BUSY = 0x400,
    ME_MAD_REDIRECT,
    ME_MAD_BAD_VER,
    ME_MAD_METHOD_NOT_SUPP,
    ME_MAD_METHOD_ATTR_COMB_NOT_SUPP,
    ME_MAD_BAD_DATA,
    ME_MAD_GENERAL_ERR,

    /* errors regarding gearbox icmd new interface gateway */
    ME_GB_ICMD_OK = 0x500,
    ME_GB_ICMD_FAILED,
    ME_GB_ICMD_FAILED_ACCESS,
    ME_GB_ICMD_FAILED_BAD_PARAM,
    ME_GB_ICMD_TIMEOUT,
    ME_GB_ICMD_NOT_SUPPORTED,
    ME_GB_ICMD_UNKNOWN_STATUS,

    ME_LAST
} MError;

/* typedefs for UEFI */
#ifdef UEFI_BUILD
#include <mft_uefi_common.h>
#endif
typedef enum MType_t
{
    MST_ERROR = 0x0,
    MST_FPGA = 0x1, /* Unsupported */
    MST_MLNXOS = 0x2,
    MST_LPC = 0x4,
    MST_PCI = 0x8,
    MST_PCICONF = 0x10,
    /*MST_CALBR,*/
    MST_USB = 0x20,
    MST_IB = 0x40,
    MST_FWCTL_CONTROL_DRIVER = 0x80,
    MST_PPC = 0x100,
    MST_USB_DIMAX = 0x200,
    MST_FWCTX = 0x400,
    MST_REMOTE = 0x800,
#ifdef ENABLE_MST_DEV_I2C
    MST_DEV_I2C = 0x1000,
#endif
    MST_CALBR = 0x2000,
    MST_FPGA_ICMD = 0x4000, /* Unsupported */
    MST_CABLE = 0x8000,
    MST_FPGA_DRIVER = 0x10000, /* Unsupported */
    MST_SOFTWARE = 0x20000,
    MST_DRIVER_CONF = 0x40000,
    MST_DRIVER_CR = 0x80000,
    MST_LINKX_CHIP = 0x100000,
    MST_BAR0_GW_PCI = 0x200000,
    MST_NVML = 0x400000,
#ifdef ENABLE_VFIO
    MST_VFIO_DEVICE = 0x800000,
#endif
    MST_DEFAULT = 0xffffffff & ~MST_CABLE & ~MST_FPGA & ~MST_FPGA_ICMD & ~MST_FPGA_DRIVER & ~MST_LINKX_CHIP
} MType;

typedef enum DType_t
{
    MST_GAMLA,
    MST_TAVOR,
    MST_DIMM,
    MST_NOADDR
} DType;
#define MST_ANAFA2 MST_TAVOR
#define MST_EEPROM MST_GAMLA
typedef enum Mdevs_t
{
    MDEVS_GAMLA = 0x01,         /*  Each device that actually is a Gamla */
    MDEVS_I2CM = 0x02,          /*  Each device that can work as I2C master */
    MDEVS_MEM = 0x04,           /*  Each device that is a memory driver (vtop) */
    MDEVS_TAVOR_DDR = 0x08,     /*  Each device that maps to DDR */
    MDEVS_TAVOR_UAR = 0x10,     /*  Each device that maps to UAR */
    MDEVS_TAVOR_CR = 0x20,      /*  Each device that maps to CR */
    MDEVS_REM = 0x80,           /*  Remote devices */
    MDEVS_PPC = 0x100,          /*  PPC devices */
    MDEVS_DEV_I2C = 0x200,      /* Generic linux kernel i2c device */
    MDEVS_IB = 0x400,           /* Cr access over IB Mads */
    MDEVS_MLNX_OS = 0x800,      /* access by CmdIf in MlnxOS */
    MDEVS_FWCTX = 0x900,        /* access by func/context (like UEFI) */
    MDEVS_LPC = 0x1000,         /* Access LPC region */
    MDEVS_FPGA = 0x2000,        /* Access LPC region - DEPRECATED */
    MDEVS_FPGA_NEWTON = 0x4000, /* Access LPC region - DEPRECATED */
    MDEVS_CABLE = 0x8000,
    MDEVS_SOFTWARE = 0x10000, /* Software system char dev */
    MDEVS_LINKX_CHIP = 0x200000,
    MDEVS_GBOX = 0x400000,
    MDEVS_TAVOR = (MDEVS_TAVOR_DDR | MDEVS_TAVOR_UAR | MDEVS_TAVOR_CR),
    MDEVS_ALL = 0xffffffff
} Mdevs;

typedef enum
{
    MACCESS_REG_METHOD_GET = 1,
    MACCESS_REG_METHOD_SET = 2,
    MACCESS_LAST_REG_METHOD = 3
} maccess_reg_method_t;

typedef enum
{
    VCC_INITIALIZED = 0x0,
    VCC_ICMD_EXT_SPACE_SUPPORTED = 0x1,
    VCC_CRSPACE_SPACE_SUPPORTED = 0x2,
    VCC_ICMD_SPACE_SUPPORTED = 0x3,
    VCC_NODNIC_INIT_SEG_SPACE_SUPPORTED = 0x4,
    VCC_EXPANSION_ROM_SPACE_SUPPORTED = 0x5,
    VCC_ND_CRSPACE_SPACE_SUPPORTED = 0x6,
    VCC_SCAN_CRSPACE_SPACE_SUPPORTED = 0x7,
    VCC_SEMAPHORE_SPACE_SUPPORTED = 0x8,
    VCC_RECOVERY_SPACE_SUPPORTED = 0x9,
    VCC_MAC_SPACE_SUPPORTED = 0xa,
    VCC_PCI_ICMD_SPACE_SUPPORTED = 0xb,
    VCC_PCI_CRSPACE_SPACE_SUPPORTED = 0xc,
    VCC_PCI_ALL_ICMD_SPACE_SUPPORTED = 0xd,
    VCC_PCI_SCAN_CRSPACE_SPACE_SUPPORTED = 0xe,
    VCC_PCI_GLOBAL_SEMAPHORE_SPACE_SUPPORTED = 0xf,
} VSCCapCom;

typedef enum
{
    AS_ICMD_EXT = 0x1,
    AS_CR_SPACE = 0x2,
    AS_ICMD = 0x3,
    AS_NODNIC_INIT_SEG = 0x4,
    AS_EXPANSION_ROM = 0x5,
    AS_ND_CRSPACE = 0x6,
    AS_SCAN_CRSPACE = 0x7,
    AS_SEMAPHORE = 0xa,
    AS_RECOVERY = 0xc,
    AS_MAC = 0xf,
    AS_PCI_ICMD = 0x101,
    AS_PCI_CRSPACE = 0x102,
    AS_PCI_ALL_ICMD = 0x103,
    AS_PCI_SCAN_CRSPACE = 0x107,
    AS_PCI_GLOBAL_SEMAPHORE = 0x10a,
    AS_END
} address_space_t;

typedef struct vf_info_t
{
    char dev_name[512];
    u_int16_t domain;
    u_int8_t bus;
    u_int8_t dev;
    u_int8_t func;
    char** net_devs; /* Null terminated array */
    char** ib_devs;  /* Null terminated array */
} vf_info;

typedef struct dev_info_t
{
    Mdevs type;
    char dev_name[512];
    int ul_mode;

    union
    {
        struct
        {
            u_int16_t domain;
            u_int8_t bus;
            u_int8_t dev;
            u_int8_t func;
            u_int16_t dev_id;
            u_int16_t vend_id;
            u_int32_t class_id;
            u_int16_t subsys_id;
            u_int16_t subsys_vend_id;
            char cr_dev[512];
            char conf_dev[512];
            char** net_devs;      /* Null terminated array */
            char** ib_devs;       /* Null terminated array */
            char numa_node[4096]; /* */
            vf_info* virtfn_arr;
            u_int16_t virtfn_count;
            char fwctl_dev[DEV_NAME_SZ]; // fwctl device path
        } pci;

        struct
        {
            u_int32_t mtusb_serial;
            u_int32_t TBD;
        } usb;

        struct
        {
            u_int32_t TBD;
        } ib;

        struct
        {
            char remote_device_name[512];
        } remote;
    };
} dev_info;

typedef enum
{
    RA_MFPA = 0x9010,
    RA_MFBA = 0x9011,
    RA_MFBE = 0x9012,
} reg_access_t;
typedef struct dma_lib_hdl_t dma_lib_hdl;

typedef enum
{
    GEARBPX_OVER_MTUSB = 1,
    GEARBPX_OVER_I2C = 2,
    GEARBPX_OVER_SWITCH = 3,
    GEARBPXO_UNKNOWN_CONNECTION = 0
} gearbox_connection_t;
typedef enum
{
    MTCR_STATUS_UNKNOWN,
    MTCR_STATUS_TRUE,
    MTCR_STATUS_FALSE,
} mtcr_status_e;

typedef struct icmd_params_t
{
    int icmd_opened;
    int took_semaphore;
    int ctrl_addr;
    int cmd_addr;
    int cmd_ptr_bitlen;
    int version_addr;
    int version_bit_offset;
    int version_bitlen;
    u_int32_t max_cmd_size;
    int semaphore_addr;
    int static_cfg_not_done_addr;
    int static_cfg_not_done_offs;
    u_int32_t lock_key;
    int ib_semaphore_lock_supported;
    u_int64_t dma_pa;
    u_int32_t dma_size;
    int dma_icmd;
    mtcr_status_e icmd_ready;
    int syndrome;
    int syndrome_addr;
} icmd_params;

typedef struct ctx_params_t
{
    void* fw_cmd_context;
    void* fw_cmd_func;
    void* fw_cmd_dma;
} ctx_params;

typedef struct io_region_t
{
    unsigned int start;
    unsigned int end;
} io_region;

typedef struct tools_hcr_params_t
{
    int supp_cr_mbox; /* 1: mbox supported , -1: mbox not supported */
} tools_hcr_params;

/* max_reg_size depends on the desired method operated on the register. */
/* max_reg_size[<method_enum_value>] will give the relevant max_reg_size. */
/* For example max_reg_size[MACCESS_REG_METHOD_GET] will give max_reg_size for Get() method. */
typedef struct access_reg_params_t
{
    int max_reg_size[MACCESS_LAST_REG_METHOD];
} access_reg_params;

typedef struct mfile_t mfile;

struct mtcr_page_addresses
{
    u_int64_t dma_address;
    u_int64_t virtual_address;
};

struct page_list
{
    /* User space buffer page aligned. */
    char* page_list;
    int page_amount;
};

struct mtcr_page_info
{
    unsigned int page_amount;
    unsigned long page_pointer_start;
    struct mtcr_page_addresses page_addresses_array[MAX_PAGES_SIZE];
};

struct mtcr_read_dword_from_config_space
{
    unsigned int offset;
    unsigned int data;
};

typedef void (*f_mpci_change)(mfile* mf);

#define GEARBOX_ADDR_WIDTH 4
#define GEARBOX_SLAVE_ADDR 0x48
#define GB_MNGR_SLAVE_ADDR 0x33

typedef enum
{
    GB_UNKNOWN = 0,
    GB_AMOS,
    GB_ABIR
} gearbox_type;

typedef struct gearbox_info_t
{
    gearbox_type gb_type;
    u_int8_t is_gearbox;
    u_int8_t is_gb_mngr;
    int gearbox_index;
    int ilne_card_id;
    gearbox_connection_t gb_conn_type;
    char gb_mngr_full_name[DEV_NAME_SZ];
    char gearbox_full_name[DEV_NAME_SZ];
    unsigned char i2c_secondary;
    u_int8_t addr_width;
    char device_orig_name[DEV_NAME_SZ];
    char device_real_name[DEV_NAME_SZ];
    u_int32_t data_req_addr;
    u_int32_t data_res_addr;
} gearbox_info;

typedef struct cables_info_t
{
    int slave_addr_additional_offset;
} cables_info;

#define HW_ID_ADDR 0xf0014

#define VSEC_MIN_SUPPORT_UL(mf)                                                                                                                                                     \
    (((mf)->vsec_cap_mask & (1 << VCC_INITIALIZED)) && ((mf)->vsec_cap_mask & (1 << VCC_CRSPACE_SPACE_SUPPORTED)) && ((mf)->vsec_cap_mask & (1 << VCC_ICMD_EXT_SPACE_SUPPORTED)) && \
     ((mf)->vsec_cap_mask & (1 << VCC_SEMAPHORE_SPACE_SUPPORTED)))

#define VSEC_PXIR_SUPPORT(mf) (mf->pxir_vsec_supp)

/* Macro for VSEC_SUPPORTED_UL */
#define VSEC_SUPPORTED_UL(mf) ((mf)->functional_vsec_supp && (VSEC_MIN_SUPPORT_UL(mf) || VSEC_PXIR_SUPPORT(mf)))

#endif /* ifndef _MTCR_COM_DEFS_H */
