/*
 * oem_dell.c
 * Handle Dell OEM command functions
 *
 * Change history:
 *  08/17/2011 ARCress - included in ipmiutil source tree
 *
 */
/******************************************************************
Copyright (c) 2008, Dell Inc
All rights reserved.
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. 
- Neither the name of Dell Inc nor the names of its contributors
may be used to endorse or promote products derived from this software 
without specific prior written permission. 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. 


******************************************************************/
/*
* Thursday Oct 7 17:30:12 2009
* <deepaganesh_paulraj@dell.com>
*
* This code implements a dell OEM proprietary commands.
* This Code is edited and Implemented the License feature for Delloem
* Author Harsha S <Harsha_S1@dell.com>
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef WIN32
#include <windows.h>
#define int8_t   char
#define uint8_t  unsigned char
#define uint16_t unsigned short
#define uint32_t unsigned int
#define uint64_t unsigned long
#include "getopt.h"
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <ctype.h>
#include <limits.h>
#ifndef HPUX
#include <getopt.h>
#endif
#endif

#include <time.h>
#include "ipmicmd.h"
#include "isensor.h"
#include "ievents.h"
#include "oem_dell.h"

// #ifdef METACOMMAND is assumed 
extern int i_sol(int  argc, char **argv);  /*isol.c*/
extern void lprintf(int level, const char * format, ...); /*ipmilanplus.c*/
extern void set_loglevel(int level);
extern void printbuf(const uint8_t * buf, int len, const char * desc);

#define IPMI_DELL_OEM_NETFN        (uint8_t)(0x30)
#define GET_CHASSIS_LED_STATE      (uint8_t)(0x32)
#define GET_IDRAC_VIRTUAL_MAC      (uint8_t)(0xC9)
// 11g Support Macros
#define INVALID -1
#define SHARED 0
#define SHARED_WITH_FAILOVER_LOM2 1
#define DEDICATED 2
#define SHARED_WITH_FAILOVER_ALL_LOMS 3
char AciveLOM_String[6][10] = {"dedicated","LOM1","LOM2","LOM3","LOM4","None" };
#define        INVAILD_FAILOVER_MODE   -2
#define        INVAILD_FAILOVER_MODE_SETTINGS  -3
#define        INVAILD_SHARED_MODE             -4

#define        INVAILD_FAILOVER_MODE_STRING    "ERROR: Cannot set shared with failover lom same as current shared lom.\n"
#define        INVAILD_FAILOVER_MODE_SET       "ERROR: Cannot set shared with failover loms when NIC is set to dedicated Mode.\n"
#define        INVAILD_SHARED_MODE_SET_STRING  "ERROR: Cannot set shared Mode for Blades.\n"

// 11g Support Strings for nic selection
char NIC_Selection_Mode_String [4] [50] =	{	"shared",  
												"shared with failover lom2",
												"dedicated",
												"shared with Failover all loms"
											};

// 11g Support Macros
#define SHARED 0
#define SHARED_WITH_FAILOVER_LOM2 1
#define DEDICATED 2
#define SHARED_WITH_FAILOVER_ALL_LOMS 3

// 12g Support Strings for nic selection
char NIC_Selection_Mode_String_12g[] [50] =	{	
												"dedicated",
												"shared with lom1",  
												"shared with lom2",
												"shared with lom3",
												"shared with lom4",
												"shared with failover lom1",
												"shared with failover lom2",
												"shared with failover lom3",
												"shared with failover lom4",
												"shared with failover all loms"
											};

static char * progver   = "2.84";
static char * progname  = "idelloem";
static int verbose = 0;
static char fdebug = 0;
static uchar  g_bus  = PUBLIC_BUS;
static uchar  g_sa   = BMC_SA;
static uchar  g_lun  = BMC_LUN;
static uchar  g_addrtype = ADDR_SMI;
static uchar *sdrcache = NULL;
static char  *sdrfile = NULL;
static int    argc_sav; 
static char **argv_sav;
static int current_arg =0;
uint8_t iDRAC_FLAG=0;
LCD_MODE lcd_mode;
static uint8_t LcdSupported=0;
static uint8_t SetLEDSupported=0;

volatile uint8_t IMC_Type = IMC_IDRAC_10G;


const struct vFlashstr vFlash_completion_code_vals[] = {
	{0x00, "SUCCESS"},
	{0x01, "NO_SD_CARD"},
	{0x63, "UNKNOWN_ERROR"},
	{0x00, NULL}
};


POWER_HEADROOM powerheadroom;

uint8_t PowercapSetable_flag=0;
uint8_t PowercapstatusFlag=0;

static void usage(void);

/* LCD Function prototypes */
static int ipmi_delloem_lcd_main (void * intf, int  argc, char ** argv);
static int ipmi_lcd_get_platform_model_name (void * intf,char* lcdstring,
                        uint8_t max_length,uint8_t field_type);
static int ipmi_idracvalidator_command (void * intf);
static int ipmi_lcd_get_configure_command_wh (void * intf);
static int ipmi_lcd_get_configure_command (void * intf,uint8_t *command);
static int ipmi_lcd_set_configure_command (void * intf, int command);
static int ipmi_lcd_set_configure_command_wh (void * intf, uint32_t  mode,
                        uint16_t lcdqualifier,uint8_t errordisp);
static int ipmi_lcd_get_single_line_text (void * intf, char* lcdstring, uint8_t max_length);
static int ipmi_lcd_get_info_wh(void * intf);
static int ipmi_lcd_get_info(void * intf);
static int ipmi_lcd_get_status_val(void * intf, LCD_STATUS* lcdstatus);
static int IsLCDSupported ();
static void CheckLCDSupport(void * intf);
static void ipmi_lcd_status_print( LCD_STATUS lcdstatus);
static int ipmi_lcd_get_status(void * intf );
static int ipmi_lcd_set_kvm(void * intf, char status);
static int ipmi_lcd_set_lock(void * intf,  char lock);
static int ipmi_lcd_set_single_line_text (void * intf, char * text);
static int ipmi_lcd_set_text(void * intf, char * text, int line_number);
static int ipmi_lcd_configure_wh (void * intf, uint32_t  mode ,
                       uint16_t lcdqualifier, uint8_t errordisp, 
                       int8_t line_number, char * text);
static int ipmi_lcd_configure (void * intf, int command, 
                    int8_t line_number, char * text);
static void ipmi_lcd_usage(void);

/* MAC Function prototypes */
static int ipmi_delloem_mac_main (void * intf, int  argc, char ** argv);
static int make_int(const char *str, int *value);
static void InitEmbeddedNICMacAddressValues ();
static int ipmi_macinfo_drac_idrac_virtual_mac(void* intf,uint8_t NicNum);
static int ipmi_macinfo_drac_idrac_mac(void* intf,uint8_t NicNum);
static int ipmi_macinfo_10g (void* intf, uint8_t NicNum);
static int ipmi_macinfo_11g (void* intf, uint8_t NicNum);
static int ipmi_macinfo (void* intf, uint8_t NicNum);
static void ipmi_mac_usage(void);

/* LAN Function prototypes */
static int ipmi_delloem_lan_main (void * intf, int  argc, char ** argv);
static int IsLANSupported ();
static int get_nic_selection_mode (int current_arg, char ** argv);
static int ipmi_lan_set_nic_selection (void* intf, uint8_t nic_selection);
static int ipmi_lan_get_nic_selection (void* intf);
static int get_nic_selection_mode_12g (void* intf,int iarg, char **argv, char *nic_set);
static int ipmi_lan_get_active_nic (void* intf);
static void ipmi_lan_usage(void);
static int ipmi_lan_set_nic_selection_12g (void* intf, uint8_t* nic_selection);

/* POwer monitor Function prototypes */
static int ipmi_delloem_powermonitor_main (void * intf, int  argc, char **argv);
static void ipmi_time_to_str(time_t rawTime, char* strTime);
static int ipmi_get_sensor_reading(void *intf ,
            unsigned char sensorNumber, 
                        SensorReadingType* pSensorReadingData);
static int ipmi_get_power_capstatus_command (void * intf);
static int ipmi_set_power_capstatus_command (void * intf,uint8_t val);
static int ipmi_powermgmt(void* intf);
static int ipmi_powermgmt_clear(void* intf,uint8_t clearValue);
static uint64_t watt_to_btuphr_conversion(uint32_t powerinwatt);
static uint32_t btuphr_to_watt_conversion(uint64_t powerinbtuphr);
static int ipmi_get_power_headroom_command (void * intf,uint8_t unit);
static int ipmi_get_power_consumption_data(void* intf,uint8_t unit);
static int ipmi_get_instan_power_consmpt_data(void* intf,
                        IPMI_INST_POWER_CONSUMPTION_DATA* instpowerconsumptiondata);
static void ipmi_print_get_instan_power_Amps_data(IPMI_INST_POWER_CONSUMPTION_DATA instpowerconsumptiondata);
static int ipmi_print_get_power_consmpt_data(void* intf,uint8_t  unit);
static int ipmi_get_avgpower_consmpt_history(void* intf,IPMI_AVGPOWER_CONSUMP_HISTORY* pavgpower );
static int ipmi_get_peakpower_consmpt_history(void* intf,IPMI_POWER_CONSUMP_HISTORY * pstPeakpower);
static int ipmi_get_minpower_consmpt_history(void* intf,IPMI_POWER_CONSUMP_HISTORY * pstMinpower);
static int ipmi_print_power_consmpt_history(void* intf,int unit );
static int ipmi_get_power_cap(void* intf,IPMI_POWER_CAP* ipmipowercap );
static int ipmi_print_power_cap(void* intf,uint8_t unit );
static int ipmi_set_power_cap(void* intf,int unit,int val );
static int getpowersupplyfruinfo(void *intf, uint8_t id, 
                       struct fru_header header, struct fru_info fru);
static void ipmi_powermonitor_usage(void);

/* vFlash Function prototypes */
static int ipmi_delloem_vFlash_main(void * intf, int  argc, char ** argv);
const char * get_vFlash_compcode_str(uint8_t vflashcompcode, const struct vFlashstr *vs);
static int ipmi_get_sd_card_info(void* intf);
static int ipmi_delloem_vFlash_process(void* intf, int current_arg, char ** argv);
static void ipmi_vFlash_usage(void);


/* windbg Function prototypes */
volatile uint8_t windbgsession = 0;
static int ipmi_delloem_windbg_main (void * intf, int  argc, char ** argv);
static int ipmi_windbg_start (void * intf);
static int ipmi_windbg_end (void * intf);
static void ipmi_windbg_usage (void);



/* LED Function prototypes */

static int ipmi_getsesmask(int, char **);
static int CheckSetLEDSupport(void * intf);
static int IsSetLEDSupported(void);
static void ipmi_setled_usage(void);
static int ipmi_delloem_setled_main(void *intf, int  argc, char ** argv);
static int ipmi_delloem_getled_main(void *intf, int  argc, char ** argv);
static int ipmi_setled_state (void * intf, int bayId, int slotId, int state);
static int ipmi_getdrivemap (void * intf, int b, int d, int f, int *bayId, int *slotId);
//extern int optind;  /*from getopt*/

static int ipmi_sol_activate(void *intf, int j, int k) 
{ 
   char **args;
   int rv, i, n;
   n = argc_sav;
   args = argv_sav;
   /* use the user-specified args, but switch to sol */
   for (i = 0; i < n; i++) {
      if (strcmp(args[i],"ipmiutil") == 0) { n--; args++; } 
      else if (strcmp(args[i],"delloem") == 0) args[i] = "sol";
      else if (strcmp(args[i],"windbg") == 0) args[i] = "-a";
      else if (strcmp(args[i],"start") == 0) args[i] = "-a";
   }
   ipmi_close_();
   optind = 0;
   rv = i_sol(n, args);
   return rv; 
}

static int ipmi_sol_deactivate(void *intf) 
{
   char **args;
   int rv, i, n;
   n = argc_sav;
   args = argv_sav;
   /* use the user-specified args, but switch to sol */
   for (i = 0; i < n; i++) {
      if (strcmp(args[i],"ipmiutil") == 0) { n--; args++; } 
      else if (strcmp(args[i],"delloem") == 0) args[i] = "sol";
      else if (strcmp(args[i],"windbg") == 0) args[i] = "-d";
      else if (strcmp(args[i],"start") == 0) args[i] = "-d";
   }
   ipmi_close_();
   optind = 0;
   rv = i_sol(n, args);
   return rv; 
}

/*****************************************************************
* Function Name:       ipmi_delloem_main
*
* Description:         This function processes the delloem command
* Input:               intf    - ipmi interface
                       argc    - no of arguments
                       argv    - argument string array
* Output:        
*
* Return:              return code     0 - success
*                                      -1 - failure
*
******************************************************************/

int
ipmi_delloem_main(void * intf, int  argc, char ** argv)
{
    int rc = 0;

    // ipmi_idracvalidator_command(intf);
    // CheckLCDSupport (intf);
    // CheckSetLEDSupport (intf);

    if (argc == 0 || strncmp(argv[0], "help\0", 5) == 0) 
    {
        usage();
        return 0;
    }

    if (0 ==strncmp(argv[current_arg], "lcd\0", 4) ) 
    {
        rc = ipmi_delloem_lcd_main (intf,argc,argv);
    }
    /* mac address*/
    else if (strncmp(argv[current_arg], "mac\0", 4) == 0) 
    {
        rc = ipmi_delloem_mac_main (intf,argc,argv);
    }
    /* lan address*/
    else if (strncmp(argv[current_arg], "lan\0", 4) == 0) 
    {
        rc = ipmi_delloem_lan_main (intf,argc,argv);
    }
    /* SetLED support */
    else if (strncmp(argv[current_arg], "setled\0", 7) == 0)
    {
        rc = ipmi_delloem_setled_main (intf,argc,argv);
    }
    else if (strncmp(argv[current_arg], "getled\0", 13) == 0) 
    {
        rc = ipmi_delloem_getled_main (intf,argc,argv);
    }
    /*Powermanagement report processing*/
    else if (strncmp(argv[current_arg], "powermonitor\0", 13) == 0) 
    {
        rc = ipmi_delloem_powermonitor_main (intf,argc,argv);
    }
	/* vFlash Support */	
	else if (strncmp(argv[current_arg], "vFlash\0", 7) == 0)
	{
        rc = ipmi_delloem_vFlash_main (intf,argc,argv);	
	}
	else if (strncmp(argv[current_arg], "windbg\0", 7) == 0) 
	{
        rc = ipmi_delloem_windbg_main (intf,argc,argv);		
	}
    else
    {
        usage();
        return ERR_USAGE;
    }
    return rc;
}

/*****************************************************************
* Function Name:     usage
*
* Description:       This function prints help message for delloem command
* Input:           
* Output:       
*
* Return:              
*
******************************************************************/

static void usage(void)
{
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "usage: delloem <command> [option...]");
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "commands:");
    lprintf(LOG_NOTICE, "    lcd"); 
    lprintf(LOG_NOTICE, "    mac");         
    lprintf(LOG_NOTICE, "    lan");
    lprintf(LOG_NOTICE, "    setled");         
    lprintf(LOG_NOTICE, "    getled");         
    lprintf(LOG_NOTICE, "    powermonitor");        
    lprintf(LOG_NOTICE, "    windbg");	
    lprintf(LOG_NOTICE, "    vFlash");
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "For help on individual commands type:");
    lprintf(LOG_NOTICE, "delloem <command> help");

}

/*****************************************************************
* Function Name:       ipmi_delloem_lcd_main
*
* Description:         This function processes the delloem lcd command
* Input:               intf    - ipmi interface
                       argc    - no of arguments
                       argv    - argument string array
* Output:        
*
* Return:              return code     0 - success
*                         -1 - failure
*
******************************************************************/

static int ipmi_delloem_lcd_main (void * intf, int  argc, char ** argv)
{
    int rc = 0;

    current_arg++;
    if (argc < current_arg) 
    {
        usage();
        return -1;
    }


    /* ipmitool delloem lcd info*/
    if (argc == 1 || strcmp(argv[current_arg], "help") == 0)
    {
        ipmi_lcd_usage();
	return 0;
    }
    CheckLCDSupport (intf);
    ipmi_idracvalidator_command(intf);
    if (!IsLCDSupported()) {
        printf("lcd is not supported on this system.\n");
        return -1;
    }
    else if (strncmp(argv[current_arg], "info\0", 5) == 0) 
    {
	if((iDRAC_FLAG==IDRAC_11G) || (iDRAC_FLAG==IDRAC_12G) )            
            rc = ipmi_lcd_get_info_wh(intf);
        else
            rc = ipmi_lcd_get_info(intf);
    }
    else if (strncmp(argv[current_arg], "status\0", 7) == 0)
    {
        rc = ipmi_lcd_get_status(intf);
    }
    /* ipmitool delloem lcd set*/
    else if (strncmp(argv[current_arg], "set\0", 4) == 0) 
    {
        uint8_t line_number = 0;
        current_arg++;
        if (argc <= current_arg) 
        {
            ipmi_lcd_usage();
            return -1;
        }
        if (strncmp(argv[current_arg], "line\0", 5) == 0) 
        {
            current_arg++;
            if (argc <= current_arg) {usage();return -1;}
            line_number = (uint8_t)strtoul(argv[current_arg], NULL, 0);
            current_arg++;
            if (argc <= current_arg) {usage();return -1;}
        }


		if ((strncmp(argv[current_arg], "mode\0", 5) == 0)&&((iDRAC_FLAG==IDRAC_11G) || (iDRAC_FLAG==IDRAC_12G) )) 
        {
            current_arg++;
            if (argc <= current_arg) 
            {
                ipmi_lcd_usage();
                return -1;
            }    
            if (argv[current_arg] == NULL)  
            {
                ipmi_lcd_usage();
                return -1;
            }
            if (strncmp(argv[current_arg], "none\0", 5) == 0) 
            {
                rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_CONFIG_NONE,0xFF,0XFF, 0, NULL);
            }
            else if (strncmp(argv[current_arg], "modelname\0", 10) == 0) 
            {
                rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_CONFIG_DEFAULT,0xFF,0XFF, 0, NULL);
            }
            else if (strncmp(argv[current_arg], "userdefined\0", 12) == 0) 
            {
                current_arg++;
                if (argc <= current_arg) 
                {
                    ipmi_lcd_usage();return -1;
                }
                rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_CONFIG_USER_DEFINED,0xFF,0XFF, line_number, argv[current_arg]);
            }
            else if (strncmp(argv[current_arg], "ipv4address\0", 12) == 0) 
            {
                rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_iDRAC_IPV4ADRESS  ,0xFF,0XFF, 0, NULL);
            }
            else if (strncmp(argv[current_arg], "macaddress\0", 11) == 0) 
            {
                rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_IDRAC_MAC_ADDRESS,0xFF,0XFF, 0, NULL);
            }
            else if (strncmp(argv[current_arg], "systemname\0", 11) == 0) 
            {
                rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_OS_SYSTEM_NAME,0xFF,0XFF, 0, NULL);
            }
            else if (strncmp(argv[current_arg], "servicetag\0", 11) == 0) 
            {
                rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_SERVICE_TAG, 0xFF,0XFF,0, NULL);
            }
            else if (strncmp(argv[current_arg], "ipv6address\0", 12) == 0) 
            {
                rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_iDRAC_IPV6ADRESS  ,0xFF,0XFF, 0, NULL);
            }
            else if (strncmp(argv[current_arg], "ambienttemp\0", 12) == 0) 
            {
                rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_AMBEINT_TEMP, 0xFF,0XFF,0, NULL);

            }
            else if (strncmp(argv[current_arg], "systemwatt\0", 11) == 0) 
            {
                rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_SYSTEM_WATTS , 0xFF,0XFF,0, NULL);

            }
            else if (strncmp(argv[current_arg], "assettag\0", 9) == 0) 
            {
                rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_ASSET_TAG , 0xFF,0XFF,0, NULL);

            }
            else if (strncmp(argv[current_arg], "help\0", 5) == 0) 
            {
                ipmi_lcd_usage();
            }
            else
            {       
                ipmi_lcd_usage();
            }
        }
		else if ((strncmp(argv[current_arg], "lcdqualifier\0", 13)== 0) &&((iDRAC_FLAG==IDRAC_11G) || (iDRAC_FLAG==IDRAC_12G) ) )
        {

            current_arg++;
            if (argc <= current_arg) 
            {
                ipmi_lcd_usage();
                return -1;
            }
            if (argv[current_arg] == NULL) 
            {
                ipmi_lcd_usage();
                return -1;
            } 

            if (strncmp(argv[current_arg], "watt\0", 5) == 0) {


                rc = ipmi_lcd_configure_wh (intf, 0xFF,0x00,0XFF, 0, NULL);
            }
            else if (strncmp(argv[current_arg], "btuphr\0",7) == 0) {
                rc = ipmi_lcd_configure_wh (intf, 0xFF,0x01,0XFF, 0, NULL);

            } else if (strncmp(argv[current_arg], "celsius\0", 8) == 0) {
                rc = ipmi_lcd_configure_wh (intf, 0xFF,0x02,0xFF, 0, NULL);
            } else if (strncmp(argv[current_arg], "fahrenheit", 11) == 0) {
                rc = ipmi_lcd_configure_wh (intf, 0xFF,0x03,0xFF, 0, NULL);

            }else if (strncmp(argv[current_arg], "help\0", 5) == 0) {
                ipmi_lcd_usage();
            }
            else {  
                ipmi_lcd_usage();
            }
        }
		else if( (strncmp(argv[current_arg], "errordisplay\0", 13) == 0)&&((iDRAC_FLAG==IDRAC_11G) || (iDRAC_FLAG==IDRAC_12G) )) 
        {

            current_arg++;
            if (argc <= current_arg)
            {
                ipmi_lcd_usage();
                return -1;
            }
            if (argv[current_arg] == NULL) 
            { 
                ipmi_lcd_usage();
                return -1;
            } 

            if (strncmp(argv[current_arg], "sel\0", 4) == 0) 
            {
                rc = ipmi_lcd_configure_wh (intf, 0xFF,0xFF,IPMI_DELL_LCD_ERROR_DISP_SEL , 0, NULL);
            }
            else if (strncmp(argv[current_arg], "simple\0", 7) == 0) 
            {
                rc = ipmi_lcd_configure_wh (intf, 0xFF,0xFF,IPMI_DELL_LCD_ERROR_DISP_VERBOSE , 0, NULL);

            }
            else if (strncmp(argv[current_arg], "help\0", 5) == 0) 
            {
                ipmi_lcd_usage();
            }
            else 
            {       
                ipmi_lcd_usage();
            }
        }

        else if ((strncmp(argv[current_arg], "none\0", 5) == 0)&&(iDRAC_FLAG==0)) 
        {
            rc = ipmi_lcd_configure (intf, IPMI_DELL_LCD_CONFIG_NONE, 0, NULL);
        }
        else if ((strncmp(argv[current_arg], "default\0", 8) == 0)&&(iDRAC_FLAG==0)) 
        {
            rc = ipmi_lcd_configure (intf, IPMI_DELL_LCD_CONFIG_DEFAULT, 0, NULL);

        } 
        else if ((strncmp(argv[current_arg], "custom\0", 7) == 0)&&(iDRAC_FLAG==0))  
        {
            current_arg++;
            if (argc <= current_arg) 
            {
                ipmi_lcd_usage();
                return -1;
            }
            rc = ipmi_lcd_configure (intf, IPMI_DELL_LCD_CONFIG_USER_DEFINED, line_number, argv[current_arg]);
        } 

        else if (strncmp(argv[current_arg], "vkvm\0", 5) == 0) 
        {
            current_arg++;
            if (argc <= current_arg) 
            {
                ipmi_lcd_usage();
                return -1;
            }

            if (strncmp(argv[current_arg], "active\0", 7) == 0) 
            {
                rc = ipmi_lcd_set_kvm (intf, 1);
            }
            else if (strncmp(argv[current_arg], "inactive\0", 9)==0)
            {
                rc = ipmi_lcd_set_kvm (intf, 0);

            }
            else if (strncmp(argv[current_arg], "help\0", 5) == 0) 
            {
                ipmi_lcd_usage();
            }
            else 
            {       
                ipmi_lcd_usage();
            }

        }
        else if (strncmp(argv[current_arg], "frontpanelaccess\0", 17) == 0) 
        {
            current_arg++;
            if (argc <= current_arg) 
            {
                ipmi_lcd_usage();
                return -1;
            }
            if (strncmp(argv[current_arg], "viewandmodify\0", 14) == 0) 
            {
                rc = ipmi_lcd_set_lock (intf, 0);
            }
            else if (strncmp(argv[current_arg], "viewonly\0", 9)==0)
            {
                rc =  ipmi_lcd_set_lock (intf, 1);

            }
            else if (strncmp(argv[current_arg], "disabled\0", 9)==0)
            {
                rc =  ipmi_lcd_set_lock (intf, 2);

            }
            else if (strncmp(argv[current_arg], "help\0", 5) == 0) 
            {
                ipmi_lcd_usage();
            }
            else 
            {       
                ipmi_lcd_usage();
            }

        }
        else if( (strncmp(argv[current_arg], "help\0", 5) == 0)&&(iDRAC_FLAG==0))  
        {
            ipmi_lcd_usage();
        }
        else 
        {
            ipmi_lcd_usage();
            return -1;
        }
    } 
    else 
    {
        ipmi_lcd_usage();
        return -1;
    }
    return(rc);
}



