
/*                  - Mellanox Confidential and Proprietary -
 *
 *  Copyright (C) Jan 2013, Mellanox Technologies Ltd.  ALL RIGHTS RESERVED.
 *
 *  Except as specifically permitted herein, no portion of the information,
 *  including but not limited to object code and source code, may be reproduced,
 *  modified, distributed, republished or otherwise exploited in any form or by
 *  any means for any purpose without the prior written permission of Mellanox
 *  Technologies Ltd. Use of software subject to the terms and conditions
 *  detailed in the file "LICENSE.txt".
 *
 */

/*
 *
 *  mtcr.h - Mellanox Software tools (mst) driver definitions
 *
 */

#ifndef _MST_H
#define _MST_H


#ifdef __WIN__
#include <Winsock2.h>
#include <winsock2.h>
#include <windows.h>

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

#ifdef MTCR_STDCALL
    #define MTCR_CALL_CONV __stdcall
#else
    #define MTCR_CALL_CONV __cdecl
#endif
//#define MTCR_API

#if defined(__MINGW32__) || defined(__MINGW64__)
    #include <stdint.h>
    #ifndef   MFT_TOOLS_VARS
        #define MFT_TOOLS_VARS
        typedef uint8_t  u_int8_t;
        typedef uint16_t u_int16_t;
        typedef uint32_t u_int32_t;
        typedef uint64_t u_int64_t;
    #endif
#else
    typedef unsigned __int8  u_int8_t;
    typedef __int8           int8_t;
    typedef unsigned __int16 u_int16_t;
    typedef __int16          int16_t;
    typedef unsigned __int32 u_int32_t;
    typedef __int32          int32_t;
    typedef unsigned __int64 u_int64_t;
    typedef __int64          int64_t;

#endif

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

#else  /* UNIX */

#include <sys/types.h>
#define MTCR_API
#define MTCR_CALL_CONV

#endif

#define SLV_ADDRS_NUM 128

#ifdef __cplusplus
extern "C" {
#endif

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

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

    ME_MAD_SEND_FAILED,
    ME_UNKOWN_ACCESS_TYPE,
    ME_UNSUPPORTED_DEVICE,
    ME_REG_NOT_SUPPORTED,

    // 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_EXCCEEDS_LIMIT,
    ME_REG_ACCESS_CONF_CORRUPT,
    ME_REG_ACCESS_LEN_TOO_SMALL,
    ME_REG_ACCESS_BAD_CONFIG,
    ME_REG_ACCESS_ERASE_EXEEDED,

    // 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_BAD_SIGNATURE,

    //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,

    ME_LAST
} MError;

typedef enum MType_t {MST_PCI, MST_PCICONF, MST_CALBR, MST_USB,
                        MST_IB, MST_IF, MST_PPC, MST_USB_DIMAX, MST_FWCTX
#ifdef ENABLE_MST_DEV_I2C
                        ,MST_DEV_I2C
#endif
} 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_IF        = 0x40, /*  Standard device  interface */
    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_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_reg_method_t;

typedef struct icmd_params_t {
    int icmd_opened;
    int took_semaphore;
    int ctrl_addr;
    int cmd_addr;
    int semaphore_addr;
    int static_cfg_not_done_addr;
    int static_cfg_not_done_offs;
}icmd_params;

/*  All fields in follow structure are not supposed to be used */
/*  or modified by user programs. Except i2c_slave that may be */
/*  modified before each access to target I2C slave address */
typedef struct mfile_t {
    MType         tp;           /*  type of driver */
    MType         res_tp;       /*  Reserved  type of driver for HCR usage */
    DType         dtype;        /*  target device to access to */
    DType         itype;        /*  interface device to access via */
    int           is_i2cm;      /*  use device as I2C master */
    unsigned char i2c_slave;
    long          mtusb_serial;
#ifdef __WIN__
    MT_ulong_ptr_t fd;
    MT_ulong_ptr_t res_fd;
#else
    int           fd;
#endif
    int           sock;         /*  in not -1 - remote interface */
    void         *ptr;
    void         *ctx;
    unsigned int  map_size;
    MIB_Private   mib;          /*  Data for IB interface (if relevant) */
    unsigned int  i2c_RESERVED; /*  Reserved for internal usage (i2c internal) */
    enum Mdevs_t  flags;
    u_int32_t     connectx_wa_slot; /* apply connectx cr write workaround */
    int           connectx_wa_last_op_write;
    u_int32_t     connectx_wa_stat;
    u_int64_t     connectx_wa_max_retries;
    u_int64_t     connectx_wa_num_of_writes;
    u_int64_t     connectx_wa_num_of_retry_writes;
    int           server_ver_major;
    int           server_ver_minor;
    //for ICMD access
    icmd_params icmd;
} mfile;

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

    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
        } pci;

        struct {
            u_int32_t TBD;
        } usb;

        struct {
            u_int32_t TBD;
        } ib;

        struct {
            u_int32_t TBD;
        } remote;
    };
} dev_info;

