/*
 * Copyright (C) Jan 2013 Mellanox Technologies Ltd. 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_RECIEVE(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_RECIEVE(data_struct, struct_name, method)
#endif

/***************************************************/

// register access for variable size registers (like mfba)
#define MAD_IFC_ACCESS(mf, method, attr_id, attr_mod, data_struct, struct_name)\
    int status = 0;\
    u_int8_t data[MAX_DATA_SIZE] = {0};\
    tools_open_##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);\
    }\
    tools_open_##struct_name##_unpack(data_struct, data);\
    DEBUG_PRINT_RECIEVE(data_struct, struct_name, method);\
    if (status) {\
        return (mad_ifc_status_t)status;\
    }\
    return ME_OK

/************************************
 * 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* port_info)
{
    MAD_IFC_ACCESS(mf, method, MAD_ATTR_PORT_INFO, attr_mod, port_info, ib_port_info);
}

/************************************
 * 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);
}

/************************************
 * 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* ext_port_info)
{
    MAD_IFC_ACCESS(mf, method, MAD_ATTR_NODE_INFO, attr_mod, ext_port_info, extended_ib_port_info);
}

/************************************
 * 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* general_info)
{
    MAD_IFC_ACCESS(mf, method, MAD_ATTR_GENERAL_INFO_SMP, attr_mod, general_info, smp_vsp_general_info);
}

/************************************
 * Function: mad_ifc_general_info_hw
 ************************************/
mad_ifc_status_t mad_ifc_general_info_hw(mfile* mf, struct tools_open_hw_info* hwinfo)
{
    MAD_IFC_ACCESS(mf, MAD_IFC_METHOD_GET, MAD_ATTR_GENERAL_INFO_SMP, 0, hwinfo, hw_info);
}

/************************************
 * Function: mad_ifc_general_info_fw
 ************************************/
mad_ifc_status_t mad_ifc_general_info_fw(mfile* mf, struct tools_open_fw_info* fwinfo)
{
    MAD_IFC_ACCESS(mf, MAD_IFC_METHOD_GET, MAD_ATTR_GENERAL_INFO_SMP, 1, fwinfo, fw_info);
}

/************************************
 * Function: mad_ifc_general_info_hw
 ************************************/
mad_ifc_status_t mad_ifc_general_info_sw(mfile* mf, struct tools_open_sw_info* swinfo)
{
    MAD_IFC_ACCESS(mf, MAD_IFC_METHOD_GET, MAD_ATTR_GENERAL_INFO_SMP, 2, swinfo, sw_info);
}
/************************************
 * Function: mad_ifc_err2str
 ************************************/

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