/*****************************************************************
* Function Name:      ipmi_lcd_get_platform_model_name
*
* Description: This function retrieves the platform model name, or any other parameter 
*              which stores  data in the same format
* Input:       intf         - pointer to interface
*              max_length   - length of the platform model string
*              field_type   - either hostname / platform model
* Output:      lcdstring    - hostname / platform model string
*
* Return:            
*
******************************************************************/ 
static int
ipmi_lcd_get_platform_model_name (void * intf, 
                          char* lcdstring, 
                                  uint8_t max_length, 
                                  uint8_t field_type)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE];
    int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[4];
    IPMI_DELL_LCD_STRING * lcdstringblock;
    int lcdstring_len = 0;
    int bytes_copied = 0;

    int ii;

    for (ii = 0; ii < 4; ii++)
    {
        int bytes_to_copy;
		memset (&req,0,sizeof(req));
        req.msg.netfn = IPMI_NETFN_APP;
        req.msg.lun = 0;
        req.msg.cmd = IPMI_GET_SYS_INFO;
        req.msg.data_len = 4;
        req.msg.data = data;
        data[0] = 0;                            /* get parameter*/
        data[1] = field_type;
        data[2] = ii;
        data[3] = 0;


	rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
	if (rv) {
	   printf("Error getting platform model name: ");
	   if (rv < 0) printf("no response\n");
	   else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv));
	   return rv;
        }

        lcdstringblock = (IPMI_DELL_LCD_STRING *) (void *) rsp;

        /* first block is different - 14 bytes*/
        if (0 == ii) {
            lcdstring_len = lcdstringblock->lcd_string.selector_0_string.length;

            lcdstring_len = MIN (lcdstring_len,max_length);

            bytes_to_copy = MIN(lcdstring_len, IPMI_DELL_LCD_STRING1_SIZE);
            memcpy (lcdstring, lcdstringblock->lcd_string.selector_0_string.data, bytes_to_copy);
        } else {
            int string_offset;

            bytes_to_copy = MIN(lcdstring_len - bytes_copied, IPMI_DELL_LCD_STRINGN_SIZE);
            if (bytes_to_copy < 1)
                break;
            string_offset = IPMI_DELL_LCD_STRING1_SIZE + IPMI_DELL_LCD_STRINGN_SIZE * (ii-1);
            memcpy (lcdstring+string_offset, lcdstringblock->lcd_string.selector_n_data, bytes_to_copy);
        }


        bytes_copied += bytes_to_copy;

        if (bytes_copied >= lcdstring_len)

            break;
    }
    return rv;
}

/*****************************************************************
* Function Name:    ipmi_idracvalidator_command
*
* Description:      This function returns the iDRAC6 type
* Input:            intf            - ipmi interface
* Output:       
*
* Return:           iDRAC6 type     1 - whoville 
*                                   0 - others
*
******************************************************************/

static int
ipmi_idracvalidator_command (void * intf)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE];
    int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[4];

    memset (&req,0,sizeof(req));
    req.msg.netfn = IPMI_NETFN_APP;
    req.msg.lun = 0;
    req.msg.cmd = IPMI_GET_SYS_INFO;
    req.msg.data_len = 4;
    req.msg.data = data;
    data[0] = 0;
    data[1] = IPMI_DELL_IDRAC_VALIDATOR;
    data[2] = 2;
    data[3] = 0;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv && fdebug) {
        printf(" Error getting IMC type");
        if (rv < 0) printf("no response\n");
        else printf("Completion Code 0x%02x\n", rv);
        return rv;
    }
    IMC_Type = rsp[10];
    if( (IMC_Type == IMC_IDRAC_11G_MONOLITHIC) || (IMC_Type == IMC_IDRAC_11G_MODULAR) )
    {
		iDRAC_FLAG=IDRAC_11G;
    }
    else if( (IMC_Type == IMC_IDRAC_12G_MONOLITHIC) || (IMC_Type == IMC_IDRAC_12G_MODULAR) )
    {
		iDRAC_FLAG=IDRAC_12G;
    }
    else
    {
        iDRAC_FLAG=0;
    }       
    
    return 0;
}

/*****************************************************************
* Function Name:    ipmi_lcd_get_configure_command_wh
*
* Description:      This function returns current lcd configuration for Dell OEM LCD command
* Input:            intf            - ipmi interface
* Global:           lcd_mode - lcd mode setting
* Output:    
*
* Return:           returns the current lcd configuration
*                   0 = User defined
*                   1 = Default
*                   2 = None
*
******************************************************************/ 
static int
ipmi_lcd_get_configure_command_wh (void * intf)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE];
    int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[4];

    req.msg.netfn = IPMI_NETFN_APP;
    req.msg.lun = 0;
    req.msg.cmd = IPMI_GET_SYS_INFO;
    req.msg.data_len = 4;
    req.msg.data = data;
    data[0] = 0;
    data[1] = IPMI_DELL_LCD_CONFIG_SELECTOR;
    data[2] = 0;
    data[3] = 0;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
        printf("Error getting LCD configuration: ");
        if (rv < 0) printf("no response\n");
        else printf("Completion Code 0x%02x\n", rv);
        return rv;
    }

    lcd_mode= *((LCD_MODE*)(&rsp[0]));
    return 0;
}


/*****************************************************************
* Function Name:    ipmi_lcd_get_configure_command
*
* Description:   This function returns current lcd configuration for Dell OEM LCD command
* Input:         intf            - ipmi interface
* Output:        command         - user defined / default / none / ipv4 / mac address / 
                 system name / service tag / ipv6 / temp / system watt / asset tag
*
* Return:             
*
******************************************************************/

static int
ipmi_lcd_get_configure_command (void * intf,
                                uint8_t *command)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE];
    int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[4];

    req.msg.netfn = IPMI_NETFN_APP;
    req.msg.lun = 0;
    req.msg.cmd = IPMI_GET_SYS_INFO;
    req.msg.data_len = 4;
    req.msg.data = data;
    data[0] = 0;
    data[1] = IPMI_DELL_LCD_CONFIG_SELECTOR;
    data[2] = 0;
    data[3] = 0;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
        printf("Error getting LCD configuration: ");
        if (rv < 0) printf("no response\n");
        else printf("Completion Code 0x%02x\n", rv);
        return rv;
    }

    /* rsp->data[0] is the rev */
    *command = rsp[1];

    return 0;
}

/*****************************************************************
* Function Name:    ipmi_lcd_set_configure_command
*
* Description:      This function updates current lcd configuration 
* Input:            intf            - ipmi interface
*                   command         - user defined / default / none / ipv4 / mac address / 
*                        system name / service tag / ipv6 / temp / system watt / asset tag
* Output:
* Return:             
*
******************************************************************/

static int
ipmi_lcd_set_configure_command (void * intf, int command)
{
#define LSCC_DATA_LEN 2

    uint8_t rsp[IPMI_RSPBUF_SIZE];
    int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[2];

    req.msg.netfn = IPMI_NETFN_APP;
    req.msg.lun = 0;
    req.msg.cmd = IPMI_SET_SYS_INFO;
    req.msg.data_len = 2;
    req.msg.data = data;
    data[0] = IPMI_DELL_LCD_CONFIG_SELECTOR;
    data[1] = command;                      /* command - custom, default, none */

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
        printf("Error setting LCD configuration: ");
        if (rv < 0) printf("no response\n");
        else printf("Completion Code 0x%02x\n", rv);
        return rv;
    }

    return 0;
}


/*****************************************************************
* Function Name:    ipmi_lcd_set_configure_command
*
* Description:      This function updates current lcd configuration 
* Input:            intf            - ipmi interface
*                   mode            - user defined / default / none 
*                   lcdqualifier   - lcd quallifier id
*                   errordisp       - error number
* Output:
* Return:                
*
******************************************************************/ 
static int
ipmi_lcd_set_configure_command_wh (void * intf, 
                                   uint32_t  mode,
                                   uint16_t lcdqualifier,
                                   uint8_t errordisp)
{
#define LSCC_DATA_LEN 2

    uint8_t rsp[IPMI_RSPBUF_SIZE];
    int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[13];

    ipmi_lcd_get_configure_command_wh(intf);
    req.msg.netfn = IPMI_NETFN_APP;
    req.msg.lun = 0;
    req.msg.cmd = IPMI_SET_SYS_INFO;
    req.msg.data_len = 13;
    req.msg.data = data;
    data[0] = IPMI_DELL_LCD_CONFIG_SELECTOR;

    if(mode!=0xFF)
    {

        data[1] = mode&0xFF;                    /* command - custom, default, none*/
        data[2]=(mode&0xFF00)>>8;
        data[3]=(mode&0xFF0000)>>16;
        data[4]=(mode&0xFF000000)>>24;
    }
    else
    {
        data[1] = (lcd_mode.lcdmode)&0xFF;                      /* command - custom, default, none*/
        data[2]=((lcd_mode.lcdmode)&0xFF00)>>8;
        data[3]=((lcd_mode.lcdmode)&0xFF0000)>>16;
        data[4]=((lcd_mode.lcdmode)&0xFF000000)>>24;
    }

    if(lcdqualifier!=0xFF)
    {
        if(lcdqualifier==0x01)
        {
            data[5] =(lcd_mode.lcdqualifier)|0x01;                 /* command - custom, default, none*/

        }
        else  if(lcdqualifier==0x00)
        {
            data[5] =(lcd_mode.lcdqualifier)&0xFE;                 /* command - custom, default, none*/
        }
        else if (lcdqualifier==0x03)
        {
            data[5] =(lcd_mode.lcdqualifier)|0x02;                 /* command - custom, default, none*/
        }
        else if (lcdqualifier==0x02)
        {
            data[5] =(lcd_mode.lcdqualifier)&0xFD; 
        }
    }
    else
    {
        data[5]=(uchar)lcd_mode.lcdqualifier;
    }   
    if(errordisp!=0xFF)
    {
        data[11]=errordisp;
    }
    else
    {
        data[11]=lcd_mode.error_display;
    }
    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
        printf("Error setting LCD configuration: ");
        if (rv < 0) printf("no response\n");
        else printf("Completion Code 0x%02x\n", rv);
        return rv;
    }

    return 0;
}



/*****************************************************************
* Function Name:    ipmi_lcd_get_single_line_text
*
* Description:    This function updates current lcd configuration 
* Input:          intf            - ipmi interface
*                 lcdstring       - new string to be updated 
*                 max_length      - length of the string
* Output:
* Return:              
*
******************************************************************/

static int
ipmi_lcd_get_single_line_text (void * intf, char* lcdstring, uint8_t max_length)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE];
    int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[4];
    IPMI_DELL_LCD_STRING * lcdstringblock;
    int lcdstring_len = 0;
    int bytes_copied = 0;
    int ii;

    for (ii = 0; ii < 4; ii++) {
        int bytes_to_copy;

        req.msg.netfn = IPMI_NETFN_APP;
        req.msg.lun = 0;
        req.msg.cmd = IPMI_GET_SYS_INFO;
        req.msg.data_len = 4;
        req.msg.data = data;
        data[0] = 0;                            /* get parameter*/
        data[1] = IPMI_DELL_LCD_STRING_SELECTOR;
        data[2] = ii;                           /* block selector*/
        data[3] = 00;                           /* set selector (n/a)*/

	rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
	if (rv) {
	   printf("Error getting text data: ");
	   if (rv < 0) printf("no response\n");
	   else printf("Completion Code 0x%02x\n", rv);
	   return rv;
	}

        lcdstringblock = (IPMI_DELL_LCD_STRING *) (void *) rsp;

        /* first block is different - 14 bytes*/
        if (0 == ii)
        {
            lcdstring_len = lcdstringblock->lcd_string.selector_0_string.length;

            if (lcdstring_len < 1 || lcdstring_len > max_length)
                break;

            bytes_to_copy = MIN(lcdstring_len, IPMI_DELL_LCD_STRING1_SIZE);
            memcpy (lcdstring, lcdstringblock->lcd_string.selector_0_string.data, bytes_to_copy);
        }
        else
        {
            int string_offset;

            bytes_to_copy = MIN(lcdstring_len - bytes_copied, IPMI_DELL_LCD_STRINGN_SIZE);
            if (bytes_to_copy < 1)
                break;
            string_offset = IPMI_DELL_LCD_STRING1_SIZE + IPMI_DELL_LCD_STRINGN_SIZE * (ii-1);
            memcpy (lcdstring+string_offset, lcdstringblock->lcd_string.selector_n_data, bytes_to_copy);
        }

        bytes_copied += bytes_to_copy;
        if (bytes_copied >= lcdstring_len)
            break;
    }
    return 0;
}

/*****************************************************************
* Function Name:    ipmi_lcd_get_info_wh
*
* Description:     This function prints current lcd configuration for whoville platform
* Input:           intf            - ipmi interface
* Output:
* Return:              
*
******************************************************************/

static int
ipmi_lcd_get_info_wh(void * intf)

{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[4];
    uint8_t command = 0;
    IPMI_DELL_LCD_CAPS* lcd_caps;
    char lcdstring[IPMI_DELL_LCD_STRING_LENGTH_MAX+1] = {0};
    int rc;


    printf("LCD info\n");

    if (ipmi_lcd_get_configure_command_wh (intf) != 0) 
    {
        return -1;
    }
    else 
    {
        if (lcd_mode.lcdmode== IPMI_DELL_LCD_CONFIG_DEFAULT) 
        {
            char text[IPMI_DELL_LCD_STRING_LENGTH_MAX+1] = {0};

            ipmi_lcd_get_platform_model_name(intf, text, 
                IPMI_DELL_LCD_STRING_LENGTH_MAX,
                IPMI_DELL_PLATFORM_MODEL_NAME_SELECTOR);

            if (text == NULL)
                return -1;
            printf("    Setting:Model name\n");
            printf("    Line 1:  %s\n", text);
        }
        else if (lcd_mode.lcdmode == IPMI_DELL_LCD_CONFIG_NONE) 
        {
            printf("    Setting:   none\n");
        }
        else if (lcd_mode.lcdmode == IPMI_DELL_LCD_CONFIG_USER_DEFINED) 
        {
            req.msg.netfn = IPMI_NETFN_APP;
            req.msg.lun = 0;
            req.msg.cmd = IPMI_GET_SYS_INFO;
            req.msg.data_len = 4;
            req.msg.data = data;
            data[0] = 0;                            /* get parameter*/
            data[1] = IPMI_DELL_LCD_GET_CAPS_SELECTOR;
            data[2] = 0;                            /* set selector (n/a)*/
            data[3] = 0;                            /* block selector (n/a)*/

            printf("    Setting: User defined\n");

            rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
        printf("Error getting LCD capabilities: ");
        if (rv < 0) printf("no response\n");
        else printf("Completion Code 0x%02x\n", rv);
        return rv;
    }

            lcd_caps = (IPMI_DELL_LCD_CAPS *)rsp;
            if (lcd_caps->number_lines > 0) 
            {
                memset(lcdstring, 0, IPMI_DELL_LCD_STRING_LENGTH_MAX+1);

                rc = ipmi_lcd_get_single_line_text (intf, lcdstring, lcd_caps->max_chars[0]);
                printf("    Text:    %s\n", lcdstring);
            }
            else 
            {
                printf("    No lines to show\n");
            }
        }
        else if (lcd_mode.lcdmode == IPMI_DELL_LCD_iDRAC_IPV4ADRESS) 
        {
            printf("    Setting:   IPV4 Address\n");
        }
        else if (lcd_mode.lcdmode == IPMI_DELL_LCD_IDRAC_MAC_ADDRESS) 
        {
            printf("    Setting:   MAC Address\n");
        }
        else if (lcd_mode.lcdmode == IPMI_DELL_LCD_OS_SYSTEM_NAME) 
        {
            printf("    Setting:   OS System Name\n");
        }
        else if (lcd_mode.lcdmode == IPMI_DELL_LCD_SERVICE_TAG) 
        {
            printf("    Setting:   System Tag\n");
        }
        else if (lcd_mode.lcdmode == IPMI_DELL_LCD_iDRAC_IPV6ADRESS) 
        {
            printf("    Setting:  IPV6 Address\n");
        }
        else if (lcd_mode.lcdmode == IPMI_DELL_LCD_AMBEINT_TEMP) 
        {
            printf("    Setting:  Ambient Temp\n");
            if(lcd_mode.lcdqualifier&0x02)
                printf("    Unit:  F\n");  
            else
                printf("    Unit:  C\n");  
        }
        else if (lcd_mode.lcdmode == IPMI_DELL_LCD_SYSTEM_WATTS)
        {
            printf("    Setting:  System Watts\n");

            if(lcd_mode.lcdqualifier&0x01)
                printf("    Unit:  BTU/hr\n");  
            else
                printf("    Unit:  Watt\n"); 

        }
        if(lcd_mode.error_display==IPMI_DELL_LCD_ERROR_DISP_SEL)
            printf("    Error Display:  SEL\n");
        else if(lcd_mode.error_display==IPMI_DELL_LCD_ERROR_DISP_VERBOSE)
            printf("    Error Display:  Simple\n");
    }

    return 0;
}

/*****************************************************************
* Function Name:    ipmi_lcd_get_info
*
* Description:      This function prints current lcd configuration for platform other than whoville
* Input:            intf            - ipmi interface
* Output:
* Return:              
*
******************************************************************/
static int ipmi_lcd_get_info(void * intf)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[4];
    IPMI_DELL_LCD_CAPS * lcd_caps;
    uint8_t command = 0;
    char lcdstring[IPMI_DELL_LCD_STRING_LENGTH_MAX+1] = {0};
    int rc; 

    printf("LCD info\n");

    if (ipmi_lcd_get_configure_command (intf, &command) != 0)
    {
        return -1;
    }
    else
    {
        if (command == IPMI_DELL_LCD_CONFIG_DEFAULT)
        {
            memset (lcdstring,0,IPMI_DELL_LCD_STRING_LENGTH_MAX+1);

            ipmi_lcd_get_platform_model_name(intf, lcdstring, IPMI_DELL_LCD_STRING_LENGTH_MAX,
                IPMI_DELL_PLATFORM_MODEL_NAME_SELECTOR);

            printf("    Setting: default\n");
            printf("    Line 1:  %s\n", lcdstring);
        }
        else if (command == IPMI_DELL_LCD_CONFIG_NONE)
        {
            printf("    Setting:   none\n");
        }
        else if (command == IPMI_DELL_LCD_CONFIG_USER_DEFINED)
        {
            req.msg.netfn = IPMI_NETFN_APP;
            req.msg.lun = 0;
            req.msg.cmd = IPMI_GET_SYS_INFO;
            req.msg.data_len = 4;
            req.msg.data = data;
            data[0] = 0;                            /* get parameter */
            data[1] = IPMI_DELL_LCD_GET_CAPS_SELECTOR;
            data[2] = 0;                            /* set selector (n/a) */
            data[3] = 0;                            /* block selector (n/a) */

            printf("    Setting: custom\n");

            rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
        printf("Error getting LCD capabilities: ");
        if (rv < 0) printf("no response\n");
        else printf("Completion Code 0x%02x\n", rv);
        return rv;
    }

            lcd_caps = (IPMI_DELL_LCD_CAPS *)(void *)rsp;
            if (lcd_caps->number_lines > 0)
            {
                memset (lcdstring,0,IPMI_DELL_LCD_STRING_LENGTH_MAX+1);
                rc = ipmi_lcd_get_single_line_text (intf, lcdstring, lcd_caps->max_chars[0]);
                printf("    Text:    %s\n", lcdstring);
            }
            else
            {
                printf("    No lines to show\n");
            }
        }
    }

    return 0;
}

/*****************************************************************
* Function Name:    ipmi_lcd_get_status_val
*
* Description:      This function gets current lcd configuration 
* Input:            intf            - ipmi interface
* Output:           lcdstatus       - KVM Status & Lock Status
* Return:           
*
******************************************************************/

static int
ipmi_lcd_get_status_val(void * intf, LCD_STATUS* lcdstatus)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[4];


    req.msg.netfn = IPMI_NETFN_APP;
    req.msg.lun = 0;
    req.msg.cmd = IPMI_GET_SYS_INFO;
    req.msg.data_len = 4;
    req.msg.data = data;
    data[0] = 0;                            /* get parameter */
    data[1] = IPMI_DELL_LCD_STATUS_SELECTOR;
    data[2] = 0;                            /* block selector */
    data[3] = 0;            
    /* set selector (n/a) */
    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
        printf("Error getting LCD status: ");
        if (rv < 0) printf("no response\n");
        else printf("Completion Code 0x%02x\n", rv);
        return rv;
    }

    /*lcdstatus= (LCD_STATUS* ) rsp->data; */

    lcdstatus->vKVM_status=rsp[1];
    lcdstatus->lock_status=rsp[2];

    return 0;
}


/*****************************************************************
* Function Name:    IsLCDSupported
*
* Description:   This function returns whether lcd supported or not
* Input:              
* Output:       
* Return:               
*
******************************************************************/
static int IsLCDSupported ()
{
    return LcdSupported;
}

/*****************************************************************
* Function Name:         CheckLCDSupport
*
* Description:  This function checks whether lcd supported or not
* Input:        intf            - ipmi interface
* Output:       
* Return:               
*
******************************************************************/
static void CheckLCDSupport(void * intf)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[4];

    LcdSupported = 0;

    req.msg.netfn = IPMI_NETFN_APP;
    req.msg.lun = 0;
    req.msg.cmd = IPMI_GET_SYS_INFO;
    req.msg.data_len = 4;
    req.msg.data = data;
    data[0] = 0;                            /* get parameter */
    data[1] = IPMI_DELL_LCD_STATUS_SELECTOR;
    data[2] = 0;                            /* block selector */
    data[3] = 0;            
    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) { return; }
    LcdSupported = 1;       

}