#ifdef __WIN__
#define FromHandle(h)   ((MT_ulong_ptr_t)(h))
#define ToHandle(h)     ((HANDLE)(h))
#else
#define FromHandle(h)   ((int)(h))
#define ToHandle(h)     ((HANDLE)(h))
#endif

/*
 * Get list of MST (Mellanox Software Tools) devices.
 * Put all device names as null-terminated strings to buf.
 *
 * Return number of devices found or -1 if buf overflow
 */
MTCR_API int MTCR_CALL_CONV mdevices(char *buf, int len, int mask);

/*
 * Get list of MST (Mellanox Software Tools) devices + PCI IDs of the devices.
 * Put all device names as null-terminated strings to buf.
 *
 * Return number of devices found or negative value for errors:
 *   INVALID_HANDLE_VALUE
 *   -1 for general error
 */

MTCR_API int MTCR_CALL_CONV mdevices_ids(char *buf, int len, int mask);

/*
 *  * Get list of MST (Mellanox Software Tools) devices info records.
 *  * Return a dynamic allocated array of dev_info records.
 *  * len will be updated to hold the array length
 *  *
 */
MTCR_API dev_info* mdevices_info(int mask, int* len);

/*
 *  Release dev_info allocated by mdevices_info()
 */
MTCR_API void mdevice_info_destroy(dev_info* dev_info, int len);


/*
 *  Release dev_info allocated by mdevices_info()
 */
MTCR_API void mdevices_info_destroy(dev_info* dev_info, int len);

/*
 * Open Mellanox Software tools (mst) driver.
 * Return valid mfile ptr or 0 on failure
 */
MTCR_API mfile * MTCR_CALL_CONV mopend(const char *name, DType dtype);

/*
 * Open Mellanox Software tools (mst) driver. Device type==INFINIHOST
 * Return valid mfile ptr or 0 on failure
 */
MTCR_API mfile * MTCR_CALL_CONV mopen(const char *name);

/*
 * Open Mellanox Software tools with uefi driver
 * Return valid mfile ptr or 0 on failure
 * NOTE: mfile will not conatin device data just context and uefi access function
 * supports only maccess_reg() function.
 */
MTCR_API mfile *mopen_fw_ctx(void* fw_cmd_context, void* fw_cmd_func);

/*
 * Close Mellanox driver
 * req. descriptor
 */
MTCR_API int MTCR_CALL_CONV mclose(mfile *mf);

/*
 * Accelerate device if possible.
 * When device is I2C master - overclock it
 */
MTCR_API void MTCR_CALL_CONV maccelerate(mfile *mf);

/*
 * Restore normal settings, if device was accelerated.
 */
MTCR_API void MTCR_CALL_CONV mrestore(mfile *mf);

/*
 * Read 4 bytes, return number of succ. read bytes or -1 on failure
 */
MTCR_API int MTCR_CALL_CONV mread4(mfile *mf, unsigned int offset, u_int32_t *value);

/*
 * Write 4 bytes, return number of succ. written bytes or -1 on failure
 */
MTCR_API int MTCR_CALL_CONV mwrite4(mfile *mf, unsigned int offset, u_int32_t value);

/*
 * Read a block of dwords, return number of succ. read bytes or -1 on failure
 * Works for any interface, but can be faster for interfaces where bursts
 * are supported (MTUSB, IB).
 * Data retrns in the same endianess of mread4/mwrite4
 */
MTCR_API int MTCR_CALL_CONV mread4_block (mfile *mf, unsigned int offset, u_int32_t* data, int byte_len);
MTCR_API int MTCR_CALL_CONV mwrite4_block(mfile *mf, unsigned int offset, u_int32_t* data, int byte_len);

