/*
 * 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.
 */


#include "mad_ifc.h"

#define MAD_ATTR_PORT_INFO          0x15
#define MAD_ATTR_NODE_INFO          0x11
#define MAD_ATTR_GENERAL_INFO_SMP   0xff17

#define MAX_DATA_SIZE               64

// for debug:
// #define _ENABLE_DEBUG_
#ifdef _ENABLE_DEBUG_
# define DEBUG_PRINT_SEND(data_struct, struct_name, method) \
    printf("-I- Data Sent (Method: %s):\n", method == MAD_IFC_METHOD_SET ? "SET" : "GET"); \
    tools_open_##struct_name##_print(data_struct, stdout, 1)
# define DEBUG_PRINT_RECEIVE(data_struct, struct_name, method) \
    printf("-I- Data Received (Mehtod: %s):\n", method == MAD_IFC_METHOD_SET ? "SET" : "GET"); \
    tools_open_##struct_name##_print(data_struct, stdout, 1)
#else
# define DEBUG_PRINT_SEND(data_struct, struct_name, method)
# define DEBUG_PRINT_RECEIVE(data_struct, struct_name, method)
#endif

/***************************************************/
#if !defined(DISABLE_OFED) && !defined(NO_INBAND)
    // register access for variable size registers (like mfba)
    #define MAD_IFC_ACCESS(mf, method, attr_id, attr_mod, data_struct, struct_name, prefix) \
        int status = 0; \
        u_int8_t data[MAX_DATA_SIZE] = {0}; \
        prefix##_##struct_name##_pack(data_struct, data); \
        if (method != MAD_IFC_METHOD_GET && method != MAD_IFC_METHOD_SET) { \
            return ME_ERROR; \
        } \
        DEBUG_PRINT_SEND(data_struct, struct_name, method); \
        if (method == MAD_IFC_METHOD_GET) { \
            status = mib_smp_get(mf, data, attr_id, attr_mod); \
        } else { \
            status = mib_smp_set(mf, data, attr_id, attr_mod); \
        } \
        prefix##_##struct_name##_unpack(data_struct, data); \
        DEBUG_PRINT_RECEIVE(data_struct, struct_name, method); \
        if (status) { \
            return (mad_ifc_status_t)status; \
        } \
        return ME_OK
#else
    #define MAD_IFC_ACCESS(mf, method, attr_id, attr_mod, data_struct, struct_name, prefix) \
        (void) mf; \
        (void) method; \
        (void) attr_id; \
        (void) attr_mod; \
        (void) data_struct; \
        return ME_NOT_IMPLEMENTED
#endif

/************************************
* Function: mad_ifc_port_info
************************************/
mad_ifc_status_t mad_ifc_port_info(mfile *mf, mad_ifc_method_t method, u_int16_t attr_mod, struct tools_open_ib_port_info *ib_port_info)
{
    MAD_IFC_ACCESS(mf, method, MAD_ATTR_PORT_INFO, attr_mod, ib_port_info,
            ib_port_info, tools_open);
}

/************************************
* Function: mad_ifc_node_info
************************************/
mad_ifc_status_t mad_ifc_node_info(mfile *mf, mad_ifc_method_t method, u_int16_t attr_mod, struct tools_open_node_info *node_info)
{
    MAD_IFC_ACCESS(mf, method, MAD_ATTR_NODE_INFO, attr_mod, node_info,
            node_info, tools_open);
}

/************************************
* Function: mad_ifc_extended_port_info
************************************/
mad_ifc_status_t mad_ifc_extended_port_info(mfile *mf, mad_ifc_method_t method, u_int16_t attr_mod, struct tools_open_extended_ib_port_info *extended_ib_port_info)
{
    MAD_IFC_ACCESS(mf, method, MAD_ATTR_NODE_INFO, attr_mod, extended_ib_port_info,
            extended_ib_port_info, tools_open);
}

/************************************
* Function: mad_ifc_general_info_smp
************************************/
mad_ifc_status_t mad_ifc_general_info_smp(mfile *mf, mad_ifc_method_t method, u_int16_t attr_mod, union tools_open_smp_vsp_general_info *smp_vsp_general_info)
{
    MAD_IFC_ACCESS(mf, method, MAD_ATTR_GENERAL_INFO_SMP, attr_mod,
            smp_vsp_general_info, smp_vsp_general_info, tools_open);
}

/************************************
* Function: mad_ifc_general_info_hw
************************************/
mad_ifc_status_t mad_ifc_general_info_hw(mfile *mf,
        struct reg_access_hca_mgir_hardware_info *mgir_hardware_info) {
    MAD_IFC_ACCESS(mf, MAD_IFC_METHOD_GET, MAD_ATTR_GENERAL_INFO_SMP, 0, mgir_hardware_info,
            mgir_hardware_info, reg_access_hca);
}

/************************************
* Function: mad_ifc_general_info_fw
************************************/
mad_ifc_status_t mad_ifc_general_info_fw(mfile *mf,
        struct reg_access_hca_mgir_fw_info *mgir_fw_info) {
    MAD_IFC_ACCESS(mf, MAD_IFC_METHOD_GET, MAD_ATTR_GENERAL_INFO_SMP, 1, mgir_fw_info,
            mgir_fw_info, reg_access_hca);
}

/************************************
* Function: mad_ifc_general_info_sw
************************************/
mad_ifc_status_t mad_ifc_general_info_sw(mfile *mf,
        struct reg_access_hca_mgir_sw_info *mgir_sw_info) {
    MAD_IFC_ACCESS(mf, MAD_IFC_METHOD_GET, MAD_ATTR_GENERAL_INFO_SMP, 2, mgir_sw_info,
            mgir_sw_info, reg_access_hca);
}
/************************************
* Function: mad_ifc_err2str
************************************/

const char* mad_ifc_err2str(mad_ifc_status_t status)
{
    return m_err2str(status);
}