/*****************************************************************
* Function Name:     ipmi_lcd_status_print
*
* Description:    This function prints current lcd configuration KVM Status & Lock Status
* Input:          lcdstatus - KVM Status & Lock Status
* Output:   
* Return:               
*
******************************************************************/

static void ipmi_lcd_status_print( LCD_STATUS lcdstatus)
{
    switch (lcdstatus.vKVM_status)
    {
    case 0x00: 
        printf("LCD KVM Status :Inactive\n");
        break;
    case 0x01: 
        printf("LCD KVM Status :Active\n");
        break;
    default:
        printf("LCD KVM Status :Invalid Status\n");

        break;
    }                       

    switch (lcdstatus.lock_status)
    {
    case 0x00: 
        printf("LCD lock Status :View and modify\n");
        break;
    case 0x01: 
        printf("LCD lock Status :View only\n");
        break;
    case 0x02:
        printf("LCD lock Status :disabled\n");
        break;
    default:
        printf("LCD lock Status :Invalid\n");
        break;
    }

}

/*****************************************************************
* Function Name:     ipmi_lcd_get_status
*
* Description:      This function gets current lcd KVM active status & lcd access mode
* Input:            intf            - ipmi interface
* Output:       
* Return:           -1 on error
*                   0 if successful
*
******************************************************************/
static int
ipmi_lcd_get_status(void * intf )
{
    int rc=0;
    LCD_STATUS  lcdstatus;

    rc =ipmi_lcd_get_status_val( intf, &lcdstatus);
    if (rc <0)
        return -1;
    ipmi_lcd_status_print(lcdstatus);

    return rc;

}

/*****************************************************************
* Function Name:     ipmi_lcd_set_kvm
*
* Description:       This function sets lcd KVM active status 
* Input:             intf            - ipmi interface
*                    status  - Inactive / Active
* Output:    
* Return:            -1 on error
*                    0 if successful
*
******************************************************************/ 
static int
ipmi_lcd_set_kvm(void * intf, char status)
{
#define LSCC_DATA_LEN 2
    LCD_STATUS lcdstatus;
    int rc=0;
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[5];
    rc=ipmi_lcd_get_status_val(intf,&lcdstatus);
    if (rc < 0)
        return -1;
    req.msg.netfn = IPMI_NETFN_APP;
    req.msg.lun = 0;
    req.msg.cmd = IPMI_SET_SYS_INFO;
    req.msg.data_len = 5;
    req.msg.data = data;
    data[0] = IPMI_DELL_LCD_STATUS_SELECTOR;
    data[1] = status;                       /* active- incative*/
    data[2] = lcdstatus.lock_status;        /* full-veiw-locked */
    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
        printf("Error setting LCD status: ");
        if (rv < 0) printf("no response\n");
        else printf("Completion Code 0x%02x\n", rv);
        return rv;
    }

    return rc;
}

/*****************************************************************
* Function Name:   ipmi_lcd_set_lock
*
* Description:     This function sets lcd access mode 
* Input:           intf            - ipmi interface
*                  lock    - View and modify / View only / Diabled
* Output:        
* Return:          -1 on error
*                  0 if successful
*
******************************************************************/ 
static int
ipmi_lcd_set_lock(void * intf,  char lock)
{
#define LSCC_DATA_LEN 2
    LCD_STATUS lcdstatus;
    int rc =0;
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[5];
    rc=ipmi_lcd_get_status_val(intf,&lcdstatus);
    if (rc < 0)
        return -1;
    req.msg.netfn = IPMI_NETFN_APP;
    req.msg.lun = 0;
    req.msg.cmd = IPMI_SET_SYS_INFO;
    req.msg.data_len = 5;
    req.msg.data = data;
    data[0] = IPMI_DELL_LCD_STATUS_SELECTOR;
    data[1] = lcdstatus.vKVM_status;                        /* active- incative */
    data[2] = lock;                 /* full- veiw-locked */
    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
        printf("Error setting LCD status: ");
        if (rv < 0) printf("no response\n");
        else printf("Completion Code 0x%02x\n", rv);
        return rv;
    }

    return rc;
}

/*****************************************************************
* Function Name:   ipmi_lcd_set_single_line_text
*
* Description:    This function sets lcd line text
* Input:          intf            - ipmi interface
*                 text    - lcd string
* Output:   
* Return:         -1 on error
*                 0 if successful
*
******************************************************************/

static int 
ipmi_lcd_set_single_line_text (void * intf, char * text)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[18];
    int bytes_to_store = strlen(text);
    int bytes_stored = 0;
    int ii;
    int rc = 0;
    if (bytes_to_store>IPMI_DELL_LCD_STRING_LENGTH_MAX)
    {
        lprintf(LOG_ERR, " Out of range Max limit is 62 characters");
        return 1;

    }
    else
    {
        bytes_to_store = MIN(bytes_to_store, IPMI_DELL_LCD_STRING_LENGTH_MAX);
        for (ii = 0; ii < 4; ii++) {
            /*first block, 2 bytes parms and 14 bytes data*/
            if (0 == ii) {
                int size_of_copy =  
                    MIN((bytes_to_store - bytes_stored), IPMI_DELL_LCD_STRING1_SIZE);
                if (size_of_copy < 0)           /* allow 0 string length*/
                    break;
                req.msg.netfn = IPMI_NETFN_APP;
                req.msg.lun = 0;
                req.msg.cmd = IPMI_SET_SYS_INFO;
                req.msg.data_len = size_of_copy + 4; /* chars, selectors and sizes*/
                req.msg.data = data;
                data[0] = IPMI_DELL_LCD_STRING_SELECTOR;
                data[1] = ii;                           /* block number to use (0)*/
                data[2] = 0;                            /*string encoding*/
                data[3] = bytes_to_store;       /* total string length*/
                memcpy (data+4, text+bytes_stored, size_of_copy);
                bytes_stored += size_of_copy;
            } else {
                int size_of_copy =  
                    MIN((bytes_to_store - bytes_stored), IPMI_DELL_LCD_STRINGN_SIZE);
                if (size_of_copy <= 0)
                    break;
                req.msg.netfn = IPMI_NETFN_APP;
                req.msg.lun = 0;
                req.msg.cmd = IPMI_SET_SYS_INFO;
                req.msg.data_len = size_of_copy + 2;
                req.msg.data = data;
                data[0] = IPMI_DELL_LCD_STRING_SELECTOR;
                data[1] = ii;                           /* block number to use (1,2,3)*/
                memcpy (data+2, text+bytes_stored, size_of_copy);
                bytes_stored += size_of_copy;
            }

            rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
        printf("Error setting text data: ");
        if (rv < 0) printf("no response\n");
        else printf("Completion Code 0x%02x\n", rv);
        return rv;
    }
        }
    }
    return rc;
}

/*****************************************************************
* Function Name:   ipmi_lcd_set_text
*
* Description:     This function sets lcd line text
* Input:           intf            - ipmi interface
*                  text    - lcd string
*                  line_number- line number

* Output:       
* Return:          -1 on error
*                  0 if successful
*
******************************************************************/

static int
ipmi_lcd_set_text(void * intf, char * text, int line_number)
{
    int rc = 0;

    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[4];
    IPMI_DELL_LCD_CAPS * lcd_caps;

    req.msg.netfn = IPMI_NETFN_APP;
    req.msg.lun = 0;
    req.msg.cmd = IPMI_GET_SYS_INFO;
    req.msg.data_len = 4;
    req.msg.data = data;
    data[0] = 0;                            /* get parameter*/
    data[1] = IPMI_DELL_LCD_GET_CAPS_SELECTOR;
    data[2] = 0;                            /* set selector (n/a)*/
    data[3] = 0;                            /* block selector (n/a)*/

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
        printf("Error getting LCD capabilities: ");
        if (rv < 0) printf("no response\n");
        else printf("Completion Code 0x%02x\n", rv);
        return rv;
    }

    lcd_caps = (IPMI_DELL_LCD_CAPS *)(void *)rsp;

    if (lcd_caps->number_lines > 0) {
        rc = ipmi_lcd_set_single_line_text (intf, text);
    } else {
        lprintf(LOG_ERR, "LCD does not have any lines that can be set");
        rc = -1;
    }


    return rc;
}

/*****************************************************************
* Function Name:   ipmi_lcd_configure_wh
*
* Description:     This function updates the current lcd configuration
* Input:           intf            - ipmi interface
*                  lcdqualifier- lcd quallifier
*                  errordisp       - error number
*                  line_number-line number
*                  text            - lcd string
* Output:   
* Return:          -1 on error
*                  0 if successful
*
******************************************************************/

static int
ipmi_lcd_configure_wh (void * intf, uint32_t  mode ,
                       uint16_t lcdqualifier, uint8_t errordisp, 
                       int8_t line_number, char * text)
{
    int rc = 0;


    if (IPMI_DELL_LCD_CONFIG_USER_DEFINED == mode)
        /* Any error was reported earlier. */
        rc = ipmi_lcd_set_text(intf, text, line_number);


    if (rc == 0)

        rc = ipmi_lcd_set_configure_command_wh (intf, mode ,lcdqualifier,errordisp);

    return rc;
}


/*****************************************************************
* Function Name:   ipmi_lcd_configure
*
* Description:     This function updates the current lcd configuration
* Input:           intf            - ipmi interface
*                  command- lcd command
*                  line_number-line number
*                  text            - lcd string
* Output:   
* Return:          -1 on error
*                  0 if successful
*
******************************************************************/

static int
ipmi_lcd_configure (void * intf, int command, 
                    int8_t line_number, char * text)
{
    int rc = 0;

    if (IPMI_DELL_LCD_CONFIG_USER_DEFINED == command)
        rc = ipmi_lcd_set_text(intf, text, line_number);

    if (rc == 0)
        rc = ipmi_lcd_set_configure_command (intf, command);

    return rc;
}


/*****************************************************************
* Function Name:   ipmi_lcd_usage
*
* Description:   This function prints help message for lcd command
* Input:               
* Output:       
*
* Return:              
*
******************************************************************/

static void
ipmi_lcd_usage(void)
{
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "Generic DELL HW:");
    lprintf(LOG_NOTICE, "   lcd set {none}|{default}|{custom <text>}");
    lprintf(LOG_NOTICE, "      Set LCD text displayed during non-fault conditions");

    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "iDRAC 11g or iDRAC 12g:");
    lprintf(LOG_NOTICE, "   lcd set {mode}|{lcdqualifier}|{errordisplay}");
    lprintf(LOG_NOTICE, "      Allows you to set the LCD mode and user-definedstring.");
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   lcd set mode {none}|{modelname}|{ipv4address}|{macaddress}|");
    lprintf(LOG_NOTICE, "   {systemname}|{servicetag}|{ipv6address}|{ambienttemp}");
    lprintf(LOG_NOTICE, "   {systemwatt }|{assettag}|{userdefined}<text>");
    lprintf(LOG_NOTICE, "         Allows you to set the LCD display mode to any of the preceding parameters");
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   lcd set lcdqualifier {watt}|{btuphr}|{celsius}|{fahrenheit}");
    lprintf(LOG_NOTICE, "      Allows you to set the unit for the system ambient temperature mode.");
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   lcd set errordisplay {sel}|{simple}");
    lprintf(LOG_NOTICE, "      Allows you to set the error display.");
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   lcd info");
    lprintf(LOG_NOTICE, "      Show LCD text that is displayed during non-fault conditions");
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   lcd set vkvm{active}|{inactive}");
    lprintf(LOG_NOTICE, "           Set vKVM active and inactive, message will be displayed on lcd"); 
    lprintf(LOG_NOTICE, " when vKVM is active and vKVM session is in progress");
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   lcd set frontpanelaccess {viewandmodify}|{viewonly}|{disabled}");
    lprintf(LOG_NOTICE, "      Set LCD mode to view and modify, view only or disabled ");
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   lcd status");
    lprintf(LOG_NOTICE, "           Show LCD Status for vKVM display<active|inactive>");
    lprintf(LOG_NOTICE, "   and Front Panel access mode {viewandmodify}|{viewonly}|{disabled} ");
    lprintf(LOG_NOTICE, "");
}

/*****************************************************************
* Function Name:       ipmi_delloem_mac_main
*
* Description:         This function processes the delloem mac command
* Input:               intf    - ipmi interface
                       argc    - no of arguments
                       argv    - argument string array
* Output:        
*
* Return:              return code     0 - success
*                         -1 - failure
*
******************************************************************/


static int ipmi_delloem_mac_main (void * intf, int  argc, char ** argv)
{
    int rc = 0;
    int currIdInt = -1;

    current_arg++;
    if (argc > 1 && strcmp(argv[current_arg], "help") == 0)
    {
        ipmi_mac_usage();
        return 0;
    }
    ipmi_idracvalidator_command(intf);
    if (argc == 1) /*( || (strncmp(argv[current_arg], "list\0", 5) == 0) )*/ 
    {
        rc = ipmi_macinfo(intf, 0xff);
    }
    else if (strncmp(argv[current_arg], "get\0", 4) == 0)
    {
        int currIdInt;
        current_arg++;
        if (argv[current_arg] == NULL)
        {
            ipmi_mac_usage();
            return -1;
        }
        if(make_int(argv[current_arg],&currIdInt) < 0) {
            lprintf(LOG_ERR, "Invalid NIC number. The NIC number should be between 0-8\n");
            return -1;
        }
        if( (currIdInt > 8) || (currIdInt < 0) )
        {
            lprintf(LOG_ERR, "Invalid NIC number. The NIC number should be between 0-8\n");
            return -1;
        }
        rc = ipmi_macinfo(intf, currIdInt);
    }
    else
    {
        ipmi_mac_usage();
    }
    return(rc);
}


/*****************************************************************
* Function Name:     make_int
*
* Description:   This function convert string into integer
* Input:         str     - decimal number string
* Output:        value   - integer value
* Return:                
*
******************************************************************/
static int make_int(const char *str, int *value)
{
    char *tmp=NULL;
    *value = (int)strtol(str,&tmp,0);
    if ( tmp-str != strlen(str) )
    {
        return -1;
    }
    return 0;
}





EmbeddedNICMacAddressType EmbeddedNICMacAddress;

EmbeddedNICMacAddressType_10G EmbeddedNICMacAddress_10G;

static void InitEmbeddedNICMacAddressValues ()
{
    uint8_t i;
    uint8_t j;


    for (i=0;i<MAX_LOM;i++)
    {
#ifdef LOM_OLD
        EmbeddedNICMacAddress.LOMMacAddress[i].BladSlotNumber = 0;
        EmbeddedNICMacAddress.LOMMacAddress[i].MacType = LOM_MACTYPE_RESERVED;
        EmbeddedNICMacAddress.LOMMacAddress[i].EthernetStatus = LOM_ETHERNET_RESERVED;
        EmbeddedNICMacAddress.LOMMacAddress[i].NICNumber = 0;
        EmbeddedNICMacAddress.LOMMacAddress[i].Reserved = 0;
#else
	EmbeddedNICMacAddress.LOMMacAddress[i].b0 = 0xF0;
	EmbeddedNICMacAddress.LOMMacAddress[i].b1 = 0x00;
#endif
        for (j=0;j<MACADDRESSLENGH;j++)
        {
            EmbeddedNICMacAddress.LOMMacAddress[i].MacAddressByte[j] = 0;
            EmbeddedNICMacAddress_10G.MacAddress[i].MacAddressByte[j] = 0;
        }
    }
}

uint8_t UseVirtualMacAddress = 0;
#define VIRTUAL_MAC_OFFSET (2)
static int ipmi_macinfo_drac_idrac_virtual_mac(void* intf,uint8_t NicNum)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req;

    uint8_t msg_data[30];
    uint8_t VirtualMacAddress [MACADDRESSLENGH];
    uint8_t input_length=0;
    uint8_t j;
    //uint8_t length;
    uint8_t i;


    if (0xff==NicNum || IDRAC_NIC_NUMBER==NicNum )
    {
        UseVirtualMacAddress = 0;

        input_length = 0;
        msg_data[input_length++] = 1; /*Get*/

      	req.msg.netfn = IPMI_DELL_OEM_NETFN;
        req.msg.lun = 0;                
        req.msg.cmd = GET_IDRAC_VIRTUAL_MAC;
        req.msg.data = msg_data;
        req.msg.data_len = input_length;

        rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
	if (rv) { return rv; }

        if( (IMC_IDRAC_12G_MODULAR == IMC_Type) || (IMC_IDRAC_12G_MONOLITHIC== IMC_Type) ) {
           // Get the Chasiss Assigned MAC Addresss        for 12g Only
           memcpy(VirtualMacAddress,&rsp[1],MACADDRESSLENGH);

           for (i=0;i<MACADDRESSLENGH;i++)
           {
              if (0 != VirtualMacAddress [i])
              {
                 UseVirtualMacAddress = 1;
              }
           }
           // Get the Server Assigned MAC Addresss for 12g Only
           if(!UseVirtualMacAddress) {
              memcpy(VirtualMacAddress,&rsp[1+MACADDRESSLENGH],MACADDRESSLENGH);

              for (i=0;i<MACADDRESSLENGH;i++)
              {
                 if (0 != VirtualMacAddress [i])
                 {
                    UseVirtualMacAddress = 1;
                 }
              }
           }
        } else {
           memcpy(VirtualMacAddress,&rsp[VIRTUAL_MAC_OFFSET],MACADDRESSLENGH);

           for (i=0;i<MACADDRESSLENGH;i++)
           {
              if (0 != VirtualMacAddress [i])
              {
                UseVirtualMacAddress = 1;
              }       
           }
	}
        if (0 == UseVirtualMacAddress)
            return -1;              
        if (IMC_IDRAC_10G == IMC_Type)
            printf ("\nDRAC MAC Address ");
        else if ( (IMC_IDRAC_11G_MODULAR == IMC_Type) || (IMC_IDRAC_11G_MONOLITHIC== IMC_Type) )
            printf ("\niDRAC6 MAC Address ");
        else if ( (IMC_IDRAC_12G_MODULAR == IMC_Type) || (IMC_IDRAC_12G_MONOLITHIC== IMC_Type) )
            printf ("\niDRAC7 MAC Address ");

        for (j=0;j<5;j++)
            printf("%02x:",VirtualMacAddress[j]);
        printf("%02x",VirtualMacAddress[j]); /*5*/

        printf ("\n\r");        

    }  
    return 0;
}


/*****************************************************************
* Function Name:    ipmi_macinfo_drac_idrac_mac
*
* Description:      This function retrieves the mac address of DRAC or iDRAC
* Input:            NicNum
* Output:                 
* Return:               
*
******************************************************************/

static int ipmi_macinfo_drac_idrac_mac(void* intf,uint8_t NicNum)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req;

    uint8_t msg_data[30];
    uint8_t input_length=0;
    uint8_t iDRAC6MacAddressByte[MACADDRESSLENGH];
    uint8_t j;

    ipmi_macinfo_drac_idrac_virtual_mac (intf,NicNum);


    if ((0xff==NicNum || IDRAC_NIC_NUMBER==NicNum) && 0 == UseVirtualMacAddress)
    {

        input_length = 0;

        msg_data[input_length++] = LAN_CHANNEL_NUMBER; 
        msg_data[input_length++] = MAC_ADDR_PARAM;  
        msg_data[input_length++] = 0x00;                        
        msg_data[input_length++] = 0x00;                        

        req.msg.netfn = TRANSPORT_NETFN;
        req.msg.lun = 0;                
        req.msg.cmd = GET_LAN_PARAM_CMD;
        req.msg.data = msg_data;
        req.msg.data_len = input_length;

        rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
	if (rv) {
            printf(" Error in getting MAC Address: ");
	    if (rv < 0) printf("no response\n");
	    else printf("Completion Code 0x%02x\n", rv);
	    return rv;
        }

        memcpy(iDRAC6MacAddressByte,&rsp[PARAM_REV_OFFSET],MACADDRESSLENGH);

        if (IMC_IDRAC_10G == IMC_Type)
            printf ("\n\rDRAC MAC Address ");
		else if ((IMC_IDRAC_11G_MODULAR == IMC_Type) || (IMC_IDRAC_11G_MONOLITHIC== IMC_Type))
			printf ("\n\riDRAC6 MAC Address ");
		else if ((IMC_IDRAC_12G_MODULAR == IMC_Type) || (IMC_IDRAC_12G_MONOLITHIC== IMC_Type))		
			printf ("\n\riDRAC7 MAC Address ");
        else
            printf ("\n\riDRAC6 MAC Address ");

        for (j=0;j<5;j++)
            printf("%02x:",iDRAC6MacAddressByte[j]);
        printf("%02x",iDRAC6MacAddressByte[j]);

        printf ("\n\r");        
    }
    return 0;
}


/*****************************************************************
* Function Name:    ipmi_macinfo_10g
*
* Description:      This function retrieves the mac address of LOMs
* Input:            intf      - ipmi interface
                    NicNum    - NIC number
* Output:               
* Return:               
*
******************************************************************/

static int ipmi_macinfo_10g (void* intf, uint8_t NicNum)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req;

    uint8_t msg_data[30];
    uint8_t input_length=0;

    uint8_t j;
    uint8_t i;

    uint8_t Total_No_NICs = 0;


    InitEmbeddedNICMacAddressValues ();

    memset(msg_data, 0, sizeof(msg_data));
    input_length = 0;
    msg_data[input_length++] = 0x00; /* Get Parameter Command */
    msg_data[input_length++] = EMB_NIC_MAC_ADDRESS_9G_10G;  /* OEM Param */

    msg_data[input_length++] = 0x00;         
    msg_data[input_length++] = 0x00;         

    memset(&req, 0, sizeof(req));

    req.msg.netfn = APP_NETFN;
    req.msg.lun = 0;                
    req.msg.cmd = GET_SYSTEM_INFO_CMD;
    req.msg.data = msg_data;


    req.msg.data_len = input_length;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
            printf(" Error in getting MAC Address: ");
	    if (rv < 0) printf("no response\n");
	    else printf("Completion Code 0x%02x\n", rv);
	    return rv;
    }
    if (fdebug) dump_buf("GetMacResp_10G",rsp,rsp_len,0);

    Total_No_NICs = (uint8_t) rsp[PARAM_REV_OFFSET]; /* Byte 1: Total Number of Embedded NICs */

    if (IDRAC_NIC_NUMBER != NicNum)
    {
        if (0xff == NicNum)
        {
            printf ("\n\rSystem LOMs");
        }       
        printf("\n\rNIC Number\tMAC Address\n\r");

        memcpy(&EmbeddedNICMacAddress_10G,&rsp[PARAM_REV_OFFSET+TOTAL_N0_NICS_INDEX],Total_No_NICs* MACADDRESSLENGH);


        /*Read the LOM type and Mac Addresses */

        for (i=0;i<Total_No_NICs;i++)
        {
            if ((0xff==NicNum) || (i == NicNum)     )
            {       
                printf ("\n\r%d",i);
                printf ("\t\t");
                for (j=0;j<5;j++)
                {
                    printf("%02x:",EmbeddedNICMacAddress_10G.MacAddress[i].MacAddressByte[j]);
                }       
                printf("%02x",EmbeddedNICMacAddress_10G.MacAddress[i].MacAddressByte[j]);
            }               
        }
        printf ("\n\r");

    }

    ipmi_macinfo_drac_idrac_mac(intf,NicNum);


    return 0;
}


/*****************************************************************
* Function Name:      ipmi_macinfo_11g
*
* Description:        This function retrieves the mac address of LOMs
* Input:              intf - ipmi interface
* Output:               
* Return:               
*
******************************************************************/