/* read buffer as is without changing endians */
MTCR_API int MTCR_CALL_CONV mread_buffer(mfile *mf, unsigned int offset, u_int8_t* data, int byte_len);

/* Write buffer as is without changing endians */

MTCR_API int MTCR_CALL_CONV mwrite_buffer(mfile *mf, unsigned int offset, u_int8_t* data, int byte_len);

/*
 * Read up to 64 bytes, return number of succ. read bytes or -1 on failure
 *
 * This makes sense only w/ CALIBRE/DevaSys interfaces *to EEPROM reading only*
 */
MTCR_API int MTCR_CALL_CONV mread64(mfile *mf, unsigned int offset, void *data, int length);

/*
 * Write up to 64 bytes, return number of succ. written bytes or -1 on failure
 *
 * This makes sense only w/ CALIBRE/DevaSys interfaces *to EEPROM burning only*
 */
MTCR_API int MTCR_CALL_CONV mwrite64(mfile *mf, unsigned int offset, void *data, int length);


/*
 * Read up to 64 bytes, return number of succ. read bytes or -1 on failure
 */
MTCR_API int MTCR_CALL_CONV mread_i2cblock(mfile *mf, unsigned char i2c_slave, u_int8_t addr_width,
                            unsigned int offset, void *data, int length);

/*
 * Write up to 64 bytes, return number of succ. written bytes or -1 on failure
 */
MTCR_API int MTCR_CALL_CONV mwrite_i2cblock(mfile *mf, unsigned char i2c_slave, u_int8_t addr_width,
									 unsigned int offset, void *data, int length);


/*
 * Set a new value for i2c_slave
 * Return previous value
 */
MTCR_API unsigned char MTCR_CALL_CONV mset_i2c_slave(mfile *mf, unsigned char new_i2c_slave);

/*
 * Software reset the device.
 * Return 0 on success, <0 on failure.
 * Curently supported for IB device only.
 * Mellanox switch devices support this feature.
 * HCAs may not support this feature.
 */
MTCR_API int MTCR_CALL_CONV msw_reset(mfile *mf);

/*
 * get free phys. contigous pages
 * order should be in range [0..9]
 * the size of allocated memory will be (2^order * 4096)
 * return pointer to virtual address mapped to the allocated area
 * on failure returns 0 and errno is set
 */
MTCR_API void * MTCR_CALL_CONV mget_free_pages (mfile *mf, unsigned int order);

/*
 * free phys. contigous pages
 * order should be in range [0..9]
 * vma is freed
 * on success returns 0
 * on failure returns -1 and errno is set
 */
MTCR_API int MTCR_CALL_CONV mfree_pages (mfile *mf, void *addr, unsigned int order);



/*
 * translate virtual address to physical address
 * return physical address on success, or 0 on error
 */
MTCR_API unsigned long MTCR_CALL_CONV mvtop (mfile *mf, void *va);

/*
 * translate physical address to virtual address
 * return virtual address on success, or 0 on error
 * physical address must be page aligned and pinned
 */
MTCR_API void * MTCR_CALL_CONV mmap_kernel_memory_page(mfile *mf, u_int64_t pa, u_int32_t *err);

MTCR_API int MTCR_CALL_CONV mi2c_detect (mfile *mf, u_int8_t slv_arr[SLV_ADDRS_NUM]);

MTCR_API int MTCR_CALL_CONV mget_mdevs_flags(mfile *mf, u_int32_t *devs_flags);
MTCR_API int MTCR_CALL_CONV mget_mdevs_type(mfile *mf, u_int32_t *mtype);

#define MTCR_MFT_2_7_0
MTCR_API int MTCR_CALL_CONV maccess_reg_mad(mfile *mf, u_int8_t *data);

/*
 * Read or write byte, word or dword to the device pci configuration header.
 * These functions are built in for Linux (setpci//lspci tools) but not
 * available for Windows. These functions allow using our own pci utilities,
 * namely vpd access.
 *
 * Return values: Success: num of read/written bytes
 *                -1     : General error
 */