static int ipmi_macinfo_11g (void* intf, uint8_t NicNum)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req;
    uint8_t msg_data[30];
    uint8_t input_length=0;
    uint8_t len;
    uint8_t j;
    uint8_t offset;
    uint8_t maxlen;
    uint8_t loop_count;
    uint8_t i;
    uint8_t lom_mactype;
    uint8_t lom_nicnum;
    uint8_t lom_ethstat;
    uint8_t *lom_mac;
    // uint8_t LOMStatus = 0;
    // uint8_t PlayingDead = 0;

    offset = 0;
    len = 8; /*eigher 8 or 16 */
    maxlen = 64;
    loop_count = maxlen / len;

    InitEmbeddedNICMacAddressValues ();

    memset(msg_data, 0, sizeof(msg_data));
    input_length = 0;
    msg_data[input_length++] = 0x00; /* Get Parameter Command */
    msg_data[input_length++] = EMB_NIC_MAC_ADDRESS_11G;      /* OEM Param */

    msg_data[input_length++] = 0x00;      
    msg_data[input_length++] = 0x00;      
    msg_data[input_length++] = 0x00;      
    msg_data[input_length++] = 0x00;      

    memset(&req, 0, sizeof(req));

    req.msg.netfn = APP_NETFN;
    req.msg.lun = 0;              
    req.msg.cmd = GET_SYSTEM_INFO_CMD;
    req.msg.data = msg_data;


    req.msg.data_len = input_length;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
            printf(" Error in getting MAC Address: ");
	    if (rv < 0) printf("no response\n");
	    else printf("Completion Code 0x%02x\n", rv);
	    return rv;
    }

    len = 8; /*eigher 8 or 16 */
    maxlen = (uint8_t) rsp[0+PARAM_REV_OFFSET];
    loop_count = maxlen / len;

    if (IDRAC_NIC_NUMBER != NicNum)
    {
        if (0xff == NicNum)
        {
            printf ("\n\rSystem LOMs");
        }       
        printf("\n\rNIC Number\tMAC Address\t\tStatus\n\r");


        /*Read the LOM type and Mac Addresses */
        offset=0;
        for (i=0;i<loop_count;i++,offset=offset+len)
        {
            input_length = 4;
            msg_data[input_length++] = offset;
            msg_data[input_length++] = len;   

            req.msg.netfn = APP_NETFN;
            req.msg.lun = 0;
            req.msg.cmd = GET_SYSTEM_INFO_CMD;
            req.msg.data = msg_data;
            req.msg.data_len = input_length;

            rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
	    if (rv) {
		printf(" Error in getting MAC Address: ");
		if (rv < 0) printf("no response\n");
		else printf("Completion Code 0x%02x\n", rv);
		return rv;
	    }
	    if (fdebug) {
		printf("ipmi_macinfo_11g(%d) i=%d offset=%d\n",NicNum,i,offset);
		dump_buf("GetMacResp",rsp,rsp_len,0);
	    }

            memcpy(&(EmbeddedNICMacAddress.LOMMacAddress[i]),&rsp[PARAM_REV_OFFSET],len);

#ifdef LOM_OLD
	    lom_ethstat = EmbeddedNICMacAddress.LOMMacAddress[i].EthernetStatus;
	    lom_mactype = EmbeddedNICMacAddress.LOMMacAddress[i].MacType;
	    lom_nicnum  = EmbeddedNICMacAddress.LOMMacAddress[i].NICNumber;
	    lom_mac     = &EmbeddedNICMacAddress.LOMMacAddress[i].MacAddressByte[0];
#else
	    lom_ethstat = ((EmbeddedNICMacAddress.LOMMacAddress[i].b0 & 0xc0) >> 6);
	    lom_mactype = ((EmbeddedNICMacAddress.LOMMacAddress[i].b0 & 0x30) >> 4);
	    /* lom_bladslot = (b0 & 0x0f); */
	    lom_nicnum  = (EmbeddedNICMacAddress.LOMMacAddress[i].b1 & 0x1f);
	    lom_mac     = &EmbeddedNICMacAddress.LOMMacAddress[i].MacAddressByte[0];
	    if (fdebug) {
		printf("\n\rlom_ethstat=%x lom_mactype=%x lom_nicnum=%x\n",
			lom_ethstat,lom_mactype,lom_nicnum);
		printf("MacAdrB=%02x:%02x:%02x:%02x:%02x:%02x\n",
		     lom_mac[0], lom_mac[1], lom_mac[2],
		     lom_mac[3], lom_mac[4], lom_mac[5]);
		printf("\n\rrsp_mac=%02x:%02x:%02x:%02x:%02x:%02x\n",
		     rsp[3], rsp[4], rsp[5], rsp[6], rsp[7], rsp[8]);
	    }
	    lom_mac     = &rsp[3];
#endif

            if (LOM_MACTYPE_ETHERNET == lom_mactype)
            {

                if (  (0xff==NicNum) || (NicNum == lom_nicnum)  )
                {
                    printf ("\n\r%d",lom_nicnum);
                    printf ("\t\t");
                    for (j=0;j<5;j++)
                        printf("%02x:",lom_mac[j]);
                    printf("%02x",lom_mac[j]);

                    if (LOM_ETHERNET_ENABLED == lom_ethstat)
                        printf ("\tEnabled");
                    else
                        printf ("\tDisabled");
                }
            }

        }         
        printf ("\n\r");

    }

    ipmi_macinfo_drac_idrac_mac(intf,NicNum);

    return 0;

}     



/*****************************************************************
* Function Name:      ipmi_macinfo
*
* Description:     This function retrieves the mac address of LOMs
* Input:           intf   - ipmi interface
* Output:               
* Return:               
*
******************************************************************/

static int ipmi_macinfo (void* intf, uint8_t NicNum)
{
    if (IMC_IDRAC_10G == IMC_Type)
    {
        return ipmi_macinfo_10g (intf,NicNum);
    }
	else if ((IMC_IDRAC_11G_MODULAR == IMC_Type || IMC_IDRAC_11G_MONOLITHIC== IMC_Type )  ||
			(IMC_IDRAC_12G_MODULAR == IMC_Type || IMC_IDRAC_12G_MONOLITHIC== IMC_Type ) )
    {
        return ipmi_macinfo_11g (intf,NicNum);
    }
    else
    {
        lprintf(LOG_ERR, " Error in getting MAC Address : Not supported platform");
        return 0;
    }       
}


/*****************************************************************
* Function Name:     ipmi_mac_usage
*
* Description:   This function prints help message for mac command
* Input:               
* Output:       
*
* Return:              
*
******************************************************************/

static void
ipmi_mac_usage(void)
{
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   mac list");
    lprintf(LOG_NOTICE, "      Lists the MAC address of LOMs");
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   mac get <NIC number>");
    lprintf(LOG_NOTICE, "      Shows the MAC address of specified LOM. 0-7 System LOM, 8- DRAC/iDRAC.");
    lprintf(LOG_NOTICE, "");
}

/*****************************************************************
* Function Name:       ipmi_delloem_lan_main
*
* Description:         This function processes the delloem lan command
* Input:               intf    - ipmi interface
                       argc    - no of arguments
                       argv    - argument string array
* Output:        
*
* Return:              return code     0 - success
*                         -1 - failure
*
******************************************************************/

static int ipmi_delloem_lan_main (void * intf, int  argc, char ** argv)
{
    int rc = 0;

    int nic_selection = 0;
    char nic_set[2] = {0};
    current_arg++;
    if (argv[current_arg] == NULL || strcmp(argv[current_arg], "help") == 0)
    {
        ipmi_lan_usage();
        return 0;
    }
    ipmi_idracvalidator_command(intf);
    if (!IsLANSupported())
    {
        printf("lan is not supported on this system.\n");
        return -1;
    }               
    else if (strncmp(argv[current_arg], "set\0", 4) == 0)
    {
        current_arg++;
        if (argv[current_arg] == NULL)
        {
            ipmi_lan_usage();
            return -1;
        }
		if(iDRAC_FLAG == IDRAC_12G) {
			nic_selection = get_nic_selection_mode_12g(intf,current_arg,argv,nic_set);
			if (INVALID == nic_selection)
			{
				ipmi_lan_usage();
				return -1;
                        } else if(INVAILD_FAILOVER_MODE == nic_selection) {
                                printf(INVAILD_FAILOVER_MODE_STRING);
                                return 0;
                        } else if(INVAILD_FAILOVER_MODE_SETTINGS == nic_selection){
                                printf(INVAILD_FAILOVER_MODE_SET);
                                return 0;
                        } else if(INVAILD_SHARED_MODE == nic_selection){
                                printf(INVAILD_SHARED_MODE_SET_STRING);
                                return 0;
			}				
		
			rc = ipmi_lan_set_nic_selection_12g(intf,nic_set);
		}
		else
		{
        	  nic_selection = get_nic_selection_mode(current_arg,argv);

        	  if (INVALID == nic_selection)
        	  {
        	    ipmi_lan_usage();
        	    return -1;
        	  }
        	  if(IMC_IDRAC_11G_MODULAR == IMC_Type) {
        	    printf(INVAILD_SHARED_MODE_SET_STRING);
        	    return 0;
        	  }
        	  rc = ipmi_lan_set_nic_selection(intf,nic_selection);
		}		
        return 0;                       
    }
    else if (strncmp(argv[current_arg], "get\0", 4) == 0)
    {
        current_arg++;
        if (argv[current_arg] == NULL)
        {
            rc = ipmi_lan_get_nic_selection(intf);
            return rc;
        }
        else if (strncmp(argv[current_arg], "active\0", 7) == 0)                
        {
            rc = ipmi_lan_get_active_nic(intf);
            return rc;
        }
        else
        {
            ipmi_lan_usage();
        }

    }
    else
    {
        ipmi_lan_usage();
        return -1;
    }
    return(rc);
}


static int IsLANSupported ()
{
    if (IMC_IDRAC_11G_MODULAR == IMC_Type)
        return 0;
    return 1;
}


int get_nic_selection_mode_12g (void* intf,int current_arg, char ** argv, char *nic_set)
{
	int nic_selection_mode = 0;
	int failover = 0;

	// First get the current settings.
	uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
	struct ipmi_rq req;

	uint8_t msg_data[30];
	uint8_t input_length=0;
	
	input_length = 0;
		
   	req.msg.netfn = IPMI_DELL_OEM_NETFN;
   	req.msg.lun = 0;		
	
  	req.msg.cmd = GET_NIC_SELECTION_12G_CMD;

  	req.msg.data = msg_data;
  	req.msg.data_len = input_length;
  
	rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
	if (rv) {
            printf(" Error in getting NIC selection: ");
	    if (rv < 0) printf("no response\n");
	    else printf("Completion Code 0x%02x %s\n",
				rv,decode_cc(0,rv));
	    return rv;
	}
	
	nic_set[0] = rsp[0];
	nic_set[1] = rsp[1];

	
	if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "dedicated\0", 10)) 
	{
		nic_set[0] = 1;
		nic_set[1] = 0;
		return 0;
	}
	if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "shared\0", 7)) 
	{
		
	}
	else
		return INVALID;
	
	current_arg++;	
	if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "with\0", 5)) 
	{
	}	
	else
		return INVALID;		
	
	current_arg++;	
	if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "failover\0", 9)) 
	{
		failover = 1;
	}	
	if(failover)
		current_arg++;	
	if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "lom1\0", 5)) 
	{
                if(IMC_IDRAC_12G_MODULAR == IMC_Type)
                {
                        return INVAILD_SHARED_MODE;
                }
		if(failover) {
                        if(nic_set[0] == 2)
                        {
                                return INVAILD_FAILOVER_MODE;
                        } else if(nic_set[0] == 1) {
                                return INVAILD_FAILOVER_MODE_SETTINGS;
                        }
			nic_set[1] = 2;
		}	
		else {
			nic_set[0] = 2;
                        if(nic_set[1] == 2)
                                nic_set[1] = 0;
		}	
		return 0;
	}
	else if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "lom2\0", 5)) 
	{
                if(IMC_IDRAC_12G_MODULAR == IMC_Type)
                {
                        return INVAILD_SHARED_MODE;
                }
		if(failover) {		
			if(nic_set[0] == 3)
                        {
                                return INVAILD_FAILOVER_MODE;
                        } else if(nic_set[0] == 1) {
                                return INVAILD_FAILOVER_MODE_SETTINGS;
                        }
			nic_set[1] = 3;
		}	
		else {
			nic_set[0] = 3;
			if(nic_set[1] == 3)
			        nic_set[1] = 0;

		}	
		return 0;
	}
	else if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "lom3\0", 5)) 
	{
                if(IMC_IDRAC_12G_MODULAR == IMC_Type)
                {
                        return INVAILD_SHARED_MODE;
                }
		if(failover) {	
                        if(nic_set[0] == 4)
                        {
                                return INVAILD_FAILOVER_MODE;
                        } else if(nic_set[0] == 1) {
                                return INVAILD_FAILOVER_MODE_SETTINGS;
                        }
			nic_set[1] = 4;
		}	
		else {
			nic_set[0] = 4;
                        if(nic_set[1] == 4)
                                nic_set[1] = 0;
 	}	
		return 0;
	} 
	else if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "lom4\0", 5)) 
	{
                if(IMC_IDRAC_12G_MODULAR == IMC_Type)
                {
                        return INVAILD_SHARED_MODE;
                }
		if(failover) {	
                        if(nic_set[0] == 5)
                        {
                                return INVAILD_FAILOVER_MODE;
                        } else if(nic_set[0] == 1) {
                                return INVAILD_FAILOVER_MODE_SETTINGS;
                        }
			nic_set[1] = 5;
		}	
		else {
			nic_set[0] = 5;
                        if(nic_set[1] == 5)
                                nic_set[1] = 0;
		}	
		return 0;
	}	
	else if (failover && NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "none\0", 5)) 
	{
		if(IMC_IDRAC_12G_MODULAR == IMC_Type)
		{
		        return INVAILD_SHARED_MODE;
		}
		if(failover) {
			if(nic_set[0] == 1) {
				return INVAILD_FAILOVER_MODE_SETTINGS;
			}
			nic_set[1] = 0;
		}	
		return 0;
	}	
	else if (failover && NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "all\0", 4)) 
	{
	}	
	else
		return INVALID;	
	
	current_arg++;	
	if (failover && NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "loms\0", 5)) 
	{
		if(IMC_IDRAC_12G_MODULAR == IMC_Type)
		{
			return INVAILD_SHARED_MODE;
		}
		if(nic_set[0] == 1) {
			return INVAILD_FAILOVER_MODE_SETTINGS;
		}
		nic_set[1] = 6;
		return 0;
	}	

	return INVALID;
	
}


static int get_nic_selection_mode (int current_arg, char ** argv)
{
    int nic_selection_mode = 0;
    if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "dedicated\0", 10)) 
    {
        return DEDICATED;
    }
    if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "shared\0", 7)) 
    {
        if (NULL == argv[current_arg+1] )
            return SHARED;          
    }
    current_arg++;  
    if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "with\0", 5)) 
    {
    }       
    else
        return INVALID;         

    current_arg++;  
    if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "failover\0", 9)) 
    {
    }       
    else
        return INVALID;         

    current_arg++;  
    if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "lom2\0", 5)) 
    {
        return SHARED_WITH_FAILOVER_LOM2;
    }       
    else if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "all\0", 4)) 
    {
    }       
    else
        return INVALID; 

    current_arg++;  
    if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "loms\0", 5)) 
    {
        return SHARED_WITH_FAILOVER_ALL_LOMS;
    }       

    return INVALID;
	
}


static int ipmi_lan_set_nic_selection_12g (void* intf, uint8_t* nic_selection)
{
	uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
	struct ipmi_rq req;

	uint8_t msg_data[30];
	uint8_t input_length=0;

	input_length = 0;
		
	msg_data[input_length++] = nic_selection[0]; 
	msg_data[input_length++] = nic_selection[1]; 

	req.msg.netfn = IPMI_DELL_OEM_NETFN;
	req.msg.lun = 0;		
	req.msg.cmd = SET_NIC_SELECTION_12G_CMD;
	req.msg.data = msg_data;
	req.msg.data_len = input_length;
  
	rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
	if (rv) {
            printf(" Error in setting NIC selection: ");
	    if (rv < 0) printf("no response\n");
	    else printf("Completion Code 0x%02x %s\n",
				rv,decode_cc(0,rv));
	    return rv;
	}
	printf("configured successfully");

	return 0;
}


static int ipmi_lan_set_nic_selection (void* intf, uint8_t nic_selection)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req;

    uint8_t msg_data[30];
    uint8_t input_length=0;
    //uint8_t j;

    input_length = 0;

    msg_data[input_length++] = nic_selection; 

   	req.msg.netfn = IPMI_DELL_OEM_NETFN;
    req.msg.lun = 0;                
    req.msg.cmd = SET_NIC_SELECTION_CMD;
    req.msg.data = msg_data;
    req.msg.data_len = input_length;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
            printf(" Error in setting NIC selection: ");
	    if (rv < 0) printf("no response\n");
	    else printf("Completion Code 0x%02x %s\n",
				rv,decode_cc(0,rv));
	    return rv;
    }
    printf("configured successfully");

    return 0;
}      

static int ipmi_lan_get_nic_selection (void* intf)
{
    uint8_t nic_selection=-1;
	uint8_t nic_selection_failover = 0;

    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req;

    uint8_t msg_data[30];
    uint8_t input_length=0;
    //uint8_t j;

    input_length = 0;

    req.msg.netfn = IPMI_DELL_OEM_NETFN;
    req.msg.lun = 0;                
    if(iDRAC_FLAG == IDRAC_12G)
  	req.msg.cmd = GET_NIC_SELECTION_12G_CMD;
    else  	
        req.msg.cmd = GET_NIC_SELECTION_CMD;
    req.msg.data = msg_data;
    req.msg.data_len = input_length;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
            printf(" Error in getting NIC selection: ");
	    if (rv < 0) printf("no response\n");
	    else printf("Completion Code 0x%02x %s\n",
				rv,decode_cc(0,rv));
	    return rv;
    }
    nic_selection = rsp[0];

	if(iDRAC_FLAG == IDRAC_12G)
	{		
		
		nic_selection_failover = rsp[1];
		if ((nic_selection < 6) && (nic_selection > 0) && (nic_selection_failover < 7))
		{
			if(nic_selection == 1) {
				printf ("%s\n",NIC_Selection_Mode_String_12g[nic_selection-1]);
			} else if(nic_selection) {
				printf ("Shared LOM   :  %s\n",NIC_Selection_Mode_String_12g[nic_selection-1]);
				if(nic_selection_failover  == 0)
					printf ("Failover LOM :  None\n");
				else if(nic_selection_failover   >= 2 && nic_selection_failover   <= 6)
					printf ("Failover LOM :  %s\n",NIC_Selection_Mode_String_12g[nic_selection_failover + 3]);
			}
				
		} 
		else
		{
			lprintf(LOG_ERR, " Error Outof bond Value received (%d) (%d) \n",nic_selection,nic_selection_failover);
		  	return -1;	  	
		}
	}
	else
	{
		printf ("%s\n",NIC_Selection_Mode_String[nic_selection]);
	}

    return 0;
}      

static int ipmi_lan_get_active_nic (void* intf)
{
    uint8_t active_nic=0;
    uint8_t current_lom =0;

    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req;

    uint8_t msg_data[30];
    uint8_t input_length=0;

    input_length = 0;

    msg_data[input_length++] = 0; /*Get current LOM*/
    msg_data[input_length++] = 0; /*Reserved*/
    msg_data[input_length++] = 0; /*Reserved*/        

    req.msg.netfn = IPMI_DELL_OEM_NETFN;
    req.msg.lun = 0;                
    req.msg.cmd = GET_ACTIVE_NIC_CMD;
    req.msg.data = msg_data;
    req.msg.data_len = input_length;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
            printf(" Error in getting Current LOM Status: ");
	    if (rv < 0) printf("no response\n");
	    else printf("Completion Code 0x%02x %s\n",
				rv,decode_cc(0,rv));
	    return rv;
    }
    current_lom = rsp[0];

    input_length = 0;

    msg_data[input_length++] = 1; //Get Link status
    msg_data[input_length++] = 0; //Reserved
    msg_data[input_length++] = 0; //Reserved

    req.msg.netfn = IPMI_DELL_OEM_NETFN;
    req.msg.lun = 0;
    req.msg.cmd = GET_ACTIVE_NIC_CMD;
    req.msg.data = msg_data;
    req.msg.data_len = input_length;
    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
            printf(" Error in getting Active LOM Status: ");
	    if (rv < 0) printf("no response\n");
	    else printf("Completion Code 0x%02x %s\n",
				rv,decode_cc(0,rv));
	    return rv;
    }

    active_nic = rsp[1];
    if (current_lom < 5 && active_nic)
        printf ("\n%s\n",AciveLOM_String[current_lom]);
    else
        printf ("\n%s\n",AciveLOM_String[5]);

    return 0;
}


static void
ipmi_lan_usage(void)
{
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   lan set <Mode> ");
    lprintf(LOG_NOTICE, "      sets the NIC Selection Mode :");
    lprintf(LOG_NOTICE, "          on iDRAC12g :");

    lprintf(LOG_NOTICE, "              dedicated, shared with lom1, shared with lom2,shared with lom3,shared ");
    lprintf(LOG_NOTICE, "              with lom4,shared with failover lom1,shared with failover lom2,shared ");
    lprintf(LOG_NOTICE, "              with failover lom3,shared with failoverlom4,shared with Failover all ");
    lprintf(LOG_NOTICE, "              loms, shared with Failover None).");
    lprintf(LOG_NOTICE, "          on other systems :");
    lprintf(LOG_NOTICE, "              dedicated, shared, shared with failoverlom2,");
    lprintf(LOG_NOTICE, "              shared with Failover all loms.");
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   lan get ");
    lprintf(LOG_NOTICE, "          on iDRAC12g :");
    lprintf(LOG_NOTICE, "              returns the current NIC Selection Mode (dedicated, shared with lom1, shared ");
    lprintf(LOG_NOTICE, "              with lom2, shared with lom3, shared with lom4,shared with failover lom1,");
    lprintf(LOG_NOTICE, "              shared with failover lom2,shared with failover lom3,shared with failover ");
    lprintf(LOG_NOTICE, "              lom4,shared with Failover all loms,shared with Failover None).");
    lprintf(LOG_NOTICE, "          on other systems :");
    lprintf(LOG_NOTICE, "              dedicated, shared, shared with failover,");
    lprintf(LOG_NOTICE, "              lom2, shared with Failover all loms.");
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   lan get active");
    lprintf(LOG_NOTICE, "      Get the current active LOMs (LOM1, LOM2, LOM3, LOM4, NONE).");
    lprintf(LOG_NOTICE, "");

}

/*****************************************************************
* Function Name:       ipmi_delloem_powermonitor_main
*
* Description:         This function processes the delloem powermonitor command
* Input:               intf    - ipmi interface
                       argc    - no of arguments
                       argv    - argument string array
* Output:        
*
* Return:              return code     0 - success
*                         -1 - failure
*
******************************************************************/

static int ipmi_delloem_powermonitor_main (void * intf, int  argc, char ** argv)
{
    int rc = 0;

    current_arg++;
    if (argc > 1 && strcmp(argv[current_arg], "help") == 0)
    {
        ipmi_powermonitor_usage();
        return 0;
    }
    ipmi_idracvalidator_command(intf);
    if (argc == 1)
    {
        rc = ipmi_powermgmt(intf);
    }
    else if (strncmp(argv[current_arg], "status\0", 7) == 0) 
    {
        rc = ipmi_powermgmt(intf);
    }

    else if (strncmp(argv[current_arg], "clear\0", 6) == 0) 
    {
        current_arg++;
        if (argv[current_arg] == NULL) 
        {
            ipmi_powermonitor_usage();
            return -1;
        }
        else if (strncmp(argv[current_arg], "peakpower\0", 10) == 0) 
        {
            rc = ipmi_powermgmt_clear(intf, 1);
        }
        else if (strncmp(argv[current_arg], "cumulativepower\0", 16) == 0) 
        {
            rc = ipmi_powermgmt_clear(intf, 0);
        }
        else 
        {
            ipmi_powermonitor_usage();
            return -1;
        }

    }


    else if (strncmp(argv[current_arg], "powerconsumption\0", 17) == 0) 
    {
        current_arg++;

        if (argv[current_arg] == NULL)
        {

            rc=ipmi_print_get_power_consmpt_data(intf,watt);

        }
        else if (strncmp(argv[current_arg], "watt\0", 5) == 0) 
        {

            rc = ipmi_print_get_power_consmpt_data(intf, watt);
        }
        else if (strncmp(argv[current_arg], "btuphr\0", 7) == 0) 
        {
            rc = ipmi_print_get_power_consmpt_data(intf, btuphr);
        }
        else
        {
            ipmi_powermonitor_usage();
            return -1;
        }
    }
    else if (strncmp(argv[current_arg], "powerconsumptionhistory\0", 23) == 0) 
    {
        current_arg++;
        if (argv[current_arg] == NULL)
        {
            rc=ipmi_print_power_consmpt_history(intf,watt);

        }
        else if (strncmp(argv[current_arg], "watt\0", 5) == 0) 
        {
            rc = ipmi_print_power_consmpt_history(intf, watt);
        }
        else if (strncmp(argv[current_arg], "btuphr\0", 7) == 0)
        {
            rc = ipmi_print_power_consmpt_history(intf, btuphr);
        }
        else
        {
            ipmi_powermonitor_usage();
            return -1;
        }

    }

    else if (strncmp(argv[current_arg], "getpowerbudget\0", 15) == 0)
    {
        current_arg++;
        if (argv[current_arg] == NULL)
        {
            rc=ipmi_print_power_cap(intf,watt);

        }
        else if (strncmp(argv[current_arg], "watt\0", 5) == 0)
        {
            rc = ipmi_print_power_cap(intf, watt);
        }
        else if (strncmp(argv[current_arg], "btuphr\0", 7) == 0)
        {
            rc = ipmi_print_power_cap(intf, btuphr);
        }
        else
        {
            ipmi_powermonitor_usage();
            return -1;
        }

    }

    else if (strncmp(argv[current_arg], "setpowerbudget\0", 15) == 0)
    {
        int val;
        current_arg++;
        if (argv[current_arg] == NULL)
        { 
            ipmi_powermonitor_usage();
            return -1;
        }
		if (strchr(argv[current_arg], '.'))
		{
			lprintf(LOG_ERR, " Cap value in Watts, Btu/hr or percent should be whole number");
			return -1;
		}
        make_int(argv[current_arg],&val);
        current_arg++;
        if (argv[current_arg] == NULL)
        {       
            ipmi_powermonitor_usage();
        }
        else if (strncmp(argv[current_arg], "watt\0", 5) == 0)
        {
            rc=ipmi_set_power_cap(intf,watt,val);
        }
        else if (strncmp(argv[current_arg], "btuphr\0", 7) == 0)
        {
            rc=ipmi_set_power_cap(intf, btuphr,val);
        }
        else if (strncmp(argv[current_arg], "percent\0", 8) == 0)
        {
            rc=ipmi_set_power_cap(intf,percent,val);
        }
        else
        {
            ipmi_powermonitor_usage();
            return -1;
        }

    }

    else if (strncmp(argv[current_arg], "enablepowercap\0", 15) == 0)
    {
        rc = ipmi_set_power_capstatus_command(intf,1);
    }

    else if (strncmp(argv[current_arg], "disablepowercap\0", 16) == 0)
    {
        rc = ipmi_set_power_capstatus_command(intf,0);
    }
    else
    {
        ipmi_powermonitor_usage();
        return -1;
    }
    if (sdrcache != NULL) free_sdr_cache(sdrcache); 
    return(rc);
}


/*****************************************************************
* Function Name:     ipmi_time_to_str
*
* Description:       This function converts ipmi time format into gmtime format
* Input:             rawTime  - ipmi time format 
* Output:            strTime  - gmtime format
*
* Return:              
*
******************************************************************/

static void
ipmi_time_to_str(time_t rawTime, char* strTime)
{
    struct tm * tm;
    char *temp;
    tm = gmtime(&rawTime);

    temp = asctime(tm);

    strcpy(strTime,temp);
}

/*****************************************************************
* Function Name:      ipmi_get_sensor_reading
*
* Description:        This function retrieves a raw sensor reading
* Input:              sensorOwner       - sensor owner id
*                     sensorNumber      - sensor id
*                     intf              - ipmi interface
* Output:             sensorReadingData - ipmi response structure
* Return:             1 on error
*                     0 if successful
*
******************************************************************/
static int
ipmi_get_sensor_reading(void *intf ,
                unsigned char sensorNumber,
                        SensorReadingType* pSensorReadingData)
{
    struct ipmi_rq req;
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len;
    int rc = 0;
    // uint8_t save_addr;

    memset(&req, 0, sizeof (req));
    req.msg.netfn = IPMI_NETFN_SE;
    req.msg.lun = 0;
    req.msg.cmd = (uint8_t)(GET_SENSOR_READING | 0x0ff);
    req.msg.data = &sensorNumber;
    req.msg.data_len = 1;

    if (NULL == pSensorReadingData)
        return -1;
    memset(pSensorReadingData,0, sizeof(SensorReadingType));        

    rc = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rc) return 1; 

    memcpy(pSensorReadingData, rsp, sizeof(SensorReadingType));

    /* if sensor messages are disabled, return error*/
    if ((!(rsp[1]& 0xC0)) || ((rsp[1] & 0x20))) {
        rc =1;
    }
    return rc;
}


/*****************************************************************
* Function Name:   ipmi_get_power_capstatus_command
*
* Description:     This function gets the power cap status
* Input:           intf                 - ipmi interface
* Global:          PowercapSetable_flag - power cap status
* Output:                
*
* Return:              
*
******************************************************************/
static int
ipmi_get_power_capstatus_command (void * intf)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[2];

    req.msg.netfn = IPMI_DELL_OEM_NETFN;
    req.msg.lun = 0;
    req.msg.cmd = IPMI_DELL_POWER_CAP_STATUS;
    req.msg.data_len = 2;
    req.msg.data = data;
    data[0] = 01;
    data[1] = 0xFF;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
            printf(" Error getting powercap status: ");
	    if (rv < 0) printf("no response\n");
	    else printf("Completion Code 0x%02x %s\n",
				rv,decode_cc(0,rv));
	    return rv;
    }
    if (rsp[0]&0x02)
        PowercapSetable_flag=1;
    if(rsp[0]&0x01)
        PowercapstatusFlag=1;
    return 0;
}

/*****************************************************************
* Function Name:    ipmi_set_power_capstatus_command
*
* Description:      This function sets the power cap status
* Input:            intf     - ipmi interface
*                   val      - power cap status
* Output:            
*
* Return:              
*
******************************************************************/

static int
ipmi_set_power_capstatus_command (void * intf,uint8_t val)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[2];
	if(ipmi_get_power_capstatus_command(intf) < 0)
		return -1;

    if (PowercapSetable_flag!=1)
    {
        lprintf(LOG_ERR, " Can not set powercap on this system");
        return -1;
    }
    req.msg.netfn = IPMI_DELL_OEM_NETFN;
    req.msg.lun = 0;
    req.msg.cmd = IPMI_DELL_POWER_CAP_STATUS;
    req.msg.data_len = 2;
    req.msg.data = data;

    data[0] = 00;
    data[1] = val;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
         printf(" Error setting powercap status: ");
	 if (rv < 0) printf("no response\n");
	 else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) {
		printf("FM001 : A required license is missing or expired\n");
		return rv;	//return unlicensed Error code
	 } 
	 else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv));
	 return rv;
    }

    return 0;
}



/*****************************************************************
* Function Name:    ipmi_powermgmt
*
* Description:      This function print the powermonitor details
* Input:            intf     - ipmi interface
* Output:              
*
* Return:              
*
******************************************************************/
static int ipmi_powermgmt(void* intf)
{
    time_t now;
    struct tm* tm;
    char* dte;

    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req;
    uint8_t msg_data[2];
    uint32_t cumStartTimeConv;
    uint32_t cumReadingConv;
    uint32_t maxPeakStartTimeConv;
    uint32_t ampPeakTimeConv;
    uint16_t ampReadingConv;
    uint32_t wattPeakTimeConv;
    uint32_t wattReadingConv;
    uint32_t bmctimeconv;
    uint32_t * bmctimeconvval;

    IPMI_POWER_MONITOR* pwrMonitorInfo;


    char cumStartTime[26];
    char maxPeakStartTime[26];
    char ampPeakTime[26];
    char wattPeakTime[26];
    char bmctime[26];

    // float cumReading;
    int ampReading;
    int wattReading;
    int ampReadingRemainder;
    // int round;
    // int round2;
    int remainder;

    now = time(0);
    tm = gmtime(&now);
    dte = asctime(tm);

    memset(&req, 0, sizeof(req));
    req.msg.netfn = IPMI_NETFN_STORAGE;
    req.msg.lun = 0;
    req.msg.cmd = IPMI_CMD_GET_SEL_TIME;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
        printf(" Error getting BMC time info ");
	if (rv < 0) printf("no response\n");
	else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv));
	return rv;
    }
    bmctimeconvval=(uint32_t*)rsp;
#if WORDS_BIGENDIAN
    bmctimeconv=BSWAP_32(*bmctimeconvval);
#else
    bmctimeconv=*bmctimeconvval;
#endif

    /* get powermanagement info*/
    req.msg.netfn = IPMI_DELL_OEM_NETFN;
    req.msg.lun = 0x0;
    req.msg.cmd = GET_PWRMGMT_INFO_CMD;
    req.msg.data = msg_data;
    req.msg.data_len = 2;

    memset(msg_data, 0, 2);
    msg_data[0] = 0x07;     
    msg_data[1] = 0x01;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
	printf(" Error getting power management info ");
	if (rv < 0) printf("no response\n");
	else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) {
		printf("FM001 : A required license is missing or expired\n");
		return rv;	
	} 
	else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv));
	return rv;
    }

    pwrMonitorInfo = (IPMI_POWER_MONITOR*)rsp;

#if WORDS_BIGENDIAN
    cumStartTimeConv = BSWAP_32(pwrMonitorInfo->cumStartTime);
    cumReadingConv = BSWAP_32(pwrMonitorInfo->cumReading);
    maxPeakStartTimeConv = BSWAP_32(pwrMonitorInfo->maxPeakStartTime);
    ampPeakTimeConv = BSWAP_32(pwrMonitorInfo->ampPeakTime);
    ampReadingConv = BSWAP_16(pwrMonitorInfo->ampReading);
    wattPeakTimeConv = BSWAP_32(pwrMonitorInfo->wattPeakTime);
    wattReadingConv = BSWAP_16(pwrMonitorInfo->wattReading);
#else
    cumStartTimeConv = pwrMonitorInfo->cumStartTime;
    cumReadingConv = pwrMonitorInfo->cumReading;
    maxPeakStartTimeConv = pwrMonitorInfo->maxPeakStartTime;
    ampPeakTimeConv = pwrMonitorInfo->ampPeakTime;
    ampReadingConv = pwrMonitorInfo->ampReading;
    wattPeakTimeConv = pwrMonitorInfo->wattPeakTime;
    wattReadingConv = pwrMonitorInfo->wattReading;
#endif

    ipmi_time_to_str(cumStartTimeConv, cumStartTime);

    ipmi_time_to_str(maxPeakStartTimeConv, maxPeakStartTime);
    ipmi_time_to_str(ampPeakTimeConv, ampPeakTime);
    ipmi_time_to_str(wattPeakTimeConv, wattPeakTime);
    ipmi_time_to_str(bmctimeconv, bmctime);

    now = time(0);


    remainder = (cumReadingConv % 1000);
    cumReadingConv = cumReadingConv / 1000;
    remainder = (remainder + 50) / 100;

    ampReading = ampReadingConv;
    ampReadingRemainder = ampReading%10;
    ampReading = ampReading/10;

    wattReading = wattReadingConv;

    printf("Power Tracking Statistics\n");
    printf("Statistic      : Cumulative Energy Consumption\n");
    printf("Start Time     : %s", cumStartTime);
    printf("Finish Time    : %s", bmctime);
    printf("Reading        : %d.%d kWh\n\n", cumReadingConv, remainder);

    printf("Statistic      : System Peak Power\n");
    printf("Start Time     : %s", maxPeakStartTime);
    printf("Peak Time      : %s", wattPeakTime);
    printf("Peak Reading   : %d W\n\n", wattReading);

    printf("Statistic      : System Peak Amperage\n");
    printf("Start Time     : %s", maxPeakStartTime);
    printf("Peak Time      : %s", ampPeakTime);
    printf("Peak Reading   : %d.%d A\n", ampReading, ampReadingRemainder);


    return 0;

}
/*****************************************************************
* Function Name:    ipmi_powermgmt_clear
*
* Description:     This function clears peakpower / cumulativepower value
* Input:           intf           - ipmi interface
*                  clearValue     - peakpower / cumulativepower
* Output:          
*
* Return:              
*
******************************************************************/
static int
ipmi_powermgmt_clear(void* intf,uint8_t clearValue)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req;
    uint8_t clearType;
    uint8_t msg_data[3];

    if (clearValue) {
        clearType = 2;
    } else {
        clearType = 1;
    }

    /* clear powermanagement info*/
    req.msg.netfn = IPMI_DELL_OEM_NETFN;
    req.msg.lun = 0;
    req.msg.cmd = CLEAR_PWRMGMT_INFO_CMD;
    req.msg.data = msg_data;
    req.msg.data_len = 3;


    memset(msg_data, 0, 3);
    msg_data[0] = 0x07;
    msg_data[1] = 0x01;
    msg_data[2] = clearType;


    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
	printf(" Error clearing power values: ");
	if (rv < 0) printf("no response\n");
	else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) {
		printf("FM001 : A required license is missing or expired\n");
		return rv;	
	} 
	else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv));
	return rv;
    }
	return 0;

}

/*****************************************************************
* Function Name:    watt_to_btuphr_conversion
*
* Description:      This function converts the power value in watt to btuphr
* Input:            powerinwatt     - power in watt
*                               
* Output:           power in btuphr
*
* Return:              
*
******************************************************************/
static uint64_t watt_to_btuphr_conversion(uint32_t powerinwatt)
{
    uint64_t powerinbtuphr;
    powerinbtuphr=(uint64_t)(3.413*powerinwatt);

    return(powerinbtuphr);
}

/*****************************************************************
* Function Name:    btuphr_to_watt_conversion
*
* Description:      This function converts the power value in  btuphr to watt
* Input:            powerinbtuphr   - power in btuphr
*                              
* Output:           power in watt
*
* Return:                
*
******************************************************************/
static uint32_t btuphr_to_watt_conversion(uint64_t powerinbtuphr)
{
    uint32_t powerinwatt;
    /*returning the floor value*/
    powerinwatt= (uint32_t)(powerinbtuphr/3.413);
    return (powerinwatt);
}

/*****************************************************************
* Function Name:        ipmi_get_power_headroom_command
*
* Description:          This function prints the Power consumption information
* Input:                intf    - ipmi interface
*                       unit    - watt / btuphr
* Output:           
*
* Return:              
*
******************************************************************/
static int ipmi_get_power_headroom_command (void * intf,uint8_t unit)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint64_t peakpowerheadroombtuphr;
    uint64_t instantpowerhearoom;

    req.msg.netfn = IPMI_DELL_OEM_NETFN;
    req.msg.lun = 0;
    req.msg.cmd = GET_PWR_HEADROOM_CMD;
    req.msg.data_len = 0;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
	printf(" Error getting power headroom status: ");
	if (rv < 0) printf("no response\n");
	else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) {
		printf("FM001 : A required license is missing or expired\n");
		return rv;	
	}
	else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv));
	return rv;
    }
    if(verbose>1)
        printf("power headroom  Data               : %x %x %x %x ",
        /*need to look into */                                                                  rsp[0], rsp[1], rsp[2], rsp[3]);
    powerheadroom= *(( POWER_HEADROOM *)rsp);
#if WORDS_BIGENDIAN
    powerheadroom.instheadroom = BSWAP_16(powerheadroom.instheadroom);
    powerheadroom.peakheadroom = BSWAP_16(powerheadroom.peakheadroom);
#endif

    printf ("Headroom\n\r");
    printf ("Statistic                     Reading\n\r");   

    if(unit == btuphr)
    {
        peakpowerheadroombtuphr=watt_to_btuphr_conversion(powerheadroom.peakheadroom);
        instantpowerhearoom= watt_to_btuphr_conversion(powerheadroom.instheadroom);

        printf ("System Instantaneous Headroom : %ld BTU/hr\n",instantpowerhearoom);
		printf ("System Peak Headroom          : %ld BTU/hr\n",peakpowerheadroombtuphr);
	}
	else
	{
        printf ("System Instantaneous Headroom : %ld W\n",powerheadroom.instheadroom);
		printf ("System Peak Headroom          : %ld W\n",powerheadroom.peakheadroom);
	}

    return 0;
}

/*****************************************************************
* Function Name:       ipmi_get_power_consumption_data
*
* Description:         This function updates the instant Power consumption information
* Input:               intf - ipmi interface
* Output:              power consumption current reading 
*                      Assumption value will be in Watt.
*
* Return:               
*
******************************************************************/
static int ipmi_get_power_consumption_data(void* intf,uint8_t unit)
{
    int rc = 0;
    SensorReadingType sensorReadingData;
    uint8_t rsp[IPMI_RSPBUF_SIZE]; 
    struct sdr_record_list *sdr = NULL;
    uchar sdrbuf[SDR_SZ];
    double readingf, warningf, failuref;
    int readingbtuphr=0;
    int warning_threshbtuphr=0;
    int failure_thresbtuphr=0;
    int status=0;
    int sensor_number = 0;

    if (sdrfile != NULL) {
        rc = get_sdr_file(sdrfile,&sdrcache);
        if (rc) printf ("Error 0x%02x: Cannot get SDRs from %s\n",rc,sdrfile);
    } else if (sdrcache == NULL) {
	rc = get_sdr_cache(&sdrcache);
        if (rc) printf ("Error 0x%02x: Cannot get SDRs\n",rc);
    }

    rc = find_sdr_by_tag(sdrbuf, sdrcache, "System Level", fdebug);
    if (rc != 0)
    {
        printf ("Error %d: Cannot access the System Level sensor data\n",rc);
        return rc;
    }
    sdr = (struct sdr_record_list *)sdrbuf;

    sensor_number = sdrbuf[7]; // sdr->record.full->keys.sensor_num;
    if (fdebug) printf("calling GetSensorReading(%x)\n",sensor_number);
    rc = GetSensorReading(sensor_number, sdrbuf, 
			  (uchar *)&sensorReadingData.sensorReading);
    if (rc != 0) 
	printf("Error %d getting sensor %x reading\n",rc,sensor_number);

    rc = GetSensorThresholds( sensor_number, rsp);
    if (fdebug) printf("GetSensorThresholds(%x) rc = %d\n",sensor_number,rc);
    if (rc == 0)
    {   
        readingf = RawToFloat(sensorReadingData.sensorReading,sdrbuf);
        warningf = RawToFloat(rsp[4], sdrbuf);
        failuref = RawToFloat(rsp[5], sdrbuf);
        readingbtuphr = (int)readingf;
        warning_threshbtuphr = (int)warningf;
        failure_thresbtuphr = (int)failuref;

	if (fdebug) {
	   printf("Reading 0x%02x = %.2f, Warning 0x%02x = %.2f, Failure 0x%02x = %.2f\n",
		sensorReadingData.sensorReading, readingf,
		rsp[4], warningf, rsp[5], failuref);
	}

        printf ("System Board System Level\n\r");
        if (unit==btuphr)
        {
            readingbtuphr= watt_to_btuphr_conversion(readingbtuphr);
            warning_threshbtuphr= watt_to_btuphr_conversion(warning_threshbtuphr);
            failure_thresbtuphr= watt_to_btuphr_conversion( failure_thresbtuphr);

            printf ("Reading                : %d BTU/hr\n",readingbtuphr);
            printf ("Warning threshold      : %d BTU/hr\n",warning_threshbtuphr);
            printf ("Failure threshold      : %d BTU/hr\n",failure_thresbtuphr);
        }
        else
        {
            printf ("Reading                : %d W \n",readingbtuphr);              
            printf ("Warning threshold      : %d W \n",(warning_threshbtuphr));
            printf ("Failure threshold      : %d W \n",(failure_thresbtuphr));
        }
    }
    else
    {
        printf ("Error %d: Cannot access the System Level threshold data\n",rc);
        return -1;              
    }       
    return status;
}




/*****************************************************************
* Function Name:      ipmi_get_instan_power_consmpt_data
*
* Description:        This function updates the instant Power consumption information
* Input:              intf - ipmi interface
* Output:             instpowerconsumptiondata - instant Power consumption information
*
* Return:              
*
******************************************************************/

static int ipmi_get_instan_power_consmpt_data(void* intf,
                                              IPMI_INST_POWER_CONSUMPTION_DATA* instpowerconsumptiondata)
{

    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req={0};

    uint8_t msg_data[2];


    /*get instantaneous power consumption command*/
    req.msg.netfn = IPMI_DELL_OEM_NETFN;
    req.msg.lun = 0;
    req.msg.cmd = GET_PWR_CONSUMPTION_CMD;

    req.msg.data = msg_data;
    req.msg.data_len = 2;



    memset(msg_data, 0, 2);

    msg_data[0] = 0x0A;     
    msg_data[1] = 0x00;


    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
	printf(" Error getting power consumption data: ");
	if (rv < 0) printf("no response\n");
	else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) {
		printf("FM001 : A required license is missing or expired\n");
		return rv;	
	} 
	else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv));
	return rv;
    }

    * instpowerconsumptiondata = * ( (IPMI_INST_POWER_CONSUMPTION_DATA*) (rsp));
#if WORDS_BIGENDIAN
    instpowerconsumptiondata->instanpowerconsumption = BSWAP_16(instpowerconsumptiondata->instanpowerconsumption);
    instpowerconsumptiondata->instanApms = BSWAP_16(instpowerconsumptiondata->instanApms);
    instpowerconsumptiondata->resv1 = BSWAP_16(instpowerconsumptiondata->resv1);
#endif

    return 0;


}