MTCR_API int MTCR_CALL_CONV maccess_reg(mfile     *mf,
                         u_int16_t  reg_id,
                         maccess_reg_method_t reg_method,
                         void*      reg_data,
                         u_int32_t  reg_size,
                         u_int32_t	r_size_reg, // used when sending via icmd interface (how much data should be read back to the user)
                         u_int32_t	w_size_reg, // used when sending via icmd interface (how much data should be written to the scratchpad)
                         	 	 	 	 	 	// if you dont know what you are doing then r_size_reg = w_size_reg = your_register_size
                         int       *reg_status);

/**
 * Handles the send command procedure.
 * for completeness, but calling it is strongly advised against.
 * @param[in] dev   A pointer to a device context, previously
 *                  obtained by a call to <tt>gcif_open</tt>.
 * @return          One of the GCIF_STATUS_* values, or a raw
 *                  status value (as indicated in cr-space).
 * NOTE: when calling this function the caller needs to make
 *  	sure device supports icmd.
 **/
MTCR_API int MTCR_CALL_CONV icmd_send_command(mfile    *mf,
                      int     opcode,
                      void*   data,
                      int     data_size,
                      int     skip_write);

/**
 * Clear the Tools-HCR semaphore. Use this when an application
 * that uses this library is not terminated cleanly, leaving the
 * semaphore in a locked state.
 * @param[in] dev   A pointer to a device context, previously
 *                  obtained by a call to <tt>gcif_open</tt>.
 * @return          One of the GCIF_STATUS_* values, or a raw
 *                  status value (as indicated in cr-space).
 * NOTE: when calling this function the caller needs to make
 *  	sure device supports icmd.
 **/
MTCR_API int MTCR_CALL_CONV icmd_clear_semaphore(mfile *mf);


MTCR_API int MTCR_CALL_CONV tools_cmdif_unlock_semaphore(mfile *mf);

/*
 * send an inline command to the tools HCR
 * limitations:
 * command should not use mailbox
 */
MTCR_API int MTCR_CALL_CONV tools_cmdif_send_inline_cmd(mfile* mf,
                     u_int64_t in_param,
                     u_int64_t* out_param,
                     u_int32_t input_modifier,
                     u_int16_t opcode,
                     u_int8_t  opcode_modifier);

/*
 * send a mailbox command to the tools HCR
 * limitations:
 * i.e write data to mailbox execute command (op = opcode op_modifier= opcode_modifier) and read data back from mailbox
 * data_offs_in_mbox: offset(in bytes) to read and write data to and from mailbox should be quad word alligned.
 */
MTCR_API int MTCR_CALL_CONV tools_cmdif_send_mbox_command(mfile* mf,
                                           u_int32_t input_modifier,
                                           u_int16_t opcode,
                                           u_int8_t  opcode_modifier,
                                           int data_offs_in_mbox,
                                           void* data,
                                           int data_size,
                                           int skip_write);

/*
 * returns the maximal allowed register size (in bytes)
 * according to the FW access method or -1 if no restriction applicable
 *
 */
MTCR_API int MTCR_CALL_CONV mget_max_reg_size(mfile *mf);
/*
 * translate virtual address to physical address
 * return physical address on success, or 0 on error
 */
MTCR_API int MTCR_CALL_CONV mpci_cfg_header_read (mfile* mf, u_int32_t offset, u_int32_t size, u_int32_t *buf);
MTCR_API int MTCR_CALL_CONV mpci_cfg_header_write(mfile* mf, u_int32_t offset, u_int32_t size, u_int32_t  buf);

MTCR_API int MTCR_CALL_CONV mstart_mst(char *full_service_path, u_int8_t force_start);

MTCR_API int MTCR_CALL_CONV mstop_mst(u_int8_t force_stop);

MTCR_API const char* MTCR_CALL_CONV m_err2str(MError status);

MTCR_API int MTCR_CALL_CONV tools_cmdif_query_dev_cap(mfile *mf, u_int32_t offset, u_int64_t* data);

MTCR_API int MTCR_CALL_CONV mib_smp_get(mfile* mf, u_int8_t* data, u_int16_t attr_id, u_int32_t attr_mod);
MTCR_API int MTCR_CALL_CONV mib_smp_set(mfile* mf, u_int8_t* data, u_int16_t attr_id, u_int32_t attr_mod);


MTCR_API int mvpd_read4(mfile *mf, unsigned int offset, u_int8_t value[4]);

MTCR_API int mvpd_write4(mfile *mf, unsigned int offset, u_int8_t value[4]);

#ifdef __cplusplus
}
#endif


#endif