/*****************************************************************
* Function Name:      ipmi_print_get_instan_power_Amps_data
*
* Description:        This function prints the instant Power consumption information
* Input:              instpowerconsumptiondata - instant Power consumption information
* Output:               
*
* Return:              
*
******************************************************************/
static void ipmi_print_get_instan_power_Amps_data(IPMI_INST_POWER_CONSUMPTION_DATA instpowerconsumptiondata)
{
    uint16_t intampsval=0;
    uint16_t decimalampsval=0;


    if (instpowerconsumptiondata.instanApms>0)
    {
        decimalampsval=(instpowerconsumptiondata.instanApms%10);
        intampsval=instpowerconsumptiondata.instanApms/10;
    }
    printf("\nAmperage value: %d.%d A \n",intampsval,decimalampsval);
}
/*****************************************************************
* Function Name:     ipmi_print_get_power_consmpt_data
*
* Description:       This function prints the Power consumption information
* Input:             intf            - ipmi interface
*                    unit            - watt / btuphr 
* Output:               
*
* Return:              
*
******************************************************************/
static int ipmi_print_get_power_consmpt_data(void* intf,uint8_t  unit)
{

    int rc = 0;
    IPMI_INST_POWER_CONSUMPTION_DATA instpowerconsumptiondata = {0,0,0,0};
    // int i;
    //uint16_t inputwattageL=0;
    //int sensorIndex = 0;
    //uint32_t readingbtuphr;
    //uint32_t warning_threshbtuphr;
    //uint32_t failure_thresbtuphr;

    printf ("\nPower consumption information\n");


    rc=ipmi_get_power_consumption_data(intf,unit);
    if (-1 == rc)
        return rc;

    rc=ipmi_get_instan_power_consmpt_data(intf,&instpowerconsumptiondata);
    if (-1 == rc)
        return rc;

    ipmi_print_get_instan_power_Amps_data(instpowerconsumptiondata);


    rc=ipmi_get_power_headroom_command(intf,unit);      

    if (-1 == rc)
        return rc;

    return rc;


}


/*****************************************************************
* Function Name:   ipmi_get_avgpower_consmpt_history
*
* Description:     This function updates the average power consumption information
* Input:           intf            - ipmi interface
* Output:          pavgpower- average power consumption information
*
* Return:              
*
******************************************************************/
static int ipmi_get_avgpower_consmpt_history(void* intf,IPMI_AVGPOWER_CONSUMP_HISTORY* pavgpower )
{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[4];

    req.msg.netfn = IPMI_NETFN_APP;
    req.msg.lun = 0;
    req.msg.cmd = IPMI_GET_SYS_INFO;
    req.msg.data_len = 4;
    req.msg.data = data;
    data[0] = 0;
    data[1] = 0xeb;
    data[2] = 0;
    data[3] = 0;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
	printf(" Error getting average power consumption data: ");
	if (rv < 0) printf("no response\n");
	else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) {
		printf("FM001 : A required license is missing or expired\n");
		return rv;	
	}
	else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv));
	return rv;
    }

    if (verbose > 1)
    {
        printf("Average power consumption history  Data               :%x %x %x %x %x %x %x\n\n",
            rsp[0], rsp[1], rsp[2], rsp[3], 
            rsp[4], rsp[5], rsp[6], rsp[7]);

    }

    *pavgpower = *( (IPMI_AVGPOWER_CONSUMP_HISTORY*) rsp);
#if WORDS_BIGENDIAN
    pavgpower->lastminutepower = BSWAP_16(pavgpower->lastminutepower);
    pavgpower->lasthourpower = BSWAP_16(pavgpower->lasthourpower);
    pavgpower->lastdaypower = BSWAP_16(pavgpower->lastdaypower);
    pavgpower->lastweakpower = BSWAP_16(pavgpower->lastweakpower);
#endif

    return 0;
}

/*****************************************************************
* Function Name:    ipmi_get_peakpower_consmpt_history
*
* Description:      This function updates the peak power consumption information
* Input:            intf            - ipmi interface
* Output:           pavgpower- peak power consumption information
*
* Return:         
*
******************************************************************/
static int ipmi_get_peakpower_consmpt_history(void* intf,IPMI_POWER_CONSUMP_HISTORY * pstPeakpower)
{

    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[4];

    req.msg.netfn = IPMI_NETFN_APP;
    req.msg.lun = 0;
    req.msg.cmd = IPMI_GET_SYS_INFO;
    req.msg.data_len = 4;
    req.msg.data = data;
    data[0] = 0;
    data[1] = 0xec;
    data[2] = 0;
    data[3] = 0;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
	printf(" Error getting peak power consumption history: ");
	if (rv < 0) printf("no response\n");
	else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) {
		printf("FM001 : A required license is missing or expired\n");
		return rv;	
	} 
	else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv));
	return rv;
    }

    if (verbose > 1)
    {
        printf("Peak power consmhistory  Data               : %x %x %x %x %x %x %x %x %x %x\n   %x %x %x %x %x %x %x %x %x %x %x %x %x\n\n",
            rsp[0], rsp[1], rsp[2], rsp[3], 
            rsp[4], rsp[5], rsp[6], rsp[7], 
            rsp[8], rsp[9], rsp[10], rsp[11], 
            rsp[12], rsp[13], rsp[14], rsp[15], 
            rsp[16], rsp[17], rsp[18], rsp[19],  
            rsp[20], rsp[21], rsp[22], rsp[23]
        );

    }
    *pstPeakpower =* ((IPMI_POWER_CONSUMP_HISTORY*)rsp);
#if WORDS_BIGENDIAN
    pstPeakpower->lastminutepower = BSWAP_16(pstPeakpower->lastminutepower);
    pstPeakpower->lasthourpower = BSWAP_16(pstPeakpower->lasthourpower);
    pstPeakpower->lastdaypower = BSWAP_16(pstPeakpower->lastdaypower);
    pstPeakpower->lastweakpower = BSWAP_16(pstPeakpower->lastweakpower);
    pstPeakpower->lastminutepowertime = BSWAP_32(pstPeakpower->lastminutepowertime);
    pstPeakpower->lasthourpowertime = BSWAP_32(pstPeakpower->lasthourpowertime);
    pstPeakpower->lastdaypowertime = BSWAP_32(pstPeakpower->lastdaypowertime);
    pstPeakpower->lastweekpowertime = BSWAP_32(pstPeakpower->lastweekpowertime);
#endif
    return 0;
}


/*****************************************************************
* Function Name:    ipmi_get_minpower_consmpt_history
*
* Description:      This function updates the peak power consumption information
* Input:            intf            - ipmi interface
* Output:           pavgpower- peak power consumption information
*
* Return:         
*
******************************************************************/
static int ipmi_get_minpower_consmpt_history(void* intf,IPMI_POWER_CONSUMP_HISTORY * pstMinpower)
{

    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[4];

    req.msg.netfn = IPMI_NETFN_APP;
    req.msg.lun = 0;
    req.msg.cmd = IPMI_GET_SYS_INFO;
    req.msg.data_len = 4;
    req.msg.data = data;
    data[0] = 0;
    data[1] = 0xed;
    data[2] = 0;
    data[3] = 0;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
	printf(" Error getting min power consumption history: ");
	if (rv < 0) printf("no response\n");
	else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) {
		printf("FM001 : A required license is missing or expired\n");
		return rv;	
	}
	else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv));
	return rv;
    }

    if (verbose > 1)
    {
        printf("Peak power consmhistory  Data               : %x %x %x %x %x %x %x %x %x %x\n   %x %x %x %x %x %x %x %x %x %x %x %x %x\n\n",
            rsp[0], rsp[1], rsp[2], rsp[3], 
            rsp[4], rsp[5], rsp[6], rsp[7], 
            rsp[8], rsp[9], rsp[10], rsp[11], 
            rsp[12], rsp[13], rsp[14], rsp[15], 
            rsp[16], rsp[17], rsp[18], rsp[19],  
            rsp[20], rsp[21], rsp[22], rsp[23]
        );

    }
    *pstMinpower =* ((IPMI_POWER_CONSUMP_HISTORY*)rsp);
#if WORDS_BIGENDIAN
    pstMinpower->lastminutepower = BSWAP_16(pstMinpower->lastminutepower);
    pstMinpower->lasthourpower = BSWAP_16(pstMinpower->lasthourpower);
    pstMinpower->lastdaypower = BSWAP_16(pstMinpower->lastdaypower);
    pstMinpower->lastweakpower = BSWAP_16(pstMinpower->lastweakpower);
    pstMinpower->lastminutepowertime = BSWAP_32(pstMinpower->lastminutepowertime);
    pstMinpower->lasthourpowertime = BSWAP_32(pstMinpower->lasthourpowertime);
    pstMinpower->lastdaypowertime = BSWAP_32(pstMinpower->lastdaypowertime);
    pstMinpower->lastweekpowertime = BSWAP_32(pstMinpower->lastweekpowertime);
#endif
    return 0;
}



/*****************************************************************
* Function Name:    ipmi_print_power_consmpt_history
*
* Description:      This function print the average and peak power consumption information
* Input:            intf      - ipmi interface
*                   unit      - watt / btuphr
* Output:                
*
* Return:              
*
******************************************************************/
static int ipmi_print_power_consmpt_history(void* intf,int unit )
{

    char timestr[30];

    uint32_t lastminutepeakpower;
    uint32_t lasthourpeakpower;
    uint32_t lastdaypeakpower;
    uint32_t lastweekpeakpower;

    IPMI_AVGPOWER_CONSUMP_HISTORY avgpower;
    IPMI_POWER_CONSUMP_HISTORY stMinpower;
    IPMI_POWER_CONSUMP_HISTORY stPeakpower;
    int rc=0;

    uint64_t tempbtuphrconv;
    //uint16_t temp;


    rc= ipmi_get_avgpower_consmpt_history(intf,&avgpower);    
    if (-1 == rc)
        return rc;

    rc= ipmi_get_peakpower_consmpt_history(intf,&stPeakpower);
    if (-1 == rc)
        return rc;

    rc= ipmi_get_minpower_consmpt_history(intf,&stMinpower);
    if (-1 == rc)
        return rc;


    if(rc==0) 
    {
        printf ("Power Consumption History\n\r\n\r");
        /* The fields are alligned manually changing the spaces will alter the alignment*/
        printf ("Statistic                   Last Minute     Last Hour     Last Day     Last Week\n\r\n\r");

        if (unit ==btuphr)
        {
            printf ("Average Power Consumption  ");         
            tempbtuphrconv=watt_to_btuphr_conversion(avgpower.lastminutepower);
            printf ("%4d BTU/hr     ",tempbtuphrconv);
            tempbtuphrconv=watt_to_btuphr_conversion(avgpower.lasthourpower);
            printf ("%4d BTU/hr   ",tempbtuphrconv);
            tempbtuphrconv=watt_to_btuphr_conversion(avgpower.lastdaypower);
            printf ("%4d BTU/hr  ",tempbtuphrconv);
            tempbtuphrconv=watt_to_btuphr_conversion(avgpower.lastweakpower);
            printf ("%4d BTU/hr\n\r",tempbtuphrconv);

            printf ("Max Power Consumption      ");         
            tempbtuphrconv=watt_to_btuphr_conversion(stPeakpower.lastminutepower);
            printf ("%4d BTU/hr     ",tempbtuphrconv);
            tempbtuphrconv=watt_to_btuphr_conversion(stPeakpower.lasthourpower);
            printf ("%4d BTU/hr   ",tempbtuphrconv);
            tempbtuphrconv=watt_to_btuphr_conversion(stPeakpower.lastdaypower);
            printf ("%4d BTU/hr  ",tempbtuphrconv);
            tempbtuphrconv=watt_to_btuphr_conversion(stPeakpower.lastweakpower);
            printf ("%4d BTU/hr\n\r",tempbtuphrconv);

            printf ("Min Power Consumption      ");         
            tempbtuphrconv=watt_to_btuphr_conversion(stMinpower.lastminutepower);
            printf ("%4d BTU/hr     ",tempbtuphrconv);
            tempbtuphrconv=watt_to_btuphr_conversion(stMinpower.lasthourpower);
            printf ("%4d BTU/hr   ",tempbtuphrconv);
            tempbtuphrconv=watt_to_btuphr_conversion(stMinpower.lastdaypower);
            printf ("%4d BTU/hr  ",tempbtuphrconv);
            tempbtuphrconv=watt_to_btuphr_conversion(stMinpower.lastweakpower);
            printf ("%4d BTU/hr\n\r\n\r",tempbtuphrconv);

        }
        else
        {

            printf ("Average Power Consumption  ");         
            tempbtuphrconv=(avgpower.lastminutepower);
			printf ("%4ld W          ",tempbtuphrconv);
			tempbtuphrconv=(avgpower.lasthourpower);
			printf ("%4ld W        ",tempbtuphrconv);
			tempbtuphrconv=(avgpower.lastdaypower);
			printf ("%4ld W       ",tempbtuphrconv);
			tempbtuphrconv=(avgpower.lastweakpower);
			printf ("%4ld W   \n\r",tempbtuphrconv);

		printf ("Max Power Consumption      ");		
			tempbtuphrconv=(stPeakpower.lastminutepower);
			printf ("%4ld W          ",tempbtuphrconv);
			tempbtuphrconv=(stPeakpower.lasthourpower);
			printf ("%4ld W        ",tempbtuphrconv);
			tempbtuphrconv=(stPeakpower.lastdaypower);
			printf ("%4ld W       ",tempbtuphrconv);
			tempbtuphrconv=(stPeakpower.lastweakpower);
			printf ("%4ld W   \n\r",tempbtuphrconv);

		printf ("Min Power Consumption      ");		
			tempbtuphrconv=(stMinpower.lastminutepower);
			printf ("%4ld W          ",tempbtuphrconv);
			tempbtuphrconv=(stMinpower.lasthourpower);
			printf ("%4ld W        ",tempbtuphrconv);
			tempbtuphrconv=(stMinpower.lastdaypower);
			printf ("%4ld W       ",tempbtuphrconv);
			tempbtuphrconv=(stMinpower.lastweakpower);
		   	printf ("%4ld W   \n\r\n\r",tempbtuphrconv);
		}		
		
        lastminutepeakpower=stPeakpower.lastminutepowertime;
        lasthourpeakpower=stPeakpower.lasthourpowertime;
        lastdaypeakpower=stPeakpower.lastdaypowertime;
        lastweekpeakpower=stPeakpower.lastweekpowertime;

        printf ("Max Power Time\n\r");
        ipmi_time_to_str(lastminutepeakpower, timestr);         
        printf ("Last Minute     : %s",timestr);
        ipmi_time_to_str(lasthourpeakpower, timestr);           
        printf ("Last Hour       : %s",timestr);
        ipmi_time_to_str(lastdaypeakpower, timestr);            
        printf ("Last Day        : %s",timestr);
        ipmi_time_to_str(lastweekpeakpower, timestr);           
        printf ("Last Week       : %s",timestr);                


        lastminutepeakpower=stMinpower.lastminutepowertime;
        lasthourpeakpower=stMinpower.lasthourpowertime;
        lastdaypeakpower=stMinpower.lastdaypowertime;
        lastweekpeakpower=stMinpower.lastweekpowertime; 

        printf ("Min Power Time\n\r");
        ipmi_time_to_str(lastminutepeakpower, timestr);         
        printf ("Last Minute     : %s",timestr);
        ipmi_time_to_str(lasthourpeakpower, timestr);           
        printf ("Last Hour       : %s",timestr);
        ipmi_time_to_str(lastdaypeakpower, timestr);            
        printf ("Last Day        : %s",timestr);
        ipmi_time_to_str(lastweekpeakpower, timestr);           
        printf ("Last Week       : %s",timestr);        

    }
	return rc;

}



/*****************************************************************
* Function Name:    ipmi_get_power_cap
*
* Description:      This function updates the power cap information
* Input:            intf         - ipmi interface
* Output:           ipmipowercap - power cap information
*
* Return:          
*
******************************************************************/

static int ipmi_get_power_cap(void* intf,IPMI_POWER_CAP* ipmipowercap )
{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req={0};
    //uint64_t tempbtuphrconv;
    uint8_t data[4];

    /* power supply rating command*/
    req.msg.netfn = IPMI_NETFN_APP;
    req.msg.lun = 0;
    req.msg.cmd = IPMI_GET_SYS_INFO;
    req.msg.data_len = 4;
    req.msg.data = data;

    data[0] = 0;
    data[1] = IPMI_DELL_POWER_CAP;
    data[2] = 0;
    data[3] = 0;


    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
	printf(" Error getting power cap: ");
	if (rv < 0) printf("no response\n");
	else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) {
		printf("FM001 : A required license is missing or expired\n");
		return rv;	
	} 
	else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv));
	return rv;
    }
    if (verbose > 1){
        printf("power cap  Data               :%x %x %x %x %x %x %x %x %x %x %x",
            rsp[1], rsp[2], rsp[3], 
            rsp[4], rsp[5], rsp[6], rsp[7], 
            rsp[8], rsp[9], rsp[10],rsp[11]);

    }

    * ipmipowercap = *((IPMI_POWER_CAP*)(rsp));
#if WORDS_BIGENDIAN
    ipmipowercap->PowerCap = BSWAP_16(ipmipowercap->PowerCap);
    ipmipowercap->MaximumPowerConsmp = BSWAP_16(ipmipowercap->MaximumPowerConsmp);
    ipmipowercap->MinimumPowerConsmp = BSWAP_16(ipmipowercap->MinimumPowerConsmp);
    ipmipowercap->totalnumpowersupp = BSWAP_16(ipmipowercap->totalnumpowersupp);
    ipmipowercap->AvailablePower = BSWAP_16(ipmipowercap->AvailablePower);
    ipmipowercap->SystemThrottling = BSWAP_16(ipmipowercap->SystemThrottling);
    ipmipowercap->Resv = BSWAP_16(ipmipowercap->Resv);
#endif

    return 0;
}

/*****************************************************************
* Function Name:    ipmi_print_power_cap
*
* Description:      This function print the power cap information
* Input:            intf            - ipmi interface
*                   unit            - watt / btuphr
* Output:                
* Return:               
*
******************************************************************/
static int ipmi_print_power_cap(void* intf,uint8_t unit )
{
    uint64_t tempbtuphrconv;
    int rc;
    IPMI_POWER_CAP ipmipowercap;

	memset(&ipmipowercap,0,sizeof(ipmipowercap));
    rc=ipmi_get_power_cap(intf,&ipmipowercap);


    if (rc==0) 
    {
        if (unit ==btuphr){
            tempbtuphrconv=watt_to_btuphr_conversion(ipmipowercap.MaximumPowerConsmp);
			printf ("Maximum power: %ld  BTU/hr\n",tempbtuphrconv);
			tempbtuphrconv=watt_to_btuphr_conversion(ipmipowercap.MinimumPowerConsmp);
			printf ("Minimum power: %ld  BTU/hr\n",tempbtuphrconv);
			tempbtuphrconv=watt_to_btuphr_conversion(ipmipowercap.PowerCap);
			printf ("Power cap    : %ld  BTU/hr\n",tempbtuphrconv);
		}else{
		
			printf ("Maximum power: %ld Watt\n",ipmipowercap.MaximumPowerConsmp);
			printf ("Minimum power: %ld Watt\n",ipmipowercap.MinimumPowerConsmp);
			printf ("Power cap    : %ld Watt\n",ipmipowercap.PowerCap);
        }
    }
    return rc;

}  

/*****************************************************************
* Function Name:     ipmi_set_power_cap
*
* Description:       This function updates the power cap information
* Input:             intf            - ipmi interface
*                    unit            - watt / btuphr
*                    val             - new power cap value
* Output:          
* Return:               
*
******************************************************************/
static int ipmi_set_power_cap(void* intf,int unit,int val )
{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req={0};
    uint8_t data[13];
    uint16_t powercapval;
    uint64_t maxpowerbtuphr;
    uint64_t maxpowerbtuphr1;
    uint64_t minpowerbtuphr;
    IPMI_POWER_CAP ipmipowercap;

	if(ipmi_get_power_capstatus_command(intf) < 0)
		return -1;	// Adding the failed condition check

    if (PowercapSetable_flag!=1)
    {
        lprintf(LOG_ERR, " Can not set powercap on this system");
        return -1;
    }
    else if(PowercapstatusFlag!=1)
    {
        lprintf(LOG_ERR, " Power cap set feature is not enabled");
        return -1;
    }

    req.msg.netfn = IPMI_NETFN_APP;
    req.msg.lun = 0;
    req.msg.cmd = IPMI_GET_SYS_INFO;
    req.msg.data_len = 4;
    memset(data, 0, 4);
    req.msg.data = data;

    data[0] = 0;
    data[1] = IPMI_DELL_POWER_CAP;
    data[2] = 0;
    data[3] = 0;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
	printf(" Error getting power cap: ");
	if (rv < 0) printf("no response\n");
	else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) {
		printf("FM001 : A required license is missing or expired\n");
		return rv;	
	}
	else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv));
	return rv;
    }
    if (verbose > 1)
    {
        printf("power cap  Data               :%x %x %x %x %x %x %x %x %x %x ",
            rsp[1], rsp[2], rsp[3], 
            rsp[4], rsp[5], rsp[6], rsp[7], 
            rsp[8], rsp[9], rsp[10],rsp[11]);

    }

    ipmipowercap.PowerCap=((rsp[1]<<8)+rsp[2]);
    ipmipowercap.unit=rsp[3];
    ipmipowercap.MaximumPowerConsmp=((rsp[4]<<8)+rsp[5]);
    ipmipowercap.MinimumPowerConsmp=((rsp[6]<<8)+rsp[7]);
    /* ARC: need Dell to verify these 3 values */
    ipmipowercap.totalnumpowersupp = rsp[8];
    ipmipowercap.AvailablePower = ((rsp[9]<<8)+rsp[10]);
    ipmipowercap.SystemThrottling = rsp[11];

    memset(data, 0, 13);
    req.msg.netfn = IPMI_NETFN_APP;
    req.msg.lun = 0;
    req.msg.cmd = IPMI_SET_SYS_INFO;
    req.msg.data_len = 13;
    req.msg.data = data;
    data[0] = IPMI_DELL_POWER_CAP;
    powercapval=val;


    data[1] = (powercapval&0XFF);                   
    data[2] = ((powercapval&0XFF00)>>8);
    data[3] = unit;

    data[4]=((ipmipowercap.MaximumPowerConsmp&0xFF));
    data[5]=((ipmipowercap.MaximumPowerConsmp&0xFF00)>>8);
    data[6]=((ipmipowercap.MinimumPowerConsmp&0xFF));
    data[7]=((ipmipowercap.MinimumPowerConsmp&0xFF00)>>8);
    data[8]=(uint8_t)(ipmipowercap.totalnumpowersupp);  
    data[9]=((ipmipowercap.AvailablePower&0xFF));
    data[10]=((ipmipowercap.AvailablePower&0xFF00)>>8);
    data[11]=(uint8_t)(ipmipowercap.SystemThrottling);
    data[12]=0x00;

    ipmipowercap.MaximumPowerConsmp = BSWAP_16(ipmipowercap.MaximumPowerConsmp);
    ipmipowercap.MinimumPowerConsmp = BSWAP_16(ipmipowercap.MinimumPowerConsmp);
    ipmipowercap.PowerCap = BSWAP_16(ipmipowercap.PowerCap);
    if(unit==btuphr)
    {
        val = btuphr_to_watt_conversion(val);

    }
    else if(unit ==percent)
    {
       	if((val <0)||(val>100))
        {
            lprintf(LOG_ERR, " Cap value is out of boundary conditon it should be between 0  - 100");
            return -1;
        }
        val =( (val*(ipmipowercap.MaximumPowerConsmp -ipmipowercap.MinimumPowerConsmp))/100)+ipmipowercap.MinimumPowerConsmp;
        lprintf(LOG_ERR, " Cap value in percentage is  %d ",val);
        data[1] = (val&0XFF);                   
        data[2] = ((val&0XFF00)>>8);
        data[3] = watt;
    }
    if(((val<ipmipowercap.MinimumPowerConsmp)||(val>ipmipowercap.MaximumPowerConsmp))&&(unit==watt))
    {
        lprintf(LOG_ERR, " Cap value is out of boundary conditon it should be between %d  - %d",
            ipmipowercap.MinimumPowerConsmp,ipmipowercap.MaximumPowerConsmp);
        return -1;
    }
    else if(((val<ipmipowercap.MinimumPowerConsmp)||(val>ipmipowercap.MaximumPowerConsmp))&&(unit==btuphr))
    {
        minpowerbtuphr= watt_to_btuphr_conversion(ipmipowercap.MinimumPowerConsmp);
        maxpowerbtuphr=watt_to_btuphr_conversion(ipmipowercap.MaximumPowerConsmp);
        maxpowerbtuphr1= watt_to_btuphr_conversion(ipmipowercap.MaximumPowerConsmp);
        lprintf(LOG_ERR, " Cap value is out of boundary conditon it should be between %d",
            minpowerbtuphr);
        lprintf(LOG_ERR, " -%d",
            maxpowerbtuphr1);

        return -1;
    }
    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
	printf(" Error setting power cap: ");
	if (rv < 0) printf("no response\n");
	else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) {
		printf("FM001 : A required license is missing or expired\n");
		return rv;	
	} 
	else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv));
	return rv;
    }
    if (verbose > 1)
    {
        printf("CC for setpowercap :%d ",rv);
    }
    return 0;
}

/*****************************************************************
* Function Name:    getpowersupplyfruinfo
*
* Description:      This function retrieves the FRU header
* Input:            intf    - ipmi interface
*                   header  - watt / btuphr
*                   fru     - FRU information
* Output:           header  - FRU header
* Return:           
*
******************************************************************/
static int getpowersupplyfruinfo(void *intf, uint8_t id, 
                         struct fru_header header, struct fru_info fru)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req;

    uint8_t msg_data[4];

    memset(&fru, 0, sizeof(struct fru_info));
    memset(&header, 0, sizeof(struct fru_header));

    /*
    * get info about this FRU
    */
    memset(msg_data, 0, 4);
    msg_data[0] = id;

    memset(&req, 0, sizeof(req));
    req.msg.netfn = IPMI_NETFN_STORAGE;
    req.msg.lun = 0;
    req.msg.cmd = GET_FRU_INFO;
    req.msg.data = msg_data;
    req.msg.data_len = 1;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
	printf(" Device not present, ");
	if (rv < 0) printf("no response\n");
	else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv));
	return rv;
    }

    fru.size = (rsp[1] << 8) | rsp[0];
    fru.access = rsp[2] & 0x1;

    lprintf(LOG_DEBUG, "fru.size = %d bytes (accessed by %s)",
        fru.size, fru.access ? "words" : "bytes");

    if (fru.size < 1) {
        printf(" Invalid FRU size %d", fru.size);
        return -1;
    }

    /*
    * retrieve the FRU header
    */
    msg_data[0] = id;
    msg_data[1] = 0;
    msg_data[2] = 0;
    msg_data[3] = 8;

    memset(&req, 0, sizeof(req));
    req.msg.netfn = IPMI_NETFN_STORAGE;
    req.msg.lun = 0;
    req.msg.cmd = GET_FRU_DATA;
    req.msg.data = msg_data;
    req.msg.data_len = 4;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
	printf(" Device not present, ");
	if (rv < 0) printf("no response\n");
	else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv));
	return rv;
    }

    if (verbose > 1)
        printbuf(rsp, rsp_len, "FRU DATA");

    memcpy(&header, &rsp[1], 8);

	return 0;


}

/*****************************************************************
* Function Name:   ipmi_powermonitor_usage
*
* Description:     This function prints help message for powermonitor command
* Input:              
* Output:       
*
* Return:              
*
******************************************************************/
static void
ipmi_powermonitor_usage(void)
{
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   powermonitor");
    lprintf(LOG_NOTICE, "      Shows power tracking statistics ");
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   powermonitor clear cumulativepower");
    lprintf(LOG_NOTICE, "      Reset cumulative power reading");
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   powermonitor clear peakpower");
    lprintf(LOG_NOTICE, "      Reset peak power reading");
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   powermonitor powerconsumption");
    lprintf(LOG_NOTICE, "      Displays power consumption in <watt|btuphr>");
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   powermonitor powerconsumptionhistory <watt|btuphr>");
    lprintf(LOG_NOTICE, "      Displays power consumption history ");
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   powermonitor getpowerbudget");
    lprintf(LOG_NOTICE, "      Displays power cap in <watt|btuphr>");
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   powermonitor setpowerbudget <val><watt|btuphr|percent>");
    lprintf(LOG_NOTICE, "      Allows user to set the  power cap in <watt|BTU/hr|percentage>");
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   powermonitor enablepowercap ");
    lprintf(LOG_NOTICE, "      To enable set power cap");
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   powermonitor disablepowercap ");
    lprintf(LOG_NOTICE, "      To disable set power cap");
    lprintf(LOG_NOTICE, "");

}
/*****************************************************************
* Function Name:	   ipmi_delloem_vFlash_main
*
* Description:		   This function processes the delloem vFlash command
* Input:			   intf    - ipmi interface
					   argc    - no of arguments
					   argv    - argument string array
* Output:		 
*
* Return:			   return code	   0 - success
*						  -1 - failure
*
******************************************************************/

static int ipmi_delloem_vFlash_main (void * intf, int  argc, char ** argv)
{
	int rc = 0;

	current_arg++;
	rc = ipmi_delloem_vFlash_process(intf, current_arg, argv);
	return(rc);
}



/*****************************************************************
* Function Name: 	get_vFlash_compcode_str
*
* Description: 	This function maps the vFlash completion code
* 		to a string
* Input : vFlash completion code and static array of codes vs strings
* Output: - 		
* Return: returns the mapped string		
*
******************************************************************/
const char * 
get_vFlash_compcode_str(uint8_t vflashcompcode, const struct vFlashstr *vs)
{
	static char un_str[32];
	int i;

	for (i = 0; vs[i].str != NULL; i++) {
		if (vs[i].val == vflashcompcode)
			return vs[i].str;
	}

	memset(un_str, 0, 32);
	snprintf(un_str, 32, "Unknown (0x%02X)", vflashcompcode);

	return un_str;
}

/*****************************************************************
* Function Name: 	ipmi_get_sd_card_info
*
* Description: This function prints the vFlash Extended SD card info
* Input : ipmi interface
* Output: prints the sd card extended info		
* Return: 0 - success -1 - failure
*
******************************************************************/
static int
ipmi_get_sd_card_info(void* intf) {
	uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
	struct ipmi_rq req;

	uint8_t msg_data[2];
	uint8_t input_length=0;
	uint8_t cardstatus=0x00;

	IPMI_DELL_SDCARD_INFO * sdcardinfoblock;

	input_length = 2;
	msg_data[0] = msg_data[1] = 0x00;

	req.msg.netfn = IPMI_DELL_OEM_NETFN;
	req.msg.lun = 0;
	req.msg.cmd = IPMI_GET_EXT_SD_CARD_INFO;
	req.msg.data = msg_data;
	req.msg.data_len = input_length;

	rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
	if (rv) {
	   printf(" Error getting SD Card Extended info, ");
	   if (rv < 0) printf("no response\n");
	   else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv));
	   return rv;
	}

	sdcardinfoblock = (IPMI_DELL_SDCARD_INFO *) (void *) rsp;

	if( (iDRAC_FLAG == IDRAC_12G) && (sdcardinfoblock->vflashcompcode == VFL_NOT_LICENSED))
	{
		printf("FM001 : A required license is missing or expired\n");
		return -1;	
	}
	else if (sdcardinfoblock->vflashcompcode != 0x00)
	{
		lprintf(LOG_ERR, " Error in getting SD Card Extended Information (%s) \n", get_vFlash_compcode_str(sdcardinfoblock->vflashcompcode,
					vFlash_completion_code_vals));
		return -1;
	}

	if (!(sdcardinfoblock->sdcardstatus & 0x04))
	{
		lprintf(LOG_ERR, " vFlash SD card is unavailable, please insert the card\n of size 256MB or greater\n");
		return 0;
	}

	printf("vFlash SD Card Properties\n");
	printf("SD Card size       : %8dMB\n",sdcardinfoblock->sdcardsize);
	printf("Available size     : %8dMB\n",sdcardinfoblock->sdcardavailsize);
	printf("Initialized        : %10s\n", (sdcardinfoblock->sdcardstatus & 0x80) ?
			"Yes" : "No");
	printf("Licensed           : %10s\n", (sdcardinfoblock->sdcardstatus & 0x40) ?
			"Yes" : "No");
	printf("Attached           : %10s\n", (sdcardinfoblock->sdcardstatus & 0x20) ?
			"Yes" : "No");
	printf("Enabled            : %10s\n", (sdcardinfoblock->sdcardstatus & 0x10) ?
			"Yes" : "No");
	printf("Write Protected    : %10s\n", (sdcardinfoblock->sdcardstatus & 0x08) ?
			"Yes" : "No");
	cardstatus = sdcardinfoblock->sdcardstatus & 0x03;
	printf("Health             : %10s\n", ((0x00 == cardstatus
		) ? "OK" : ((cardstatus == 0x03) ? 
			"Undefined" : ((cardstatus == 0x02) ? 
				"Critical" : "Warning"))));
	printf("Bootable partition : %10d\n",sdcardinfoblock->bootpartion);
	return 0;
}

/*****************************************************************
* Function Name: 	ipmi_delloem_vFlash_process
*
* Description: 	This function processes the args for vFlash subcmd
* Input : intf - ipmi interface, arg index, argv array
* Output: prints help or error with help
* Return: 0 - Success -1 - failure
*
******************************************************************/
static int
ipmi_delloem_vFlash_process(void* intf, int current_arg, char ** argv) 
{
	int rc = 0;
	int drv;

	drv = get_driver_type();
	if (drv != DRV_MV) /* MV open driver */
	{
		lprintf(LOG_ERR, " vFlash support is enabled only for wmi and open interface.\n Its not enabled for lan and lanplus interface.");
		return -1;
	}

	if (argv[current_arg] == NULL || strcmp(argv[current_arg], "help") == 0)
	{
		ipmi_vFlash_usage();
		return 0;
	}
	ipmi_idracvalidator_command(intf);
	if (!strncmp(argv[current_arg], "info\0", 5))
	{
		current_arg++;
		if (argv[current_arg] == NULL)
		{
			ipmi_vFlash_usage();
			return -1;
		}
		else if (strncmp(argv[current_arg], "Card\0", 5) == 0)
		{
			current_arg++;
			if (argv[current_arg] != NULL)
			{
				ipmi_vFlash_usage();
				return -1;
			}
			rc = ipmi_get_sd_card_info(intf);
			return rc;
		}
		else /* TBD: many sub commands are present */
		{
			ipmi_vFlash_usage();
			return -1;
		}
	}
	/* TBD other vFlash subcommands */
	else
	{
		ipmi_vFlash_usage();
		return -1;
	}
	return(rc);
}

/*****************************************************************
* Function Name: 	ipmi_vFlash_usage
*
* Description: 	This function displays the usage for using vFlash
* Input : void
* Output: prints help		
* Return: void	
*
******************************************************************/
static void
ipmi_vFlash_usage(void)
{
	lprintf(LOG_NOTICE, "");
	lprintf(LOG_NOTICE, "   vFlash info Card");
	lprintf(LOG_NOTICE, "      Shows Extended SD Card information");
	lprintf(LOG_NOTICE, "");
}
/*****************************************************************
* Function Name:       ipmi_delloem_windbg_main
*
* Description:         This function processes the delloem windbg command
* Input:               intf    - ipmi interface
                       argc    - no of arguments
                       argv    - argument string array
* Output:        
*
* Return:              return code     0 - success
*                         -1 - failure
*
******************************************************************/

static int ipmi_delloem_windbg_main (void * intf, int  argc, char ** argv)
{
    int rc = 0;

	current_arg++;
	if (argv[current_arg] == NULL)
	{
		ipmi_windbg_usage();
		return -1;
	}		
	if (strncmp(argv[current_arg], "start\0", 6) == 0)
	{
		rc = ipmi_windbg_start(intf);
	}
	else if (strncmp(argv[current_arg], "end\0", 4) == 0)
	{
		rc = ipmi_windbg_end(intf);
	}
	else
	{
		ipmi_windbg_usage();
	}
	return(rc);
}

/*****************************************************************
* Function Name: 	ipmi_windbg_start 
*
* Description: 	This function Starts the windbg
* Input : void
* Output: Start the debug		
* Return: void	
*
******************************************************************/
static int
ipmi_windbg_start (void * intf)
{
	int rc;
	windbgsession = 1;
	lprintf(LOG_NOTICE, "Issuing sol activate");
	lprintf(LOG_NOTICE, "");
	
	rc = ipmi_sol_activate(intf,0,0);
	if (rc) lprintf(LOG_NOTICE, "Can not issue sol activate");
	return(rc);
}

/*****************************************************************
* Function Name: 	ipmi_windbg_end
*
* Description: 	This function ends the windbg
* Input : void
* Output: End the debug		
* Return: void	
*
******************************************************************/

static int
ipmi_windbg_end(void * intf)
{
	int rc;
	lprintf(LOG_NOTICE, "Issuing sol deactivate");
	lprintf(LOG_NOTICE, "");
	rc = ipmi_sol_deactivate(intf);
	if (rc) lprintf(LOG_NOTICE, "Can not issue sol deactivate");
	return(rc);	
}


/*****************************************************************
* Function Name: 	ipmi_windbg_usage
*
* Description: 	This function displays the usage for using windbg
* Input : void
* Output: prints help		
* Return: void	
*
******************************************************************/

static void
ipmi_windbg_usage(void)
{
	lprintf(LOG_NOTICE, "");
	lprintf(LOG_NOTICE, "   windbg start");
	lprintf(LOG_NOTICE, "      Starts the windbg session (Cold Reset & SOL Activation)");
	lprintf(LOG_NOTICE, "");
	lprintf(LOG_NOTICE, "   windbg end");
	lprintf(LOG_NOTICE, "      Ends the windbg session (SOL Deactivation");
	lprintf(LOG_NOTICE, "");
}



/**********************************************************************
* Function Name: ipmi_setled_usage
*
* Description:  This function prints help message for setled command
* Input:
* Output:
*
* Return:
*
***********************************************************************/
static void
ipmi_setled_usage(void)
{
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   setled <b:d.f> <state..>");
    lprintf(LOG_NOTICE, "      Set backplane LED state");
    lprintf(LOG_NOTICE, "      b:d.f = PCI Bus:Device.Function of drive (lspci format)");
    lprintf(LOG_NOTICE, "      state = present|online|hotspare|identify|rebuilding|");
    lprintf(LOG_NOTICE, "              fault|predict|critical|failed");
    lprintf(LOG_NOTICE, "");
}

ipmi_delloem_getled_usage(void)
{
    lprintf(LOG_NOTICE, "");
    lprintf(LOG_NOTICE, "   getled ");
    lprintf(LOG_NOTICE, "      Get Chassis ID LED state");
    lprintf(LOG_NOTICE, "");
}

static int
IsSetLEDSupported(void)
{
    return SetLEDSupported;
}

static int
CheckSetLEDSupport(void * intf)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[10];

    SetLEDSupported = 0;
    req.msg.netfn = IPMI_DELL_OEM_NETFN;
    req.msg.lun = 0;
    req.msg.cmd = 0xD5; 		/* Storage */
    req.msg.data_len = sizeof(data);    /*10*/
    req.msg.data = data;

    memset(data, 0, sizeof(data));
    data[0] = 0x01;                        // get
    data[1] = 0x00;			   // subcmd:get firmware version
    data[2] = 0x08;                        // length lsb
    data[3] = 0x00;			   // length msb
    data[4] = 0x00;			   // offset lsb
    data[5] = 0x00;			   // offset msb
    data[6] = 0x00;			   // bay id
    data[7] = 0x00;		
    data[8] = 0x00;
    data[9] = 0x00;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv == 0) SetLEDSupported = 1;
    return(rv);
}

/*****************************************************************
* Function Name:    ipmi_getdrivemap
*
* Description:      This function returns mapping of BDF to Bay:Slot
* Input:            intf         - ipmi interface
*		    bdf	 	 - PCI Address of drive
*		    *bay	 - Returns bay ID
		    *slot	 - Returns slot ID
* Output:           
*
* Return:          
*
******************************************************************/
static int
ipmi_getdrivemap(void * intf, int b, int d, int f, int *bay, int *slot)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[8];

    /* Get mapping of BDF to bay:slot */
    req.msg.netfn = IPMI_DELL_OEM_NETFN;
    req.msg.lun = 0;
    req.msg.cmd = 0xD5;
    req.msg.data_len = 8;
    req.msg.data = data;

    memset(data, 0, sizeof(data));
    data[0] = 0x01;		// get
    data[1] = 0x07;		// storage map
    data[2] = 0x06;		// length lsb
    data[3] = 0x00;		// length msb
    data[4] = 0x00;		// offset lsb
    data[5] = 0x00;		// offset msb
    data[6] = b;		// bus
    data[7] = (d << 3) + f;	// devfn

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
	printf(" Error issuing getdrivemap command, ");
	if (rv < 0) printf("no response\n");
	else printf("Completion Code 0x%02x %s\n", rv, decode_cc(0,rv));
	return rv;
    }

    *bay = rsp[7];
    *slot = rsp[8];
    if (*bay == 0xFF || *slot == 0xFF)
    {
	lprintf(LOG_ERR, "Error could not get drive bay:slot mapping");
	return -1;
    }
    return 0;
}

/*****************************************************************
* Function Name:    ipmi_setled_state
*
* Description:      This function updates the LED on the backplane
* Input:            intf         - ipmi interface
*		    bdf	 	 - PCI Address of drive
*		    state	 - SES Flags state of drive
* Output:           
*
* Return:          
*
******************************************************************/
static int
ipmi_setled_state (void * intf, int bayId, int slotId, int state)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[20];

    /* Issue Drive Status Update to bay:slot */
    req.msg.netfn = IPMI_DELL_OEM_NETFN;
    req.msg.lun = 0;
    req.msg.cmd = 0xD5;
    req.msg.data_len = 20;
    req.msg.data = data;

    memset(data, 0, sizeof(data));
    data[0] = 0x00;		// set
    data[1] = 0x04;		// set drive status
    data[2] = 0x0e;		// length lsb
    data[3] = 0x00;		// length msb
    data[4] = 0x00;		// offset lsb
    data[5] = 0x00;		// offset msb
    data[6] = 0x0e;		// length lsb
    data[7] = 0x00;		// length msb
    data[8] = bayId;		// bayid
    data[9] = slotId;		// slotid
    data[10] = state & 0xff;	// state LSB
    data[11] = state >> 8;	// state MSB;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
	printf(" Error issuing setled command, ");
	if (rv < 0) printf("no response\n");
	else printf("Completion Code 0x%02x %s\n", rv, decode_cc(0,rv));
	return rv;
    }

    return 0;
}

int ipmi_delloem_getled_state (void * intf, uint8_t *state)
{
    uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
    struct ipmi_rq req = {0};
    uint8_t data[2];
    uint8_t led_state = 0;

    req.msg.netfn = IPMI_DELL_OEM_NETFN;
    req.msg.lun = 0;
    req.msg.cmd = GET_CHASSIS_LED_STATE;
    req.msg.data_len = 0;
    req.msg.data = data;

    rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
    if (rv) {
	printf(" Error issuing getled command, ");
	if (rv < 0) printf("no response\n");
	else printf("Completion Code 0x%02x %s\n", rv, decode_cc(0,rv));
    } else {
        led_state = rsp[0];  
    }
    *state = led_state;
    return rv;
}

/*****************************************************************
* Function Name:    ipmi_getsesmask
*
* Description:      This function calculates bits in SES drive update
* Return:           Mask set with bits for SES backplane update
*
******************************************************************/
static int ipmi_getsesmask(int  argc, char **argv)
{
	int mask = 0;
	//int idx;
	
	while (current_arg < argc) {
		if (!strcmp(argv[current_arg], "present"))
			mask |= (1L << 0);
		if (!strcmp(argv[current_arg], "online"))
			mask |= (1L << 1);
		if (!strcmp(argv[current_arg], "hotspare"))
			mask |= (1L << 2);
		if (!strcmp(argv[current_arg], "identify"))
			mask |= (1L << 3);
		if (!strcmp(argv[current_arg], "rebuilding"))
			mask |= (1L << 4);
		if (!strcmp(argv[current_arg], "fault"))
			mask |= (1L << 5);
		if (!strcmp(argv[current_arg], "predict"))
			mask |= (1L << 6);
		if (!strcmp(argv[current_arg], "critical"))
			mask |= (1L << 9);
		if (!strcmp(argv[current_arg], "failed"))
			mask |= (1L << 10);
		current_arg++;
	}
	return mask;
}

/*****************************************************************
* Function Name:       ipmi_delloem_setled_main
*
* Description:         This function processes the delloem setled command
* Input:               intf    - ipmi interface
                       argc    - no of arguments
                       argv    - argument string array
* Output:        
*
* Return:              return code     0 - success
*                         -1 - failure
*
******************************************************************/
static int
ipmi_delloem_setled_main(void * intf, int  argc, char ** argv)
{
    int rc = 0;
    int b,d,f, mask;
    int bayId, slotId;

    bayId = 0xFF;
    slotId = 0xFF;

    current_arg++;
    if (argc < current_arg) 
    {
        usage();
        return -1;
    }

    /* ipmitool delloem setled info*/
    if (argc == 1 || strcmp(argv[current_arg], "help") == 0)
    {
        ipmi_setled_usage();
	return 0;
    }
    CheckSetLEDSupport (intf);
    if (!IsSetLEDSupported())
    {
        printf("'setled' is not supported on this system.\n");
        return -1;
    }
    else if (sscanf(argv[current_arg], "%*x:%x:%x.%x", &b,&d,&f) == 3) {
        /* We have bus/dev/function of drive */
	current_arg++;
    	ipmi_getdrivemap (intf, b, d, f, &bayId, &slotId);
    }
    else if (sscanf(argv[current_arg], "%x:%x.%x", &b,&d,&f) == 3) {
        /* We have bus/dev/function of drive */
	current_arg++;
    }
    else {
	ipmi_setled_usage();
	return -1;
    }
    /* Get mask of SES flags */	
    mask = ipmi_getsesmask(argc, argv);

    /* Get drive mapping */
    if (ipmi_getdrivemap (intf, b, d, f, &bayId, &slotId))
	return -1;

    /* Set drive LEDs */
    return ipmi_setled_state (intf, bayId, slotId, mask);
}

static int
ipmi_delloem_getled_main(void * intf, int  argc, char ** argv)
{
    int rc = 0;
    uint8_t state;

    if (argc == 1 || strncmp(argv[0], "help\0", 5) == 0) 
    {
        ipmi_delloem_getled_usage();
	return(0);
    } else {
	rc = ipmi_delloem_getled_state (intf, &state);
	if (rc != 0) printf("getled_state error %d\n",rc);
	else {
	   if (state == 0x01) 
	        printf("Chassis ID LED Status = ON\n");
	   else printf("Chassis ID LED Status = off\n");
	}
    }
    return (rc);
}

/*
 * decode_sensor_dell
 * inputs:
 *    sdr     = the SDR buffer
 *    reading = the 3 or 4 bytes of data from GetSensorReading
 *    pstring = points to the output string buffer
 *    slen    = size of the output buffer
 * outputs:
 *    rv     = 0 if this sensor was successfully interpreted here,
 *             non-zero otherwise, to use default interpretations.
 *    pstring = contains the sensor reading interpretation string (if rv==0)
 */
int decode_sensor_dell(uchar *sdr,uchar *reading,char *pstring, int slen)
{
   int rv = -1;
   char *pstr = NULL;
   uchar stype, evtype;

   if (sdr == NULL || reading == NULL) return(rv);
   if (pstring == NULL || slen == 0) return(rv);
   /* sdr[3] is SDR type: 1=full, 2=compact, 0xC0=oem */
   if (sdr[3] != 0x02) return(rv);  /*return if not compact SDR */
   stype = sdr[12];  /*sensor type*/
   evtype = sdr[13];  /*event type */
   if (stype == 0x02) {  /* Discrete Voltage */
      /* Dell Discrete Voltage is opposite from normal */
      if (evtype == 0x03) {   /*oem interpretation */
	 if (reading[2] & 0x01) strncpy(pstring,"OK",slen); 
	 else      strncpy(pstring,"Exceeded",slen); /*LimitExceeded*/
         rv = 0;
      }
   }
   return(rv);
}

#define BIT(x)		(1 << x)
#define	SIZE_OF_DESC	128

char * get_dell_evt_desc(uchar *sel_rec)
{
	struct sel_event_record * rec = (struct sel_event_record *)sel_rec;
	int data1, data2, data3;
	int code;
	char *desc = NULL;
	
	unsigned char count;
	unsigned char node;
	//unsigned char num;
	unsigned char dimmNum;
	unsigned char dimmsPerNode;
	char          dimmStr[32];
	//char          cardStr[32];
	//char          numStr[32];
	char          tmpdesc[SIZE_OF_DESC];
	static char   rgdesc[SIZE_OF_DESC];
	char*         str;
	unsigned char incr = 0;
	unsigned char i    = 0;
	//unsigned char postCode;
	// struct ipmi_rs *rsp;
	// struct ipmi_rq req;
	char tmpData;
	int version;
        // uint8_t devid[20]; /*usually 16 bytes*/
        uint8_t iver;
	// int rv;

	data1 = rec->sel_type.standard_type.event_data[0];
	data2 = rec->sel_type.standard_type.event_data[1];
	data3 = rec->sel_type.standard_type.event_data[2];
	if ( (rec->sel_type.standard_type.event_type == 0x0B) || 
		(rec->sel_type.standard_type.event_type == 0x6F)  || 
		(rec->sel_type.standard_type.event_type == 0x07)) 
		{
		code = rec->sel_type.standard_type.sensor_type;
		/* BDF or Slot */
		desc = rgdesc;
		memset(desc,0,SIZE_OF_DESC);
		switch (code) {
			case 0x07:
				if( ((data1 & DATA_BYTE2_SPECIFIED_MASK) == 0x80))
				{
					if((data1 & 0x0f) == 0x00) 
						snprintf(desc,SIZE_OF_DESC,"CPU Internal Err | ");
					if((data1 & 0x0f) == 0x06)
					{
						snprintf(desc,SIZE_OF_DESC,"CPU Protocol Err | ");
					}
					/* change bit location to a number */
					for (count= 0; count < 8; count++)
					{
					  if (BIT(count)& data2)
					  {
					    count++;
						if( ((data1 & 0x0f) == 0x06) && (rec->sel_type.standard_type.sensor_num == 0x0A)) 
						    snprintf(desc,SIZE_OF_DESC,"FSB %d ",count);
						else
						    snprintf(desc,SIZE_OF_DESC,"CPU %d | APIC ID %d ",count,data3);
					    break;
					  }
					}
				}
			break;
			case 0x0C:
				if ( (rec->sel_type.standard_type.event_type == 0x0B) && 
						!(data1 & 0x03) ) 
					{
						if(data2 & 0x04)
							strcpy(desc,"Memory is in Spare Mode");
						else if(data2 & 0x02)
							strcpy(desc,"Memory is in Raid Mode ");
						else if(data2 & 0x01)
							strcpy(desc,"Memory is in Mirror Mode ");
						break;
					}
			case 0x10:				
				get_devid_ver(NULL,NULL,&iver);
		//		rv = ipmi_getdeviceid(devid,sizeof(devid),fdbg);
		//		if (rv != 0) return NULL;
				version = iver;
				/* Memory DIMMS */
				if( (data1 &  0x80) || (data1 & 0x20 ) )
				{
					if( (code == 0x0c) && (rec->sel_type.standard_type.event_type == 0x0B) )
					{
						if((data1 & 0x0f) == 0x00) 
						{
							snprintf(desc,SIZE_OF_DESC," Redundancy Regained | ");
						}
						else if((data1 & 0x0f) == 0x01)
						{
							snprintf(desc,SIZE_OF_DESC,"Redundancy Lost | ");
						}
					}	
					else if(code == 0x0c) 
					{
						if((data1 & 0x0f) == 0x00)
						{
							if(rec->sel_type.standard_type.sensor_num == 0x1C)
							{
								if((data1 &  0x80) && (data1 & 0x20 ))
								{
									count = 0;
									snprintf(desc,SIZE_OF_DESC,"CRC Error on:");
									for(i=0;i<4;i++)
									{
										if((BIT(i))&(data2))
										{
											if(count)
											{
												str = desc+strlen(desc);
												*str++ = ',';
												 str = '\0';
						              			count = 0;
											}
											switch(i)
											{
												case 0: snprintf(tmpdesc,SIZE_OF_DESC,"South Bound Memory");
														strcat(desc,tmpdesc);
														count++;
														break;
												case 1:	snprintf(tmpdesc,SIZE_OF_DESC,"South Bound Config");
														strcat(desc,tmpdesc);
														count++;
														break;
												case 2: snprintf(tmpdesc,SIZE_OF_DESC,"North Bound memory");
														strcat(desc,tmpdesc);
														count++;
														break;
												case 3:	snprintf(tmpdesc,SIZE_OF_DESC,"North Bound memory-corr");
														strcat(desc,tmpdesc);
														count++;
														break;
												default:
														break;
											}
										}
									}
									if(data3>=0x00 && data3<0xFF)
									{
										snprintf(tmpdesc,SIZE_OF_DESC,"|Failing_Channel:%d",data3);
										strcat(desc,tmpdesc);
									}
								}
								break;
							}
							snprintf(desc,SIZE_OF_DESC,"Correctable ECC | ");
						}
						else if((data1 & 0x0f) == 0x01) 
						{
							snprintf(desc,SIZE_OF_DESC,"UnCorrectable ECC | ");
						}
					} 
					else if(code == 0x10)
					{
						if((data1 & 0x0f) == 0x00) 
							snprintf(desc,SIZE_OF_DESC,"Corr Memory Log Dissabled | ");
					}
				} 
				else
				{
					if(code == 0x12) 
					{
						if((data1 & 0x0f) == 0x02) 
							snprintf(desc,SIZE_OF_DESC,"Unknown System Hardware Failure ");
					}
					if(code == 0x10)
					{
						if((data1 & 0x0f) == 0x03) 
							snprintf(desc,SIZE_OF_DESC,"All Even Logging Dissabled");
					}
				}
				if(data1 & 0x80 ) 
				{
					if(((data2 >> 4) != 0x0f) && ((data2 >> 4) < 0x08))
					{
						tmpData = 	('A'+ (data2 >> 4));
						if( (code == 0x0c) && (rec->sel_type.standard_type.event_type == 0x0B) )
						{
							snprintf(tmpdesc, SIZE_OF_DESC, "Bad Card %c", tmpData);								
						}
						else
						{
							snprintf(tmpdesc, SIZE_OF_DESC, "Card %c", tmpData);
						}
						strcat(desc, tmpdesc);
					}
					if (0x0F != (data2 & 0x0f)) 
					{
						if(0x51  == version)
						{
							snprintf(tmpdesc, SIZE_OF_DESC, "Bank %d", ((data2 & 0x0f)+1));	
							strcat(desc, tmpdesc);
						}
						else 
						{
							incr = (data2 & 0x0f) << 3;
						}
					}
					
				}
				if(data1 & 0x20 )
				{
					if(0x51  == version) 
					{
						snprintf(tmpdesc, SIZE_OF_DESC, "DIMM %s", ('A'+ data3));
						strcat(desc, tmpdesc);						
					} 
					else if( ((data2 >> 4) > 0x07) && ((data2 >> 4) != 0x0F)) 
					{
						strcpy(dimmStr, " DIMM_");
						str = desc+strlen(desc);
						dimmsPerNode = 4;
						if( (data2 >> 4) == 0x09) dimmsPerNode = 6;
						else if( (data2 >> 4) == 0x0A) dimmsPerNode = 8;
						else if( (data2 >> 4) == 0x0B) dimmsPerNode = 9;
						else if( (data2 >> 4) == 0x0C) dimmsPerNode = 12;
						else if( (data2 >> 4) == 0x0D) dimmsPerNode = 24;	
						else if( (data2 >> 4) == 0x0E) dimmsPerNode = 3;							
						count = 0;
				        for (i = 0; i < 8; i++)
				        {
				          if (BIT(i) & data3)
				          {
				            if (count)
				            {
				              *str++ = ',';
				              count = 0;
				            }
				            node = (incr + i)/dimmsPerNode;
				            dimmNum = ((incr + i)%dimmsPerNode)+1;
				            dimmStr[5] = node + 'A';
				            sprintf(tmpdesc,"%d",dimmNum);
				            dimmStr[6] = tmpdesc[0];
							dimmStr[7] = '\0'; 
							strcat(str,dimmStr);
				            count++;
				          }
				        }
					} 
					else 
					{
				        strcpy(dimmStr, " DIMM");
						str = desc+strlen(desc);
				        count = 0;
				        for (i = 0; i < 8; i++)
				        {
				          if (BIT(i) & data3)
				          {
				            // check if more than one DIMM, if so add a comma to the string.
				            if (count)
				            {
				              *str++ = ',';
				              count = 0;
				            }
				            sprintf(tmpdesc,"%d",(i + incr + 1));
							dimmStr[4] = tmpdesc[0];
							dimmStr[5] = '\0'; 
				            strcat(str, dimmStr);
				            count++;
				          }
				        }
			        }
				}
			break;
			case 0x20:
				if(((data1 & 0x0f)== 0x00)&&((data1 & 0x80) && (data1 & 0x20)))
				{
					if((data2 > 0x00)&&(data2<0xFF))
					{
						//Add the code to display 194 entries.This sensor present only in ORCA
						
					}	
					switch(data3)
					{
						case 0x01:
							snprintf(desc,SIZE_OF_DESC,"BIOS TXT Error");
							break;
						case 0x02:
							snprintf(desc,SIZE_OF_DESC,"Processor/FIT TXT");
							break;
						case 0x03:
							snprintf(desc,SIZE_OF_DESC,"BIOS ACM TXT Error");
							break;
						case 0x04:
							snprintf(desc,SIZE_OF_DESC,"SINIT ACM TXT Error");
							break;
						case 0xff:
							snprintf(desc,SIZE_OF_DESC,"Unrecognized TT Error12");
							break;
						default:
							break;						
					}
				}
			break;	
			case 0x23:
				
				if(data1 == 0xC1)
				{
					if(data2 == 0x04)
					{
						snprintf(desc,SIZE_OF_DESC,"Hard Reset|Interrupt type None,SMS/OS Timer used at expiration");
					}
				}	
				
			break;
			case 0x2B:
				if(((data1 & 0x0f)== 0x02)&&((data1 & 0x80) && (data1 & 0x20)))
				{
					if(data2 == 0x02)
					{
						if(data3 == 0x00)
						{
							snprintf(desc, SIZE_OF_DESC, "between BMC/iDRAC Firmware and other hardware");
						}
						else if(data3 == 0x01)
						{
							snprintf(desc, SIZE_OF_DESC, "between BMC/iDRAC Firmware and CPU");
						}
					}
				}
			break;	
			
			case 0xC1:
				if(rec->sel_type.standard_type.sensor_num == 0x25)
				{
					if((data1 & 0x0f) == 0x01)
					{
						snprintf(desc, SIZE_OF_DESC, "Failed to program Virtual Mac Address");
						if((data1 & 0x80)&&(data1 & 0x20))
						{
							snprintf(tmpdesc, SIZE_OF_DESC, "PCI %.2x:%.2x.%x",
							data3 &0x7f, (data2 >> 3) & 0x1F, 
							data2 & 0x7);
						}
					}
					else if((data1 & 0x0f) == 0x02)
					{
						snprintf(desc, SIZE_OF_DESC, "Device option ROM failed to support link tuning or flex address");
						if((data1 & 0x80)&&(data1 & 0x20))
						{
							//Add Mezzanine code here.DELLOEM SEL displayed unknown event
						}
					}
					else if((data1 & 0x0f) == 0x03)
					{
						snprintf(desc, SIZE_OF_DESC, "Failed to get link tuning or flex address data from BMC/iDRAC");
					}
					strcat(desc,tmpdesc);
				}
			break;	
			case 0x13:
			case 0xC2:
			case 0xC3:	
				if(rec->sel_type.standard_type.sensor_num == 0x29)
				{
					if(((data1 & 0x0f)== 0x02)&&((data1 & 0x80) && (data1 & 0x20)))
					{
					#if 1 /*This sensor is not implemented in iDRAC code*/
						snprintf(tmpdesc, SIZE_OF_DESC, "Partner-(LinkId:%d,AgentId:%d)|",(data2 & 0xC0),(data2 & 0x30));
						strcat(desc,tmpdesc);
						snprintf(tmpdesc, SIZE_OF_DESC, "ReportingAgent(LinkId:%d,AgentId:%d)|",(data2 & 0x0C),(data2 & 0x03));
						strcat(desc,tmpdesc);
						if((data3 & 0xFC) == 0x00)
						{
							snprintf(tmpdesc, SIZE_OF_DESC, "LinkWidthDegraded|");
							strcat(desc,tmpdesc);
						}
						if(BIT(1)& data3)
						{
							snprintf(tmpdesc,SIZE_OF_DESC,"PA_Type:IOH|");
						}
						else
						{
							snprintf(tmpdesc,SIZE_OF_DESC,"PA-Type:CPU|");
						}
						strcat(desc,tmpdesc);
						if(BIT(0)& data3)
						{
							snprintf(tmpdesc,SIZE_OF_DESC,"RA-Type:IOH");
						}
						else
						{
							snprintf(tmpdesc,SIZE_OF_DESC,"RA-Type:CPU");
						}
						strcat(desc,tmpdesc);
					#endif	
					}
				}
				else
				{
					
					if((data1 & 0x0f) == 0x02) 
					{
						sprintf(desc,"%s","IO channel Check NMI");
					}
					else 
					{
						if((data1 & 0x0f) == 0x00)
						{
							snprintf(desc, SIZE_OF_DESC, "%s","PCIe Error |"); 
						}
						else if((data1 & 0x0f) == 0x01) 
						{
							snprintf(desc, SIZE_OF_DESC, "%s","I/O Error |"); 
						}
						else if((data1 & 0x0f) == 0x04) 
						{
							snprintf(desc, SIZE_OF_DESC, "%s","PCI PERR |"); 
						} 
						else if((data1 & 0x0f) == 0x05)
						{
							snprintf(desc, SIZE_OF_DESC, "%s","PCI SERR |");
						} 
						else 
						{
							snprintf(desc, SIZE_OF_DESC, "%s"," ");
						}
						if (data3 & 0x80)
							snprintf(tmpdesc, SIZE_OF_DESC, "Slot %d", data3 & 0x7f);
						else
							snprintf(tmpdesc, SIZE_OF_DESC, "PCI %.2x:%.2x.%x",
							data3 &0x7f, (data2 >> 3) & 0x1F, 
							data2 & 0x7);
						strcat(desc,tmpdesc);
					}
				}
			break;	
			case 0x0F:	
				if(((data1 & 0x0f)== 0x0F)&&(data1 & 0x80))
				{
					switch(data2)
					{
						case 0x80:
							snprintf(desc, SIZE_OF_DESC, "No memory is detected.");break;
						case 0x81:	
							snprintf(desc,SIZE_OF_DESC, "Memory is detected but is not configurable.");break;
						case 0x82:
							snprintf(desc, SIZE_OF_DESC, "Memory is configured but not usable.");break;
						case 0x83:
							snprintf(desc, SIZE_OF_DESC, "System BIOS shadow failed.");break;
						case 0x84:	
							snprintf(desc, SIZE_OF_DESC, "CMOS failed.");break;
						case 0x85:	
							snprintf(desc, SIZE_OF_DESC, "DMA controller failed.");break;
						case 0x86:	
							snprintf(desc, SIZE_OF_DESC, "Interrupt controller failed.");break;
						case 0x87:
							snprintf(desc, SIZE_OF_DESC, "Timer refresh failed.");break;
						case 0x88:
							snprintf(desc, SIZE_OF_DESC, "Programmable interval timer error.");break;
						case 0x89:
							snprintf(desc, SIZE_OF_DESC, "Parity error.");break;
						case 0x8A:
							snprintf(desc, SIZE_OF_DESC, "SIO failed.");break;
						case 0x8B:	
							snprintf(desc, SIZE_OF_DESC, "Keyboard controller failed.");break;
						case 0x8C:	
							snprintf(desc, SIZE_OF_DESC, "System management interrupt initialization failed.");break;
						case 0x8D:	
							snprintf(desc, SIZE_OF_DESC, "TXT-SX Error.");break;
						case 0xC0:
							snprintf(desc, SIZE_OF_DESC, "Shutdown test failed.");break;
						case 0xC1:	
							snprintf(desc, SIZE_OF_DESC, "BIOS POST memory test failed.");break;
						case 0xC2:	
							snprintf(desc, SIZE_OF_DESC, "RAC configuration failed.");break;
						case 0xC3:	
							snprintf(desc, SIZE_OF_DESC, "CPU configuration failed.");break;
						case 0xC4:	
							snprintf(desc, SIZE_OF_DESC, "Incorrect memory configuration.");break;
						case 0xFE:	
							snprintf(desc, SIZE_OF_DESC, "General failure after video.");
							break;
					}
				}
			break;
			
			default:
			break;				
		} 
	}
	else
	{
		code = rec->sel_type.standard_type.event_type;
	}
	return desc;
}

/* 
 * decode_sel_dell
 * inputs:
 *    evt    = the 16-byte IPMI SEL event
 *    outbuf = points to the output string buffer
 *    outsz  = size of the output buffer
 * outputs: 
 *    rv     = 0 if this event was successfully interpreted here,
 *             non-zero otherwise, to use default interpretations.
 *    outbuf = will contain the interpreted event text string (if rv==0)
 */
int decode_sel_dell(uint8_t *evt, char *outbuf, int outsz, char fdesc, 
			char fdbg)
{
   int rv = -1;
   uint16_t id, genid;
   uint8_t rectype;
   uint32_t timestamp;
   char timestr[40]; 
   char *type_str = NULL;
   char *gstr = NULL;
   char *pstr = NULL;
   int sevid;
   uchar stype, snum;

   fdebug = fdbg;
   sevid = SEV_INFO;
   id = evt[0] + (evt[1] << 8);
   rectype = evt[2];
   timestamp = evt[3] + (evt[4] << 8) + (evt[5] << 16) + (evt[6] << 24);
   genid = evt[7] | (evt[8] << 8);
   stype = evt[10];
   snum = evt[11];
   gstr = "BMC ";
   if (genid == 0x0033) gstr = "Bios";
   type_str = "";
   if (rectype == 0x02) type_str = get_sensor_type_desc(stype);

#ifdef OTHER
   /* evt[13] is data1/offset*/
   if ( ((evt[13] & DATA_BYTE2_SPECIFIED_MASK) == 0x80) ||
        ((evt[13] & DATA_BYTE3_SPECIFIED_MASK) == 0x20) ) {
	      // if (evt[13] & DATA_BYTE2_SPECIFIED_MASK)
	 	 // evt->data = rec->sel_type.standard_type.event_data[1];
              pstr = get_dell_evt_desc(evt);
    } else if (evt[13] == 0xC1) {
        if (snum == 0x23) {
              //     evt->data = rec->sel_type.standard_type.event_data[1];
              pstr = get_dell_evt_desc(evt);
	}
    }    
#endif
   pstr = get_dell_evt_desc(evt);
   if (pstr != NULL) rv = 0;

   if (rv == 0) {
	char sensdesc[36];
	uchar sdr[120];
	sensdesc[0] = 0;
	if (fdesc) {
           rv = get_sensor_tag(0,genid,snum,sensdesc,sdr,sizeof(sdr));
	   if (fdebug) printf("get_sensor_tag(%x) rv = %d\n",snum,rv);
	   if (rv != 0) rv = 0;
	}
	fmt_time(timestamp, timestr, sizeof(timestr));
	snprintf(outbuf,outsz, "%04x %s %s %s %s #%02x %s%s\n",
                        id,timestr,get_sev_str(sevid), gstr, type_str, 
                        snum, sensdesc, /*sensor number, sensor desc */
                        pstr);    /*evt description*/
   }
   return rv;
}

/* end oem_newisys.c */
#ifdef METACOMMAND
int i_delloem(int argc, char **argv)
#else
#ifdef WIN32
int __cdecl
#else
int
#endif
main(int argc, char **argv)
#endif
{
   int rv = 0;
   uchar devrec[16];
   int c, i;
   char *s1;

   printf("%s ver %s\n", progname,progver);
   set_loglevel(LOG_NOTICE);
   argc_sav = argc;
   argv_sav = argv;
   parse_lan_options('V',"4",0);  /*default to admin priv*/

   while ( (c = getopt( argc, argv,"m:s:xzEF:J:N:P:R:T:U:V:YZ:?")) != EOF )
      switch(c) {
          case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */
                    g_bus = htoi(&optarg[0]);  /*bus/channel*/
                    g_sa  = htoi(&optarg[2]);  /*device slave address*/
                    g_lun = htoi(&optarg[4]);  /*LUN*/
                    g_addrtype = ADDR_IPMB;
                    if (optarg[6] == 's') {
                             g_addrtype = ADDR_SMI;  s1 = "SMI";
                    } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; }
                    ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype);
                    printf("Use MC at %s bus=%x sa=%x lun=%x\n",
                            s1,g_bus,g_sa,g_lun);
                    break;
          case 's': sdrfile = optarg; break;
          case 'x': fdebug = 2; /* normal (dbglog if isol) */
                    verbose = 1;
                    break;
          case 'z': fdebug = 3; /*full debug (for isol)*/
                    verbose = 1;
                    break;
          case 'N':    /* nodename */
          case 'U':    /* remote username */
          case 'P':    /* remote password */
          case 'R':    /* remote password */
          case 'E':    /* get password from IPMI_PASSWORD environment var */
          case 'F':    /* force driver type */
          case 'T':    /* auth type */
          case 'J':    /* cipher suite */
          case 'V':    /* priv level */
          case 'Y':    /* prompt for remote password */
          case 'Z':    /* set local MC address */
                parse_lan_options(c,optarg,fdebug);
                break;
          default:
		usage();
                rv = ERR_USAGE;
                goto do_exit;
                break;
      }
   rv = ipmi_getdeviceid(devrec,16,fdebug);
   if (rv == 0) {
      char ipmi_maj, ipmi_min;
      ipmi_maj = devrec[4] & 0x0f;
      ipmi_min = devrec[4] >> 4;
      // vend_id = devrec[6] + (devrec[7] << 8) + (devrec[8] << 16);
      // prod_id = devrec[9] + (devrec[10] << 8);
      show_devid( devrec[2],  devrec[3], ipmi_maj, ipmi_min);
   }
   for (i = 0; i < optind; i++) { argv++; argc--; }

   rv = ipmi_delloem_main(NULL, argc, argv);

do_exit:
   ipmi_close_();
   return(rv);
}
/* end oem_dell.c */
