/*
 * Copyright (c) 2005 Endace Technology Ltd, Hamilton, New Zealand.
 * All rights reserved.
 *
 * This source code is proprietary to Endace Technology Limited and no part
 * of it may be redistributed, published or disclosed except as outlined in
 * the written contract supplied with this product.
 *
 */
/* 
* this component is presented on all card since 5.0 onwards which has a 
* SFP or XFP modules at the moment the assumptions are :
* that the FW has to have enumeration entry for DAG_REG_XFP
* and version 0 is used for XFP modules, version 1 is used for SFP modules 
*/

/* -- DESCRIPTION XFP module version 0:
-- This module provides the DRB register and the signal connection
-- to the connected XFP module.
--
-- The module implements one DRB Register with the following bits:
-- Bit  Type    Description
--  0   RW      SCL - Serial Clock Line
--  1   RW      SDA - Serial Data Line
--  2   RO      Module absent signal; 1=Module is absent (it is 0 Module detect )
--  3   RO      Module not ready; 1=Module not ready - Not Implemented in SW
--  4   RW      Power down / Reset XFT; 1=Power Down
--  5   RW      Deselect module; 1=deselect  - Not implemented in SW
--  6   RW      Disable TX; 1=Disable
--  7   RO      RX LoS (Loss Of Signal); 1=Lost RX signal
--  8   RO      Interrupt Pending; 0=Pending interrupt - Not implemented 
*/

/*
A new module is introduced for the SFP
   Enum table: MOD_XFP/DAG_REG_XFP - Version 0x1
   Register amount: 1
   Bits:
    -- Bit    Type    Description
    --  0    RW    SDA - Serial Data Line
    --  1    RW    SCL - Serial Clock Line
    --  2    RO    Module absent signal; 1=Module is absent
    --  3    0    reserved. Current Assumption is this bit is equivalent to Module not ready, and should be implemented s TXFault maybe 
    --  4    0    reserved
    --  5    0    reserved
    --  6    RW    Disable TX / Laser off; 1=Disable/Laser off
    --  7    RO    LOS; 1=Lost of signal
    --  8    0    reserved
*/

/* Internal project headers. */
#include "../include/attribute.h"
#include "../include/card.h"
#include "../include/cards/card_initialization.h"
#include "../include/component.h"
#include "../include/util/utility.h"
#include "../include/components/xfp_component.h"
#include "../include/create_attribute.h"

#include "dagutil.h"

/* C Standard Library headers. */
#include <assert.h>
#if defined(__FreeBSD__) || defined(__linux__) || (defined(__APPLE__) && defined(__ppc__))
#include <inttypes.h>
#endif
#include <stdlib.h>
#include <string.h>

/* POSIX headers. */
#if defined(__FreeBSD__) || defined(__linux__) || (defined(__APPLE__) && defined(__ppc__))
#include <unistd.h>
#endif
/* macros */
#define  XFP_SFP_STRING_SIZE 512

typedef struct
{
    uint32_t mBase;
    uint32_t mPortNumber;
    uint32_t mVersion;
} xfp_state_t;

/* detect attribute. */
//static void* xfp_detect_get_value(AttributePtr attribute);


typedef struct
{
    module_identifier_t module_type;
    const char* string;
} module_type_mapping_t;

static module_type_mapping_t table[] =
{
    {kInvalidModuleType ,"Invalid Module/No Module"},
    {kUnknown ,"Unknown"},
    {kGBIC, "GBIC"},
    {kSolderedConnector,"SolderedConnector"},
    {kSFP,"SFP"},
    {kXBI300Pin, "XBI300Pin"},
    {kXENPAK, "XENPAK"},
    {kXFP,"XFP"},
    {kXFF, "XFF"},
    {kXPFE, "XPFE"},
    {kXPAK ,"XPAK"},
    {kX2 ,"X2"},
};

static char* transceiver_compliance_strings_xfp[] =
{
    /*10G Ethernet Compliance Codes */
    "10GBASE-SR, ",
    "10GBASE-LR, ",
    "10GBASE-ER, ",
    "10GBASE-LRM, ",
    "10GBASE-SW, ",
    "10GBASE-LW, ",
    "10GBASE-EW, ",
    "",/*reserved*/
    /* 10 Gigabit Fibre Channel Compliance*/
    "1200-MX-SN-I, ",
    "1200-SM-LL-L, ",
    "ExtendedReach-1550nm, ",
    "IntermediateReach-1300nmFP, ",
    "",/*reserved*/
     "",/*reserved*/
     "",/*reserved*/
     "",/*reserved*/
    /* 10 Gigabit Copper Links*/
    "",/*reserved*/
    "",/*reserved*/
    "",/*reserved*/
    "",/*reserved*/
    "",/*reserved*/
    "",/*reserved*/
    "",/*reserved*/
    "",/*reserved*/
    /* Lower Speed Links */
    "1000BASE-SX/1xFCMMF, ",
    "1000BASE-LX/1xFCSMF, ",
    "2xFCMMF, ",
    "2xFCSMF, ",
    "OC48SR, ",
    "OC48IR, ",
    "OC48LR, ",
    "",/*reserved */
    /*SONET/SDH Codes - Interconnect*/
    "I-64.1r, ",
    "I-64.1, ",
    "I-64.2r, ",
    "I-64.2, ",
    "I-64.3, ",
    "I-64.5, ",
    "",/*reserved*/
    "",/*reserved*/
    /*SONET/SDH Codes – Short Haul*/
    "S-64.1, ",
    "S-64.2a, ",
    "S-64.2b, ",
    "S-64.3a, ",
    "S-64.3b, ",
    "S-64.5a, ",
    "S-64.5b, ",
    "",/*reserved*/
    /* SONET/SDH Codes – Long Haul */
    "L-64.1, ",
    "L-64.2a, ",
    "L-64.2b, ",
    "L-64.2c, ",
    "L-64.3, ",
    "G.959.1P1L1-2D2, ",
    "",/*reserved*/
    "",/*reserved*/
    /* SONET/SDH Codes – Very Long Haul*/
    "V-64.2a, ",
    "V-64.2b, ",
    "V-64.3, ",
    "",/*reserved*/
    "",/*reserved*/
    "",/*reserved*/
    "",/*reserved*/
    "",/*reserved*/
};

       
static char* transceiver_compliance_strings[] =
{
    /*10G Ethernet Compliance Codes */
    "10G Base-ER, ",
    "10G Base-LRM, ",
    "10G Base-LR, ",
    "10G Base-SR, ",
    /*Infiniband Compliance Codes */
    "1X SX, ",
    "1X LX, ",
    "1X Copper Active, ",
    "1X Copper Passive, ",
    /*ESCON Compliance Codes*/
    "ESCON MMF 1310nm LED, ",
    "ESCON SMF 1310nm Laser, ",
    /*SONET Compliance Codes*/
    "OC-192 short reach, ",
    "SONET reach specifier bit 1, ",
    "SONET reach specifier bit 2, ",
    "OC-48 long reach, ",
    "OC-48 intermediate reach, ",
    "OC-48 short reach, ",
    "Unallocated, ",
    "OC-12 single mode, long reach, ",
    "OC-12 single mode, inter. reach, ",
    "OC-12 short reach, ",
    "Unallocated, ",
    "OC-3 single mode, long reach, ",
    "OC-3 single mode, inter. reach, ",
    "OC-3 short reach, ",
    /*  Ethernet Compliance Codes*/
    "BASE-PX, ",
    "BASE-BX10, ",
    "100BASE-FX, ",
    "100BASE-LX/LX10, ",
    "1000BASE-T, ",
    "1000BASE-CX, ",
    "1000BASE-LX, ",
    "1000BASE-SX , ",
};
static char* fibre_link_length_strings[] =
{
    "very long distance (V) ",
    "short distance (S) ",
    "intermediate distance (I) ",
    "long distance (L) ",
    "medium distance (M) ",
};

static char* fibre_tr_media_strings[] = 
{
    "Twin Axial Pair (TW) ",
    "Twisted Pair (TP) ",
    "Miniature Coax (MI) ",
    "Video Coax (TV) ",
    "Multimode, 62.5um (M6) ",
    "Multimode, 50um (M5)",
    "Unallocated ",
    "Single Mode (SM)"
};
static const char* module_type_to_string(module_identifier_t type);
/* xfp  */
static void xfp_dispose(ComponentPtr component);
static void xfp_reset(ComponentPtr component);
static void xfp_default(ComponentPtr component);
static int xfp_post_initialize(ComponentPtr component);
static dag_err_t xfp_update_register_base(ComponentPtr component);

/* signal */
//static void* xfp_los_get_value(AttributePtr attribute);

/* sfppwr */
//static void* xfp_pwr_get_value(AttributePtr attribute);
//static void xfp_pwr_set_value(AttributePtr attribute, void* value, int length);

static void* module_identifier_get_value(AttributePtr attribute);
static void module_identifier_to_string(AttributePtr attribute);

static void* extended_module_identifier_get_value(AttributePtr attribute);

static void* transceiver_codes_get_value(AttributePtr attribute);
//static void transceiver_code_to_string(AttributePtr attribute);
static void* vendor_name_get_value(AttributePtr attribute);
static void* vendor_pn_get_value(AttributePtr attribute);
static void common_to_string_function(AttributePtr attribute);

static void* link_length_get_value(AttributePtr attribute);
static void* transmission_media_get_value(AttributePtr attribute);
static void* diagnostic_monitoring_get_value(AttributePtr attribute);

static void* transceiver_temperature_get_value(AttributePtr attribute); 
static void* transceiver_voltage_get_value(AttributePtr attribute);
static void* transceiver_tx_power_get_value(AttributePtr attribute);
static void* transceiver_rx_power_get_value(AttributePtr attribute);

static void* transceiver_temperature_low_get_value(AttributePtr attribute); 
static void* transceiver_voltage_low_get_value(AttributePtr attribute);
static void* transceiver_tx_power_low_get_value(AttributePtr attribute);
static void* transceiver_rx_power_low_get_value(AttributePtr attribute);

static void* transceiver_temperature_high_get_value(AttributePtr attribute); 
static void* transceiver_voltage_high_get_value(AttributePtr attribute);
static void* transceiver_tx_power_high_get_value(AttributePtr attribute);
static void* transceiver_rx_power_high_get_value(AttributePtr attribute);

static uint8_t is_ext_calibarated(DagCardPtr card, xfp_state_t* state);
static uint8_t is_rx_power_in_oma(AttributePtr attribute);

static void* sfp_temperature_get_value(AttributePtr attribute, uint8_t byte_addr); 
static void* sfp_voltage_get_value(AttributePtr attribute, uint8_t byte_addr);
static void* sfp_tx_power_get_value(AttributePtr attribute, uint8_t byte_addr);
static void* sfp_rx_power_get_value(AttributePtr attribute, uint8_t byte_addr);

static void* xfp_temperature_get_value(AttributePtr attribute, uint8_t byte_addr); 
static void* xfp_voltage_get_value(AttributePtr attribute, uint8_t byte_addr);
static void* xfp_tx_power_get_value(AttributePtr attribute, uint8_t byte_addr);
static void* xfp_rx_power_get_value(AttributePtr attribute, uint8_t byte_addr);

static float calculate_tx_power_in_milli_watt(uint8_t msb, uint8_t lsb, float tx_pwr_slope, int16_t tx_pwr_offset);
static float calculate_temperature_in_degree_celsius(int8_t msb, uint8_t lsb, float temp_slope, int16_t temp_offset);
static float calculate_rx_power_in_milli_watt(uint8_t msb, uint8_t lsb, float* coeffient_array);
int transceiver_get_msb_lsb( DagCardPtr card, uint32_t port_index, uint16_t serial_addr, uint8_t byte_addr, uint8_t *ptr_msb, uint8_t* ptr_lsb);
int transceiver_get_single_precision_float( DagCardPtr card, uint32_t port_index, uint16_t serial_addr, uint8_t byte_addr, float *ptr_float);
static void transceiver_power_to_string_routine(AttributePtr attribute);
static void transceiver_temperature_to_string_routine(AttributePtr attribute);
static void transceiver_voltage_to_string_routine(AttributePtr attribute);
static int xfp_select_upper_mem_map_page( DagCardPtr card, uint32_t port_index, uint8_t page);
static uint8_t xfp_get_supply_voltage_aux_input_number(AttributePtr attribute);

static void enable_full_rate_set_value(AttributePtr attribute,void *value, int length);
static void* enable_full_rate_get_value(AttributePtr attribute);

static void* transceiver_power_level_get_value(AttributePtr attribute);
static void transceiver_power_level_state_set_value(AttributePtr attribute,void *value, int length);
static void* transceiver_power_level_state_get_value(AttributePtr attribute);

Attribute_t xfp_sfp_attr[]=
{
   
   {
        /* Name */                 "detect",
        /* Attribute Code */       kBooleanAttributeDetect,
        /* Attribute Type */       kAttributeBoolean,
        /* Description */          "Detect presence of XFP/SFP module.",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,
        /* Register Address */     DAG_REG_XFP,
        /* Offset */               0,
        /* Size/length */          1,
        /* Read */                 grw_iom_read,
        /* Write */                grw_iom_write,
        /* Mask */                 BIT2,
        /* Default Value */        1,
        /* SetValue */             attribute_boolean_set_value,
	/* GetValue */             attribute_boolean_get_value,
	/* SetToString */          attribute_boolean_to_string,
	/* SetFromString */        attribute_boolean_from_string,
	/* Dispose */              attribute_dispose,
	/* PostInit */             attribute_post_initialize,
    },
 
	{
        /* Name */                 "physical_los",
        /* Attribute Code */       kBooleanAttributeLossOfSignal,
        /* Attribute Type */       kAttributeBoolean,
        /* Description */          "Loss of signal from the SFP/XFP module.",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    7,
        /* Register Address */     DAG_REG_XFP,
        /* Offset */               0,
        /* Size/length */          1,
        /* Read */                 grw_iom_read,
        /* Write */                grw_iom_write,
        /* Mask */                 BIT7,
        /* Default Value */        1,
        /* SetValue */             attribute_boolean_set_value,
	/* GetValue */             attribute_boolean_get_value,
	/* SetToString */          attribute_boolean_to_string,
	/* SetFromString */        attribute_boolean_from_string,
	/* Dispose */              attribute_dispose,
	/* PostInit */             attribute_post_initialize,
	},
	/*This attribute is only for XFP */
	{
        /* Name */                 "laser",
        /* Attribute Code */       kBooleanAttributeLaser,
        /* Attribute Type */       kAttributeBoolean,
        /* Description */          "Shows if laser or TX is powered",
        /* Config-Status */        kDagAttrConfig,
        /* Index in register */    6,
        /* Register Address */     DAG_REG_XFP,
        /* Offset */               0,
        /* Size/length */          1,
        /* Read */                 grw_iom_read,
        /* Write */                grw_iom_write,
        /* Mask */                 BIT6,
        /* Default Value */        1,
        /* SetValue */             attribute_boolean_set_value,
	/* GetValue */             attribute_boolean_get_value,
	/* SetToString */          attribute_boolean_to_string,
	/* SetFromString */        attribute_boolean_from_string,
	/* Dispose */              attribute_dispose,
	/* PostInit */             attribute_post_initialize,
    },
};

Attribute_t xfp_attr[]=
{

	/*This attribute is only for XFP */
	{
	/* Name */                 "optics_pwr",
	/* Attribute Code */       kBooleanAttributeSfpPwr,
	/* Attribute Type */       kAttributeBoolean,
	/* Description */          "Shows if module is powered",
	/* Config-Status */        kDagAttrConfig,
	/* Index in register */    4,
	/* Register Address */     DAG_REG_XFP,
	/* Offset */               0,
	/* Size/length */          1,
	/* Read */                 grw_iom_read,
	/* Write */                grw_iom_write,
	/* Mask */                 BIT4,
	/* Default Value */        1,
	/* SetValue */             attribute_boolean_set_value,
	/* GetValue */             attribute_boolean_get_value,
	/* SetToString */          attribute_boolean_to_string,
	/* SetFromString */        attribute_boolean_from_string,
	/* Dispose */              attribute_dispose,
	/* PostInit */             attribute_post_initialize,
    },
};
Attribute_t module_attr[] = 
{
    {
        /* Name */                 "module_identifier",
        /* Attribute Code */       kUint32AttributeTransceiverIdentifier,
        /* Attribute Type */       kAttributeUint32,
        /* Description */          "Module type identifier",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP, /* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             attribute_boolean_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             module_identifier_get_value,
        /* SetToString */          module_identifier_to_string,
        /* SetFromString */        attribute_boolean_from_string,/* Status attribute -funtion not needed*/
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "extended_identifier",
        /* Attribute Code */       kUint32AttributeTransceiverExtendedIdentifier,
        /* Attribute Type */       kAttributeUint32,
        /* Description */          "Extended Module type identifier",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP, /* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             attribute_boolean_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             extended_module_identifier_get_value,
        /* SetToString */          attribute_uint32_to_string,
        /* SetFromString */        attribute_boolean_from_string,/* Status attribute -funtion not needed*/
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    
    {
        /* Name */                 "vendor_name",
        /* Attribute Code */       kStringAttributeTransceiverVendorName,
        /* Attribute Type */       kAttributeString,
        /* Description */          "Vendor name of the module ",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP, /* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             attribute_boolean_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             vendor_name_get_value,
        /* SetToString */          common_to_string_function,
        /* SetFromString */        attribute_boolean_from_string,/* Status attribute -funtion not needed*/
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "vendor_pn",
        /* Attribute Code */       kStringAttributeTransceiverVendorPN,
        /* Attribute Type */       kAttributeString,
        /* Description */          "Vendor PN ",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP, /* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             attribute_boolean_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             vendor_pn_get_value,
        /* SetToString */          common_to_string_function,
        /* SetFromString */        attribute_boolean_from_string,/* Status attribute -funtion not needed*/
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "transceiver_compliances",
        /* Attribute Code */       kStringAttributeTransceiverCodes,
        /* Attribute Type */       kAttributeString,
        /* Description */          "Transceiver Compliance",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP, /* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             attribute_boolean_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             transceiver_codes_get_value,
        /* SetToString */          common_to_string_function,//transceiver_code_to_string,
        /* SetFromString */        attribute_boolean_from_string,/* Status attribute -funtion not needed*/
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "link_length",
        /* Attribute Code */       kStringAttributeTransceiverLinkLength,
        /* Attribute Type */       kAttributeString,
        /* Description */          "Fibre Channel link length",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP, /* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             attribute_boolean_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             link_length_get_value,
        /* SetToString */          common_to_string_function,
        /* SetFromString */        attribute_boolean_from_string,/* Status attribute -funtion not needed*/
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "transmission_media",
        /* Attribute Code */       kStringAttributeTransceiverMedia,
        /* Attribute Type */       kAttributeString,
        /* Description */          "Fibre Channel media",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP, /* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             attribute_boolean_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             transmission_media_get_value,
        /* SetToString */          common_to_string_function,
        /* SetFromString */        attribute_boolean_from_string,/* Status attribute -funtion not needed*/
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "diagnostic_monitoring",
        /* Attribute Code */       kBooleanAttributeTransceiverMonitoring,
        /* Attribute Type */       kAttributeBoolean,
        /* Description */          "Indicates diagnostic monitoring has been implemented",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP, /* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             attribute_boolean_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             diagnostic_monitoring_get_value,
        /* SetToString */          attribute_boolean_to_string,
        /* SetFromString */        attribute_boolean_from_string,/* Status attribute -funtion not needed*/
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "enable_full_rate",
        /* Attribute Code */       kBooleanAttributeEnableFullRate,
        /* Attribute Type */       kAttributeBoolean,
        /* Description */          "Enables the full line rate for a dual rate sfp+ module.",
        /* Config-Status */        kDagAttrConfig,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP,/* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             enable_full_rate_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             enable_full_rate_get_value,
        /* SetToString */          attribute_boolean_to_string,
        /* SetFromString */        attribute_boolean_from_string,
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "power_level",
        /* Attribute Code */       kUint32AttributeTransceiverPowerLevel,
        /* Attribute Type */       kAttributeUint32,
        /* Description */          "power level declaration by the module",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP,/* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             attribute_boolean_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             transceiver_power_level_get_value,
        /* SetToString */          attribute_uint32_to_string,
        /* SetFromString */        attribute_uint32_from_string,
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "power_level_state",
        /* Attribute Code */       kUint32AttributeTransceiverPowerLevelState,
        /* Attribute Type */       kAttributeUint32,
        /* Description */          "power level current state",
        /* Config-Status */        kDagAttrConfig,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP,/* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             transceiver_power_level_state_set_value,
        /* GetValue */             transceiver_power_level_state_get_value,
        /* SetToString */          attribute_uint32_to_string,
        /* SetFromString */        attribute_uint32_from_string,
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    }
};
/* following attributes are to be added only if the diagnostic_monitoring is set */
Attribute_t module_diagnostic_monitor_attributes[] =
{
    {
        /* Name */                 "module_temperature",
        /* Attribute Code */       kFloatAttributeTransceiverTemperature,
        /* Attribute Type */       kAttributeFloat,
        /* Description */          "Transceiver temperature",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP, /* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             attribute_boolean_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             transceiver_temperature_get_value,
        /* SetToString */          transceiver_temperature_to_string_routine,
        /* SetFromString */        attribute_boolean_from_string,/* Status attribute -funtion not needed*/
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
   {
        /* Name */                 "module_voltage",
        /* Attribute Code */       kFloatAttributeTransceiverVoltage,
        /* Attribute Type */       kAttributeFloat,
        /* Description */          "Transceiver supply voltage",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP, /* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             attribute_boolean_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             transceiver_voltage_get_value,
        /* SetToString */          transceiver_voltage_to_string_routine,
        /* SetFromString */        attribute_boolean_from_string,/* Status attribute -funtion not needed*/
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "rx_power",
        /* Attribute Code */       kFloatAttributeTransceiverRxPower,
        /* Attribute Type */       kAttributeFloat,
        /* Description */          "Internally measured RX Power",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP, /* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             attribute_boolean_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             transceiver_rx_power_get_value,
        /* SetToString */          transceiver_power_to_string_routine,
        /* SetFromString */        attribute_boolean_from_string,/* Status attribute -funtion not needed*/
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "tx_power",
        /* Attribute Code */       kFloatAttributeTransceiverTxPower,
        /* Attribute Type */       kAttributeFloat,
        /* Description */          "Internally measured TX Power",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP, /* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             attribute_boolean_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             transceiver_tx_power_get_value,
        /* SetToString */          transceiver_power_to_string_routine,
        /* SetFromString */        attribute_boolean_from_string,/* Status attribute -funtion not needed*/
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "module_temperature_low",
        /* Attribute Code */       kFloatAttributeTransceiverTemperatureLow,
        /* Attribute Type */       kAttributeFloat,
        /* Description */          "Transceiver temperature low threshold",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP, /* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             attribute_boolean_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             transceiver_temperature_low_get_value,
        /* SetToString */          transceiver_temperature_to_string_routine,
        /* SetFromString */        attribute_boolean_from_string,/* Status attribute -funtion not needed*/
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "module_temperature_high",
        /* Attribute Code */       kFloatAttributeTransceiverTemperatureHigh,
        /* Attribute Type */       kAttributeFloat,
        /* Description */          "Transceiver temperature high threshold",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP, /* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             attribute_boolean_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             transceiver_temperature_high_get_value,
        /* SetToString */          transceiver_temperature_to_string_routine,
        /* SetFromString */        attribute_boolean_from_string,/* Status attribute -funtion not needed*/
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "module_voltage_low",
        /* Attribute Code */       kFloatAttributeTransceiverVoltageLow,
        /* Attribute Type */       kAttributeFloat,
        /* Description */          "Transceiver supply voltage Low threshold",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP, /* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             attribute_boolean_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             transceiver_voltage_low_get_value,
        /* SetToString */          transceiver_voltage_to_string_routine,
        /* SetFromString */        attribute_boolean_from_string,/* Status attribute -funtion not needed*/
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "module_voltage_high",
        /* Attribute Code */       kFloatAttributeTransceiverVoltageHigh,
        /* Attribute Type */       kAttributeFloat,
        /* Description */          "Transceiver supply voltage high threshold",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP, /* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             attribute_boolean_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             transceiver_voltage_high_get_value,
        /* SetToString */          transceiver_voltage_to_string_routine,
        /* SetFromString */        attribute_boolean_from_string,/* Status attribute -funtion not needed*/
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "rx_power_low",
        /* Attribute Code */       kFloatAttributeTransceiverRxPowerLow,
        /* Attribute Type */       kAttributeFloat,
        /* Description */          "Internally measured RX Power low threshold",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP, /* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             attribute_boolean_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             transceiver_rx_power_low_get_value,
        /* SetToString */          transceiver_power_to_string_routine,
        /* SetFromString */        attribute_boolean_from_string,/* Status attribute -funtion not needed*/
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "rx_power_high",
        /* Attribute Code */       kFloatAttributeTransceiverRxPowerHigh,
        /* Attribute Type */       kAttributeFloat,
        /* Description */          "Internally measured RX Power high threshold",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP, /* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             attribute_boolean_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             transceiver_rx_power_high_get_value,
        /* SetToString */          transceiver_power_to_string_routine,
        /* SetFromString */        attribute_boolean_from_string,/* Status attribute -funtion not needed*/
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "tx_power_low",
        /* Attribute Code */       kFloatAttributeTransceiverTxPowerLow,
        /* Attribute Type */       kAttributeFloat,
        /* Description */          "Internally measured TX Power low threshold",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP, /* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             attribute_boolean_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             transceiver_tx_power_low_get_value,
        /* SetToString */          transceiver_power_to_string_routine,
        /* SetFromString */        attribute_boolean_from_string,/* Status attribute -funtion not needed*/
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "tx_power_high",
        /* Attribute Code */       kFloatAttributeTransceiverTxPowerHigh,
        /* Attribute Type */       kAttributeFloat,
        /* Description */          "Internally measured TX Power high threshold",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    2,/* dont care */
        /* Register Address */     DAG_REG_XFP, /* dont care */
        /* Offset */               0,/* dont care */
        /* Size/length */          1,/* dont care */
        /* Read */                 NULL,/* dont care */
        /* Write */                NULL,/* dont care */
        /* Mask */                 BIT2,/* dont care */
        /* Default Value */        1,/* dont care */
        /* SetValue */             attribute_boolean_set_value,/* Status attribute -funtion not needed*/
        /* GetValue */             transceiver_tx_power_high_get_value,
        /* SetToString */          transceiver_power_to_string_routine,
        /* SetFromString */        attribute_boolean_from_string,/* Status attribute -funtion not needed*/
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    
};
/* Number of elements in array */
#define NB_ELEM_XFP (sizeof(xfp_attr) / sizeof(Attribute_t))
#define NB_ELEM_XFP_SFP (sizeof(xfp_sfp_attr) / sizeof(Attribute_t))
#define NB_ELEM_MODULE_ATTR (sizeof(module_attr) / sizeof(Attribute_t))
#define NB_ELEM_MODULE_MONITOR_ATTR (sizeof(module_diagnostic_monitor_attributes) / sizeof(Attribute_t))

#define BUFFER_SIZE 1024

ComponentPtr
xfp_get_new_component(DagCardPtr card, uint32_t port_number)
{
    ComponentPtr result = component_init(kComponentOptics, card); 
    xfp_state_t* state = NULL;
    char buffer[BUFFER_SIZE];
    
    if (NULL != result)
    {
        component_set_dispose_routine(result, xfp_dispose);
        component_set_post_initialize_routine(result, xfp_post_initialize);
        component_set_reset_routine(result, xfp_reset);
        component_set_default_routine(result, xfp_default);
        component_set_update_register_base_routine(result, xfp_update_register_base);
        sprintf(buffer, "optics%d", port_number);
        component_set_name(result, buffer);
        state = (xfp_state_t*)malloc(sizeof(xfp_state_t));
        memset(state, 0, sizeof(xfp_state_t));
        state->mPortNumber = port_number;
	state->mBase = card_get_register_address(card, DAG_REG_XFP, state->mPortNumber);
	/* Note version 0 means XFP, version 1 means SFP */
	state->mVersion = card_get_register_version(card, DAG_REG_XFP, state->mPortNumber);
	
        component_set_private_state(result, state);
        
    }
    
    return result;
}


static void
xfp_dispose(ComponentPtr component)
{
}

static dag_err_t
xfp_update_register_base(ComponentPtr component)
{
    if (1 == valid_component(component))
    {
        DagCardPtr card = NULL;
		xfp_state_t* state = (xfp_state_t*)component_get_private_state(component);
		/* Get card reference */
		card = component_get_card(component);

        state->mBase = card_get_register_address(card, DAG_REG_XFP, state->mPortNumber);
        return kDagErrNone;
    }
    return kDagErrInvalidParameter;
}

static int
xfp_post_initialize(ComponentPtr component)
{
	DagCardPtr card = NULL;
	AttributePtr attribute = NULL;
	GenericReadWritePtr grw = NULL;  
    uint8_t *module_detect = NULL;
    uint8_t *diagnostic_monitor_present = NULL;
	
	xfp_state_t* xfp_state = (xfp_state_t*)component_get_private_state(component);

	/* Get card reference */
	card = component_get_card(component);
	
	// this is redundant with the new method 
	xfp_state->mBase = card_get_register_address(card, DAG_REG_XFP, xfp_state->mPortNumber);
	
	/* Add attribute of counter */ 
	read_attr_array(component, xfp_sfp_attr, NB_ELEM_XFP_SFP, xfp_state->mPortNumber);
	
	/* XFP module presented if version 0 if version 1 SFP module presented*/
	if( xfp_state->mVersion == 0 ) {
		
		/* Add attribute of counter */ 
		read_attr_array(component, xfp_attr, NB_ELEM_XFP, xfp_state->mPortNumber);
        /* set attribute with inverted boolean
	   * Usually set a bit means "write 1", but in these cases it means "write 0" */
	   attribute = component_get_attribute(component, kBooleanAttributeSfpPwr);
	   grw = attribute_get_generic_read_write_object(attribute);
	   grw_set_on_operation(grw, kGRWClearBit);
    
	}
	
	/* set attribute with inverted boolean
	   * Usually set a bit means "write 1", but in these cases it means "write 0" */
	attribute = component_get_attribute(component, kBooleanAttributeLaser);
	grw = attribute_get_generic_read_write_object(attribute);
	grw_set_on_operation(grw, kGRWClearBit);

    attribute = component_get_attribute(component, kBooleanAttributeDetect);
	grw = attribute_get_generic_read_write_object(attribute);
	grw_set_on_operation(grw, kGRWClearBit);

    /* use above attribute (kBooleanAttributeDetect) to check the presense of module and add the module attributes to the components */

    module_detect = (uint8_t*) attribute_boolean_get_value(attribute);
    if ( (NULL != module_detect) && (1 == *module_detect ) )
    {
        /* read the module attributes and fill in the component */
        read_attr_array( component, module_attr, NB_ELEM_MODULE_ATTR, xfp_state->mPortNumber);
    }

    /* check whether the digital diagnostic implementations are present, and 
     if so, add the temperature, voltage , power attributes */
    attribute = component_get_attribute(component, kBooleanAttributeTransceiverMonitoring);
    diagnostic_monitor_present = (uint8_t*) diagnostic_monitoring_get_value(attribute);
#if 1
    if ( (NULL != diagnostic_monitor_present) && (1 == *diagnostic_monitor_present ) )
    {
        read_attr_array( component, module_diagnostic_monitor_attributes, NB_ELEM_MODULE_MONITOR_ATTR, xfp_state->mPortNumber);
    }
#endif 
	/* Return 1 if standard post_initialize() should continue, 0 if not.
	* "Standard" post_initialize() calls post_initialize() recursively on subcomponents.
	*/
    return 1;
}

static void
xfp_reset(ComponentPtr component)
{
}


static void
xfp_default(ComponentPtr component)
{
    AttributePtr any_attr;
    void *ptr_attr = NULL;
    module_identifier_t module_type = kInvalidModuleType;
    uint32_t power_level = 0;
    
    /* if the SFP module declares power level2, enable it */
    if ( component_get_attribute_count_of_type(component, kUint32AttributeTransceiverIdentifier )  > 0 )
    {
        any_attr = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_attr = module_identifier_get_value(any_attr);
        if (NULL != ptr_attr) 
        {
            module_type = *((module_identifier_t*)ptr_attr);
        }
        any_attr = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_attr = module_identifier_get_value(any_attr);
        if (NULL != ptr_attr) 
        {
            module_type = *((module_identifier_t*)ptr_attr);
        }
        any_attr = component_get_attribute(component, kUint32AttributeTransceiverPowerLevel);
        ptr_attr = transceiver_power_level_get_value(any_attr);
        if (NULL != ptr_attr) 
        {
            power_level = *((uint32_t*)ptr_attr);
        }
    }
    if ( (module_type == kSFP) && (power_level > 1) )
    {
        any_attr = component_get_attribute(component, kUint32AttributeTransceiverPowerLevelState);
        transceiver_power_level_state_set_value(any_attr, &power_level, sizeof(power_level));
    }
    return;
}

void* module_identifier_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        GenericReadWritePtr sfp_grw = NULL;
        uint32_t address = 0;
        DagCardPtr card = attribute_get_card(attribute);
        ComponentPtr component = NULL;
        module_identifier_t  module_type = kInvalidModuleType;
        xfp_state_t* xfp_state =   NULL;
        
        component = attribute_get_component(attribute);
        xfp_state = (xfp_state_t*)component_get_private_state(component);
        address = 0xa0 << 8;
        address |= (xfp_state->mPortNumber << 16);

	    sfp_grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);

        assert(sfp_grw);
        module_type = (module_identifier_t)(int)grw_read(sfp_grw);
        attribute_set_value_array(attribute, &module_type, sizeof(module_identifier_t));
        grw_dispose(sfp_grw);
        return attribute_get_value_array(attribute);
    }
    return NULL;
}

void module_identifier_to_string(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        const char *string = NULL;
        module_identifier_t *ptr_type = NULL;

        ptr_type = (module_identifier_t*) module_identifier_get_value(attribute);
        if ( NULL != ptr_type )
        {
            string = module_type_to_string(*ptr_type);
        }
       // printf("Converted sttring %s\n",string);
        if( NULL != string )
        {
            attribute_set_to_string(attribute, string);
        }
        return;
     }
}

const char*
module_type_to_string(module_identifier_t type)
{
    int i;
    int count = sizeof(table)/sizeof(module_type_mapping_t);
    for (i = 0; i < count; i++)
    {
        if (table[i].module_type == type)
        {
            return table[i].string;
        }
    }
    return table[0].string;/* invalid module */
}


void* extended_module_identifier_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        GenericReadWritePtr sfp_grw = NULL;
        uint32_t address = 0;
        DagCardPtr card = attribute_get_card(attribute);
        ComponentPtr component = NULL;
        uint32_t extended_type = 0;
        xfp_state_t* xfp_state =   NULL;
        
        component = attribute_get_component(attribute);
        xfp_state = (xfp_state_t*)component_get_private_state(component);
        address = 0xa0 << 8;
        address |= (xfp_state->mPortNumber << 16);
        address |= 0x01;

	    sfp_grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);

        assert(sfp_grw);
        extended_type =  (uint32_t) grw_read(sfp_grw);
        attribute_set_value_array(attribute, &extended_type, sizeof(extended_type));
        grw_dispose(sfp_grw);
        return attribute_get_value_array(attribute);
    }
    return NULL;
}

void* vendor_name_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        GenericReadWritePtr sfp_grw = NULL;
        uint32_t address = 0;
        DagCardPtr card = attribute_get_card(attribute);
        ComponentPtr component = NULL;
        xfp_state_t* xfp_state =   NULL;
        char vendor_name[32] = {0};
        int i = 0;

        AttributePtr attr_mod_type; 
        module_identifier_t module_type = kInvalidModuleType;
        module_identifier_t *ptr_type = NULL;

        component = attribute_get_component(attribute);
        xfp_state = (xfp_state_t*)component_get_private_state(component);
        attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
        if( NULL != ptr_type  )
        {
           module_type = *ptr_type;
        }
        if(kUnknown == module_type)
        {
            strcpy(vendor_name,"Unknown Module");
        }
        else if( kXFP == module_type )
        {
            /* for XFP modules as defined by INF-8077i, it is a 2 level memory map (upper and lower). 
             To acces the upper memory map, the page should be selected in the byte 127 of lower map*/ 
            address = 0xa0 << 8;
            address |= (xfp_state->mPortNumber << 16);
            address |= 127;
            sfp_grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
            grw_write(sfp_grw, 0x01);
            address = (address & 0xffffff00) | 148; /* vendor name starts at the byte 148 of page 1*/
            grw_set_address(sfp_grw, address);
        }
        else if (kSFP == module_type)
        {
            
            address = 0xa0 << 8;
            address |= (xfp_state->mPortNumber << 16);
            address |= 20;/* vendor name starts at byte 20*/
            sfp_grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
        }
        else
        {
            strcpy(vendor_name,"Not Implemented");
        }

        if(sfp_grw)
        { 
           for( i = 0 ; i < 16; i++)
           {
                grw_set_address(sfp_grw, address);
                vendor_name[i] = (char) grw_read(sfp_grw);
                address++;
            }
            vendor_name[i] = '\0';
			grw_dispose(sfp_grw); /* memory leak fix */
        }
        
        attribute_set_value_array(attribute, vendor_name, strlen(vendor_name) + 1);
        return attribute_get_value_array(attribute);
    }
    return NULL;
}
void* vendor_pn_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        GenericReadWritePtr sfp_grw = NULL;
        uint32_t address = 0;
        DagCardPtr card = attribute_get_card(attribute);
        ComponentPtr component = NULL;
        xfp_state_t* xfp_state =   NULL;
        char vendor_pn[32] = {0};
        int i = 0;
        AttributePtr attr_mod_type; 
        module_identifier_t module_type = kInvalidModuleType;
        module_identifier_t *ptr_type = NULL;

        component = attribute_get_component(attribute);
        xfp_state = (xfp_state_t*)component_get_private_state(component);
        attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
        if( NULL != ptr_type  )
        {
           module_type = *ptr_type;
        }
        if( kUnknown == module_type)
        {
            strcpy(vendor_pn,"Unknown Module");
        }
        else if( kXFP == module_type )
        {
            /* for XFP modules as defined by INF-8077i, it is a 2 level memory map (upper and lower). 
             To acces the upper memory map, the page should be selected in the byte 127 of lower map*/ 
            address = 0xa0 << 8;
            address |= (xfp_state->mPortNumber << 16);
            address |= 127;
            sfp_grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
            grw_write(sfp_grw, 0x01);
            address = (address & 0xffffff00) | 168; /* vendor PN starts at the byte 168 of page 1*/
            grw_set_address(sfp_grw, address);
        }
        else if (kSFP == module_type)
        {
            
            address = 0xa0 << 8;
            address |= (xfp_state->mPortNumber << 16);
            address |= 40;/*vendor pn starts at byte 40*/
            sfp_grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
        }
        else
        {
            strcpy(vendor_pn,"Not Implemented");
        }
        
        if(sfp_grw)
        { 
           for( i = 0 ; i < 16; i++)
           {
                grw_set_address(sfp_grw, address);
                vendor_pn[i] = (char) grw_read(sfp_grw);
                address++;
            }
            vendor_pn[i] = '\0';
			grw_dispose(sfp_grw); 
        }
       attribute_set_value_array(attribute, vendor_pn, strlen(vendor_pn) + 1);
        return attribute_get_value_array(attribute);
    }
    return NULL;
}

void common_to_string_function(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        char *string = NULL;
        string = (char*) attribute_get_value(attribute);
        if ( NULL != string)
        {
            attribute_set_to_string(attribute, string);
        }
        return;
    }   
}

void* transceiver_codes_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        GenericReadWritePtr sfp_grw = NULL;
        uint32_t address = 0;
        DagCardPtr card = attribute_get_card(attribute);
        ComponentPtr component = NULL;
        uint32_t tr_code = 0;
        uint8_t read_byte  = 0;
        xfp_state_t* xfp_state =   NULL;
        char trans_compli_string[XFP_SFP_STRING_SIZE]={'\0'};
        int i = 0, j = 0;
        int string_array_size = 0;
        AttributePtr attr_mod_type; 
        module_identifier_t module_type = kInvalidModuleType;
        module_identifier_t *ptr_type = NULL;
        int copy_len = 0;

        component = attribute_get_component(attribute);
        xfp_state = (xfp_state_t*)component_get_private_state(component);
        attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
        if( NULL != ptr_type  )
        {
           module_type = *ptr_type;
        }
        if( kUnknown == module_type)
        {
            strcpy(trans_compli_string,"Unknown Module");
        }
        else if( kSFP == module_type)
        {
            component = attribute_get_component(attribute);
            xfp_state = (xfp_state_t*)component_get_private_state(component);
            address = 0xa0 << 8;
            address |= (xfp_state->mPortNumber << 16);
            address |= 0x06; /* bytes 3 to 6 */
            /* TODO- Currently not reading the additional bits(in byte 36) as defined by SFF-8472Rev10.4*/
            sfp_grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
            assert(sfp_grw);
            for( i = 0 ; i < 4; i++)
            {
                grw_set_address(sfp_grw, address);
                tr_code |= grw_read(sfp_grw) << (i *8 );
                //    printf(" 0x%02x at %d\n", grw_read(sfp_grw),6-i);            
                address--;

            }
            string_array_size = sizeof(transceiver_compliance_strings) / sizeof( char*);
            for ( i = 0; i < string_array_size; i++)
            {
                if ( (tr_code) & (0x01 << i ) )
                {
                    copy_len = XFP_SFP_STRING_SIZE - strlen(trans_compli_string) - 1;
                    if ( copy_len > 0 )
                        strncat(trans_compli_string, transceiver_compliance_strings[string_array_size-1-i], copy_len);
                    else
                        break;
                }
            }
            grw_dispose(sfp_grw);
        }
        else if (kXFP == module_type)
        {
            component = attribute_get_component(attribute);
            xfp_state = (xfp_state_t*)component_get_private_state(component);
            address = 0xa0 << 8;
            address |= (xfp_state->mPortNumber << 16);
            address |= 127; /* to select the page address for upper memory */
            sfp_grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
            grw_write(sfp_grw, 0x01);
            address = (address & 0xffffff00) | 131; /* transceiver codes starts at bye 131 of page 1*/
            /* total 64 strings */
            string_array_size = sizeof(transceiver_compliance_strings_xfp) / sizeof( char*);
            for ( i = 0; i < 8; i++)
            {
                grw_set_address(sfp_grw, address);
                read_byte = grw_read(sfp_grw);
                /* for each bit in the byte */
                for( j = 0; j < 8; j++)
                {
                    if ( read_byte & ( 0x1 << (7 - j) ) )
                    {
                        copy_len = XFP_SFP_STRING_SIZE - strlen(trans_compli_string) - 1;
                        if ( copy_len > 0 )
                            strncat(trans_compli_string, transceiver_compliance_strings_xfp[(i * 8 ) + j], copy_len);
                        else
                            break;
                    }
                }
                address++;
            }
            grw_dispose(sfp_grw);
        }
        else
        {
            strcpy(trans_compli_string,"Not Implemented");
        }
        attribute_set_value_array(attribute, trans_compli_string, strlen(trans_compli_string) + 1);
        return attribute_get_value_array(attribute);
    }
    return NULL;
}
/*
void transceiver_code_to_string(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        uint32_t *trans_code = NULL;
        int i = 0;
        trans_code = (uint32_t*) attribute_get_value(attribute);
        if ( NULL == trans_code)
        {
           return; 
        }
               attribute_set_to_string(attribute, trans_compli_string);
        return;
    }   
}

*/


void* link_length_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        GenericReadWritePtr sfp_grw = NULL;
        uint32_t address = 0;
        DagCardPtr card = attribute_get_card(attribute);
        ComponentPtr component = NULL;
        uint32_t length_code = 0;
        xfp_state_t* xfp_state =   NULL;
        char string[XFP_SFP_STRING_SIZE]={0} ;
        int i = 0;
        int string_array_size = 0;
        AttributePtr attr_mod_type; 
        module_identifier_t module_type = kInvalidModuleType;
        module_identifier_t *ptr_type = NULL;
        int copy_len = 0;

        component = attribute_get_component(attribute);
        xfp_state = (xfp_state_t*)component_get_private_state(component);
        attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
        if( NULL != ptr_type  )
        {
           module_type = *ptr_type;
        }

        if( kUnknown == module_type)
        {
            strcpy(string,"Unknown Module");
        }
        else if( kSFP == module_type)
        {
            component = attribute_get_component(attribute);
            xfp_state = (xfp_state_t*)component_get_private_state(component);
            address = 0xa0 << 8;
            address |= (xfp_state->mPortNumber << 16);
            address |= 0x07;

	       sfp_grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
            assert(sfp_grw);
            length_code = grw_read(sfp_grw);
            length_code &= 0x1f;
            //printf("LengthCode 0x%x\n",length_code);
            string_array_size = (sizeof(fibre_link_length_strings) / sizeof (char*));
            for(i =0; i < string_array_size; i++)
            {
                if ( length_code & (0x01 << i ) )
                {
                    copy_len = XFP_SFP_STRING_SIZE - strlen(string) - 1;
                    if ( copy_len > 0 )
                        strncat(string, fibre_link_length_strings[string_array_size-1-i], copy_len);
                    else
                        break;
                }
            }
            if(0 == strlen(string))
                strcpy(string, "Not specified");
			grw_dispose(sfp_grw);
        }
        else
        {
             strcpy(string, "Not Implemented");
        }
        attribute_set_value_array(attribute, string, strlen(string) + 1);
        return attribute_get_value_array(attribute);
    }
    return NULL;
}
void* transmission_media_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        GenericReadWritePtr sfp_grw = NULL;
        uint32_t address = 0;
        DagCardPtr card = attribute_get_card(attribute);
        ComponentPtr component = NULL;
        uint32_t media_code = 0;
        xfp_state_t* xfp_state =   NULL;
        char string[XFP_SFP_STRING_SIZE]={0} ;
        int i = 0;
        int string_array_size = 0;
        AttributePtr attr_mod_type; 
        module_identifier_t module_type = kInvalidModuleType;
        module_identifier_t *ptr_type = NULL;
        int copy_len = 0;

        component = attribute_get_component(attribute);
        xfp_state = (xfp_state_t*)component_get_private_state(component);
        attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
        if( NULL != ptr_type  )
        {
           module_type = *ptr_type;
        }
        if (kUnknown == module_type )
        {
            strcpy(string,"Unknown Module");
        }
        else if( kSFP == module_type)
        {
            component = attribute_get_component(attribute);
            xfp_state = (xfp_state_t*)component_get_private_state(component);
            address = 0xa0 << 8;
            address |= (xfp_state->mPortNumber << 16);
            address |= 0x09;

	       sfp_grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
            assert(sfp_grw);
            media_code = grw_read(sfp_grw);
            string_array_size = (sizeof(fibre_tr_media_strings) / sizeof (char*));
            for(i =0; i < string_array_size; i++)
            {
                if ( (media_code) & (0x01 << i ) )
                {
                    copy_len = XFP_SFP_STRING_SIZE - strlen(string) - 1;
                    if ( copy_len > 0 )
                        strncat(string, fibre_tr_media_strings[string_array_size-1-i], copy_len);
                    else
                        break;
                }
            }
            if(0 == strlen(string))
                strcpy(string, "Not specified");
			grw_dispose(sfp_grw);
        }
        else
        {
                strcpy(string, "Not Implemented");
        }
        attribute_set_value_array(attribute, string, strlen(string) + 1);
        return attribute_get_value_array(attribute);
    }
    return NULL;
}

void* diagnostic_monitoring_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        GenericReadWritePtr sfp_grw = NULL;
        uint32_t address = 0;
        DagCardPtr card = attribute_get_card(attribute);
        ComponentPtr component = NULL;
        uint8_t read_byte  = 0;
        uint8_t value = 0;
        xfp_state_t* xfp_state =   NULL;
        AttributePtr attr_mod_type; 
        module_identifier_t module_type = kInvalidModuleType;
        module_identifier_t *ptr_type = NULL;

        component = attribute_get_component(attribute);
        xfp_state = (xfp_state_t*)component_get_private_state(component);
        attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
        if( NULL != ptr_type  )
        {
           module_type = *ptr_type;
        }
        if( kSFP == module_type)
        {
            component = attribute_get_component(attribute);
            xfp_state = (xfp_state_t*)component_get_private_state(component);
            address = 0xa0 << 8;
            address |= (xfp_state->mPortNumber << 16);
            address |= 92;

	       sfp_grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
            assert(sfp_grw);
            read_byte = grw_read(sfp_grw);
        //printf("MediaCode 0x%x\n",media_code);
            if ( read_byte & BIT6 )
            {
                value = 1;
                /* do some additional checks to assert SFF-8472 compliance */
                if ( read_byte & BIT7 )
                {
                    /* reserved legacy implementation . must be ZERO for SFF-8472 */
                    value = 0;
                }
                if ( read_byte & BIT2)
                {
                    /*TODO addressing mode change is reqd. Currently not implemented. */
                    value = 0;
                }
            }
            if ( 1 == value )
            {
                /* Check byte 94 for SFF-8472 compliance */
                address &= ~0xff;
                address |= 94;
                grw_set_address(sfp_grw, address);
                read_byte = grw_read(sfp_grw);
                if ( 0 == read_byte )
                {
                    value = 0;
                }
            }
			grw_dispose(sfp_grw);
        }
        else if ( kXFP == module_type )
        {
            value = 1;
        }
        attribute_set_value_array(attribute, &value, sizeof(value));
        return attribute_get_value_array(attribute);
    }
    return NULL;
}


void* transceiver_temperature_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        ComponentPtr component = NULL;
        AttributePtr attr_mod_type; 
        module_identifier_t module_type = kInvalidModuleType;
        module_identifier_t *ptr_type = NULL;

        component = attribute_get_component(attribute);
        attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
        if( NULL != ptr_type  )
        {
           module_type = *ptr_type;
        }
        if( kSFP == module_type)
        {
            return sfp_temperature_get_value(attribute, 96);
        }
        else if ( kXFP == module_type)
        {
            return xfp_temperature_get_value(attribute, 96);
        }
    }
    return NULL;
}

void* transceiver_voltage_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        ComponentPtr component = NULL;
        AttributePtr attr_mod_type; 
        module_identifier_t module_type = kInvalidModuleType;
        module_identifier_t *ptr_type = NULL;

        component = attribute_get_component(attribute);
        attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
        if( NULL != ptr_type  )
        {
           module_type = *ptr_type;
        }
        if( kSFP == module_type)
        {
            return sfp_voltage_get_value(attribute, 98);
        }
        else if ( kXFP == module_type)
        {
             /* for XFPs the voltage is present as auxiliary measurement.We look for 3.3V supply*/
            uint8_t voltage_aux = 0;
            voltage_aux =  xfp_get_supply_voltage_aux_input_number(attribute);
            if ( 1 == voltage_aux )
            {
                /* 3.3V present as aux1 starts at byte 106*/
                return xfp_voltage_get_value(attribute, 106);
            }
            else if ( 2 == voltage_aux)
            {
                /* 3.3V present as aux1 starts at byte 108*/
                return xfp_voltage_get_value(attribute, 108);
            }
        }
    }
    return NULL;
}

void* transceiver_tx_power_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        ComponentPtr component = NULL;
        AttributePtr attr_mod_type; 
        module_identifier_t module_type = kInvalidModuleType;
        module_identifier_t *ptr_type = NULL;

        component = attribute_get_component(attribute);
        attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
        if( NULL != ptr_type  )
        {
           module_type = *ptr_type;
        }
        if( kSFP == module_type)
        {
            return sfp_tx_power_get_value(attribute, 102);
        }
        else if ( kXFP == module_type)
        {
            return xfp_tx_power_get_value(attribute, 102);
        }
    }
    return NULL;
}

void* transceiver_rx_power_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        ComponentPtr component = NULL;
        AttributePtr attr_mod_type; 
        module_identifier_t module_type = kInvalidModuleType;
        module_identifier_t *ptr_type = NULL;

        component = attribute_get_component(attribute);
        attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
        if( NULL != ptr_type  )
        {
           module_type = *ptr_type;
        }
        if( kSFP == module_type)
        {
            return sfp_rx_power_get_value(attribute, 104);
        }
        else if ( kXFP == module_type)
        {
            return xfp_rx_power_get_value(attribute, 104);
        }
    }
    return NULL;
}

void* transceiver_temperature_low_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        ComponentPtr component = NULL;
        AttributePtr attr_mod_type; 
        module_identifier_t module_type = kInvalidModuleType;
        module_identifier_t *ptr_type = NULL;

        component = attribute_get_component(attribute);
        attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
        if( NULL != ptr_type  )
        {
           module_type = *ptr_type;
        }
        if( kSFP == module_type)
        {
            return sfp_temperature_get_value(attribute, 2);
        }
        else if ( kXFP == module_type)
        {
            return xfp_temperature_get_value(attribute, 4);
        }
    }
    return NULL;
}

void* transceiver_temperature_high_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        ComponentPtr component = NULL;
        AttributePtr attr_mod_type; 
        module_identifier_t module_type = kInvalidModuleType;
        module_identifier_t *ptr_type = NULL;

        component = attribute_get_component(attribute);
        attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
        if( NULL != ptr_type  )
        {
           module_type = *ptr_type;
        }
        if( kSFP == module_type)
        {
            return sfp_temperature_get_value(attribute, 0);
        }
        else if ( kXFP == module_type)
        {
            return xfp_temperature_get_value(attribute, 2);
        }
    }
    return NULL;
}

void* transceiver_voltage_low_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        ComponentPtr component = NULL;
        AttributePtr attr_mod_type; 
        module_identifier_t module_type = kInvalidModuleType;
        module_identifier_t *ptr_type = NULL;

        component = attribute_get_component(attribute);
        attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
        if( NULL != ptr_type  )
        {
           module_type = *ptr_type;
        }
        if( kSFP == module_type)
        {
            return sfp_voltage_get_value(attribute, 10);
        }
        else if ( kXFP == module_type)
        {
            /* for XFPs the voltage is present as auxiliary measurement.We look for 3.3V supply*/
            uint8_t voltage_aux = 0;
            voltage_aux =  xfp_get_supply_voltage_aux_input_number(attribute);
            if ( 1 == voltage_aux )
            {
                /* 3.3V present as aux1 starts at byte 44*/
                return xfp_voltage_get_value(attribute, 44);
            }
            else if ( 2 == voltage_aux)
            {
                /* 3.3V present as aux1 starts at byte 52*/
                return xfp_voltage_get_value(attribute, 52);
            }
        }
    }
        return NULL;
}

void* transceiver_voltage_high_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        ComponentPtr component = NULL;
        AttributePtr attr_mod_type; 
        module_identifier_t module_type = kInvalidModuleType;
        module_identifier_t *ptr_type = NULL;

        component = attribute_get_component(attribute);
        attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
        if( NULL != ptr_type  )
        {
           module_type = *ptr_type;
        }
        if( kSFP == module_type)
        {
            return sfp_voltage_get_value(attribute, 8);
        }
        else if ( kXFP == module_type)
        {
            /* for XFPs the voltage is present as auxiliary measurement.We look for 3.3V supply*/
            uint8_t voltage_aux = 0;
            voltage_aux =  xfp_get_supply_voltage_aux_input_number(attribute);
            if ( 1 == voltage_aux )
            {
                /* 3.3V present as aux1 high starts at byte 42*/
                return xfp_voltage_get_value(attribute, 42);
            }
            else if ( 2 == voltage_aux)
            {
                /* 3.3V present as aux1 starts at byte 50*/
                return xfp_voltage_get_value(attribute, 50);
            }
        }
    }
        return NULL;
}

void* transceiver_tx_power_low_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        ComponentPtr component = NULL;
        AttributePtr attr_mod_type; 
        module_identifier_t module_type = kInvalidModuleType;
        module_identifier_t *ptr_type = NULL;

        component = attribute_get_component(attribute);
        attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
        if( NULL != ptr_type  )
        {
           module_type = *ptr_type;
        }
        if( kSFP == module_type)
        {
            return sfp_tx_power_get_value(attribute, 26);
        }
        else if ( kXFP == module_type)
        {
            return xfp_tx_power_get_value(attribute, 28);
        }
    }
    return NULL;
}

void* transceiver_tx_power_high_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        ComponentPtr component = NULL;
        AttributePtr attr_mod_type; 
        module_identifier_t module_type = kInvalidModuleType;
        module_identifier_t *ptr_type = NULL;

        component = attribute_get_component(attribute);
        attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
        if( NULL != ptr_type  )
        {
           module_type = *ptr_type;
        }
        if( kSFP == module_type)
        {
            return sfp_tx_power_get_value(attribute, 24);
        }
        else if ( kXFP == module_type)
        {
            return xfp_tx_power_get_value(attribute, 26);
        }
    }
    return NULL;
}

void* transceiver_rx_power_low_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        ComponentPtr component = NULL;
        AttributePtr attr_mod_type; 
        module_identifier_t module_type = kInvalidModuleType;
        module_identifier_t *ptr_type = NULL;

        component = attribute_get_component(attribute);
        attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
        if( NULL != ptr_type  )
        {
           module_type = *ptr_type;
        }
        if( kSFP == module_type)
        {
            return sfp_rx_power_get_value(attribute, 34);
        }
        else if ( kXFP == module_type)
        {
            return xfp_rx_power_get_value(attribute, 36);
        }
    }
    return NULL;
}

void* transceiver_rx_power_high_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        ComponentPtr component = NULL;
        AttributePtr attr_mod_type; 
        module_identifier_t module_type = kInvalidModuleType;
        module_identifier_t *ptr_type = NULL;

        component = attribute_get_component(attribute);
        attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
        if( NULL != ptr_type  )
        {
           module_type = *ptr_type;
        }
        if( kSFP == module_type)
        {
            return sfp_rx_power_get_value(attribute, 32);
        }
        else if ( kXFP == module_type)
        {
            return xfp_rx_power_get_value(attribute, 34);
        }
    }
    return NULL;
}

void *sfp_temperature_get_value(AttributePtr attribute, uint8_t byte_addr)
{
    if (1 == valid_attribute(attribute))
    {
        DagCardPtr card = attribute_get_card(attribute);
        ComponentPtr component = NULL;
        float temp = 0;
        uint8_t lsb = 0;
        int8_t msb = 0;
        float  t_slope = 1;
        int16_t  t_offset = 0;
        xfp_state_t* xfp_state =   NULL;
        
        component = attribute_get_component(attribute);
        xfp_state = (xfp_state_t*)component_get_private_state(component);
        
        if( is_ext_calibarated(card, xfp_state) )
        {
            uint8_t tmp_msb = 0, tmp_lsb =0;
            if ( transceiver_get_msb_lsb (card, xfp_state->mPortNumber, 0xa2, 84, &tmp_msb, &tmp_lsb) >= 0)
            {
               t_slope =   tmp_msb + (float) tmp_lsb / 0x100;
            }
            tmp_msb = 0;
            tmp_lsb = 0;
            if ( transceiver_get_msb_lsb (card, xfp_state->mPortNumber, 0xa2, 86, &tmp_msb, &tmp_lsb) >= 0)
            {
               t_offset = (uint16_t) (  tmp_msb << 8) | tmp_lsb;
            }
        }
        
        if ( transceiver_get_msb_lsb (card, xfp_state->mPortNumber, 0xa2, byte_addr, (uint8_t*) &msb, &lsb) < 0)
        {
            /* grw read has failed */
            /* TODO NULL return is good ?*/
            return NULL;
        }
        temp = calculate_temperature_in_degree_celsius(msb, lsb, t_slope, t_offset);
        attribute_set_value_array(attribute, &temp, sizeof(float) );
        return attribute_get_value_array(attribute);
    }
    return NULL;
}

void *sfp_voltage_get_value(AttributePtr attribute, uint8_t byte_addr)
{
     if (1 == valid_attribute(attribute))
    {
        DagCardPtr card = attribute_get_card(attribute);
        ComponentPtr component = NULL;
        float volt_value = 0;
        uint8_t lsb = 0;
        uint8_t msb = 0;
        float  v_slope = 1;
        int16_t  v_offset = 0;
        xfp_state_t* xfp_state =   NULL;
        
        component = attribute_get_component(attribute);
        xfp_state = (xfp_state_t*)component_get_private_state(component);
        
        if( is_ext_calibarated(card, xfp_state) )
        {
            uint8_t tmp_msb = 0, tmp_lsb =0;
            if ( transceiver_get_msb_lsb (card, xfp_state->mPortNumber, 0xa2, 84, &tmp_msb, &tmp_lsb) >= 0)
            {
               v_slope =   tmp_msb + (float) tmp_lsb / 0x100;
            }
            tmp_msb = 0;
            tmp_lsb = 0;
            if ( transceiver_get_msb_lsb (card, xfp_state->mPortNumber, 0xa2, 86, &tmp_msb, &tmp_lsb) >= 0)
            {
               v_offset = (uint16_t) (  tmp_msb << 8) | tmp_lsb;
            }
        }
        
        if ( transceiver_get_msb_lsb (card, xfp_state->mPortNumber, 0xa2, byte_addr, (uint8_t*) &msb, &lsb) < 0)
        {
            /* grw read has failed */
            /* TODO NULL return is good ?*/
            return NULL;
        }
        volt_value = (((float)(( msb << 8 ) | lsb )) * v_slope + v_offset)/ 10000;
        attribute_set_value_array(attribute, &volt_value, sizeof(float) );
        return attribute_get_value_array(attribute);
    }
    return NULL;
}

void *sfp_tx_power_get_value(AttributePtr attribute, uint8_t byte_addr)
{
    if (1 == valid_attribute(attribute))
    {
        DagCardPtr card = attribute_get_card(attribute);
        ComponentPtr component = NULL;
        float txpower= 0;
        uint8_t lsb = 0 , msb = 0;
        xfp_state_t* xfp_state =   NULL;
        float  tx_power_slope = 1;
        int16_t  tx_power_offset = 0;
        
        component = attribute_get_component(attribute);
        xfp_state = (xfp_state_t*)component_get_private_state(component);
        if( is_ext_calibarated(card, xfp_state) )
        {
            uint8_t tmp_msb = 0, tmp_lsb =0;
            if ( transceiver_get_msb_lsb (card, xfp_state->mPortNumber, 0xa2, 80, &tmp_msb, &tmp_lsb) >= 0)
            {
               tx_power_slope =   tmp_msb + (float) tmp_lsb / 0x100;
            }
            tmp_msb = 0;
            tmp_lsb = 0;
            if ( transceiver_get_msb_lsb (card, xfp_state->mPortNumber, 0xa2, 82, &tmp_msb, &tmp_lsb) >= 0)
            {
               tx_power_offset = (uint16_t) (  tmp_msb << 8) | tmp_lsb;
            }
        }
        if ( transceiver_get_msb_lsb (card, xfp_state->mPortNumber, 0xa2, byte_addr,  &msb, &lsb) < 0)
        {
            /* grw read has failed */
            /* TODO NULL return is good ?*/
            return NULL;
        }
        txpower = calculate_tx_power_in_milli_watt(msb, lsb, tx_power_slope, tx_power_offset);
        attribute_set_value_array(attribute, &txpower, sizeof(txpower) );
        return attribute_get_value_array(attribute);
    }
    return NULL;
}
void *sfp_rx_power_get_value(AttributePtr attribute, uint8_t byte_addr)
{
    if (1 == valid_attribute(attribute))
    {
        DagCardPtr card = attribute_get_card(attribute);
        ComponentPtr component = NULL;
        float  rxpower= 0;
        uint8_t msb = 0, lsb = 0;
        xfp_state_t* xfp_state =   NULL;
        float rx_pwr_coefficients[5]={0, 1.0, 0, 0, 0};


        component = attribute_get_component(attribute);
        xfp_state = (xfp_state_t*)component_get_private_state(component);
        if( is_ext_calibarated(card, xfp_state) )
        {
            /* use loop. Since we know that coeffcients come in consecutive address */
            int i = 0;
            uint8_t coeff_byte_addr = 56; /* Rx_PWR4's start address */
            for ( i = 4; i >= 0; i--)
            {
                if ( transceiver_get_single_precision_float(card, xfp_state->mPortNumber, 0xa2, coeff_byte_addr, &rx_pwr_coefficients[i]) < 0)
                {
                    /*read error */
                    break;
                }
                coeff_byte_addr += 4; /* 4 bytes per coefficient */
            }
        }
        if ( transceiver_get_msb_lsb (card, xfp_state->mPortNumber, 0xa2, byte_addr,  &msb, &lsb) < 0)
        {
             /* grw read has failed */
            /* TODO NULL return is good ?*/
            return NULL;
        }
        rxpower  = calculate_rx_power_in_milli_watt(msb, lsb, rx_pwr_coefficients);
        attribute_set_value_array(attribute, &rxpower, sizeof(rxpower) );
        return attribute_get_value_array(attribute);
    }
    return NULL;
}

/* // detect 
static void*
xfp_detect_get_value(AttributePtr attribute)
{
    ComponentPtr component;
    DagCardPtr card;
    static uint8_t return_value = 0;
    uint32_t register_value = 0;
    uint32_t mask = 0;
    if (1 == valid_attribute(attribute))
    {
        xfp_state_t* state = NULL;
        component = attribute_get_component(attribute);
        state = (xfp_state_t*)component_get_private_state(component);
        card = attribute_get_card(attribute);
		register_value = card_read_iom(card, state->mBase);
        mask = BIT0 << state->mPortNumber*4;
        return_value = (register_value & mask) == mask;
        return (void*)&return_value;
    }
    return NULL;
}


// buffer size 
static void*
xfp_los_get_value(AttributePtr attribute)
{
    static uint8_t return_value = 0;
    uint32_t register_value = 0;
    uint32_t mask = 0;
    xfp_state_t* state = NULL;
    ComponentPtr component = NULL;

    if (1 == valid_attribute(attribute))
    {
        DagCardPtr card = attribute_get_card(attribute);
        component = attribute_get_component(attribute);
        state = (xfp_state_t*)component_get_private_state(component);
        card = attribute_get_card(attribute);
        mask = (BIT1 << (state->mPortNumber*4));
        register_value = card_read_iom(card, state->mBase);
        return_value = (register_value & mask) == mask;
        return (void*)&return_value;
    }
    return NULL;
}


// sfppwr count
static void*
xfp_pwr_get_value(AttributePtr attribute)
{
    static uint8_t return_value = 0;
    uint32_t register_value = 0;
    uint32_t mask = 0;
    xfp_state_t* state = NULL;
    ComponentPtr component = NULL;

    if (1 == valid_attribute(attribute))
    {
        DagCardPtr card = attribute_get_card(attribute);
        component = attribute_get_component(attribute);
        state = (xfp_state_t*)component_get_private_state(component);
        card = attribute_get_card(attribute);
        mask = BIT2 << (state->mPortNumber*4);
		register_value = card_read_iom(card, state->mBase);
        return_value = (register_value & mask) == mask;
        return (void*)&return_value;
    }
    return NULL;
}

static void
xfp_pwr_set_value(AttributePtr attribute, void* value, int length)
{
	ComponentPtr component = NULL;
    xfp_state_t* state = NULL;
    uint32_t register_value = 0;
    DagCardPtr card = NULL;
  
    if (1 == valid_attribute(attribute))
    {
        component = attribute_get_component(attribute);
        state = component_get_private_state(component);
        card = component_get_card(component);
        if (*(uint8_t*)value == 0)
        {
            register_value = card_read_iom(card, state->mBase);
            switch (state->mPortNumber)
            {
                case 0:
                {
                    register_value &= ~BIT2;
                    break;
                }
                case 1:
                {
                    register_value &= ~BIT6;
                    break;
                }
                case 2:
                {
                    register_value &= ~BIT10;
                    break;
                }
                case 3:
                {
                    register_value &= ~BIT14;
                    break;
                }
            }
            card_write_iom(card, state->mBase, register_value);
        }
        else
        {
            register_value= card_read_iom(card, state->mBase);
            switch (state->mPortNumber)
            {
                case 0:
                {
                    register_value |= BIT2;
                    break;
                }
                case 1:
                {
                    register_value |= BIT6;
                    break;
                }
                case 2:
                {
                    register_value |= BIT10;
                    break;
                }
                case 3:
                {
                    register_value |= BIT14;
                    break;
                }
            }
            card_write_iom(card, state->mBase, register_value);
        }
    }
}

*/
/*
uint32_t
xfp_get_port_number(ComponentPtr component)
{
    xfp_state_t* state = NULL;
    state = (xfp_state_t*)component_get_private_state(component);
    return state->mPortNumber;
}

void
xfp_set_port_number(ComponentPtr component, uint32_t val)
{
    xfp_state_t* state = NULL;
    state = (xfp_state_t*)component_get_private_state(component);
    state->mPortNumber = val;
}
*/

uint8_t is_ext_calibarated(DagCardPtr card, xfp_state_t* state)
{
    GenericReadWritePtr sfp_grw = NULL;
    uint32_t address = 0;
    uint8_t value = 0;
    uint8_t read_byte = 0;
    address = 0xa0 << 8;
    address |= (state->mPortNumber << 16);
    address |= 92;

    sfp_grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
    assert(sfp_grw);
    read_byte = grw_read(sfp_grw);
    if ( read_byte & BIT4 )
    {
        value = 1;
    }
    grw_dispose(sfp_grw);
    return value;
    
}

void *xfp_temperature_get_value(AttributePtr attribute, uint8_t byte_addr)
{
    if (1 == valid_attribute(attribute))
    {
        DagCardPtr card = attribute_get_card(attribute);
        ComponentPtr component = NULL;
        float temperature_value = 0;
        xfp_state_t* xfp_state =   NULL;
        uint8_t lsb = 0;
        int8_t msb = 0;
        
        component = attribute_get_component(attribute);
        xfp_state = (xfp_state_t*)component_get_private_state(component);
        /* select uppoer page1 */
        xfp_select_upper_mem_map_page(card, xfp_state->mPortNumber, 0x01);
        if ( transceiver_get_msb_lsb (card, xfp_state->mPortNumber, 0xa0, byte_addr, (uint8_t*) &msb, &lsb) < 0)
            return NULL;
        temperature_value = calculate_temperature_in_degree_celsius(msb, lsb, 1/*slope*/, 0/*offset*/);
        attribute_set_value_array(attribute, &temperature_value, sizeof(float) );
        return attribute_get_value_array(attribute);
    }
    return NULL;
}

void *xfp_voltage_get_value(AttributePtr attribute, uint8_t byte_addr)
{
    if (1 == valid_attribute(attribute))
    {
        DagCardPtr card = attribute_get_card(attribute);
        ComponentPtr component = NULL;
        float volt_value = 0;
        xfp_state_t* xfp_state =   NULL;
        uint8_t lsb = 0;
        uint8_t msb = 0;
        
        component = attribute_get_component(attribute);
        xfp_state = (xfp_state_t*)component_get_private_state(component);
         /* select uppoer page1 */
        xfp_select_upper_mem_map_page(card, xfp_state->mPortNumber, 0x01);
        if ( transceiver_get_msb_lsb (card, xfp_state->mPortNumber, 0xa0, byte_addr, (uint8_t*) &msb, &lsb) < 0)
            return NULL;
        volt_value = (float)((msb << 8) | lsb)/10000;
        attribute_set_value_array(attribute, &volt_value, sizeof(volt_value) );
        return attribute_get_value_array(attribute);
    }
    return NULL;
}


void *xfp_rx_power_get_value(AttributePtr attribute, uint8_t byte_addr)
{
    if (1 == valid_attribute(attribute))
    {
        DagCardPtr card = attribute_get_card(attribute);
        ComponentPtr component = NULL;
        float  rxpower= 0;
        uint8_t msb = 0, lsb = 0;
        xfp_state_t* xfp_state =   NULL;
        float rx_pwr_coefficients[5]={0, 1.0, 0, 0, 0}; /* just the default values. always internal calibrated*/
        
        component = attribute_get_component(attribute);
        xfp_state = (xfp_state_t*)component_get_private_state(component);
         /* select uppoer page1 */
        xfp_select_upper_mem_map_page(card, xfp_state->mPortNumber, 0x01);
        if ( transceiver_get_msb_lsb (card, xfp_state->mPortNumber, 0xa0, byte_addr,  &msb, &lsb) < 0)
            return NULL;
        rxpower  = calculate_rx_power_in_milli_watt(msb, lsb, rx_pwr_coefficients);
        attribute_set_value_array(attribute, &rxpower, sizeof(rxpower) );
        return attribute_get_value_array(attribute);
    }
    return NULL;
}

void *xfp_tx_power_get_value(AttributePtr attribute, uint8_t byte_addr)
{
    if (1 == valid_attribute(attribute))
    {
        DagCardPtr card = attribute_get_card(attribute);
        ComponentPtr component = NULL;
        float txpower= 0;
        uint8_t lsb = 0 , msb = 0;
        xfp_state_t* xfp_state =   NULL;
        
        component = attribute_get_component(attribute);
        xfp_state = (xfp_state_t*)component_get_private_state(component);
         /* select uppoer page1 */
        xfp_select_upper_mem_map_page(card, xfp_state->mPortNumber, 0x01);

        if ( transceiver_get_msb_lsb (card, xfp_state->mPortNumber, 0xa0, byte_addr,  &msb, &lsb) < 0)
            return NULL;
        txpower = calculate_tx_power_in_milli_watt(msb, lsb, 1, 0);

        attribute_set_value_array(attribute, &txpower, sizeof(txpower) );
        return attribute_get_value_array(attribute);
    }
    return NULL;
}

float calculate_tx_power_in_milli_watt(uint8_t msb, uint8_t lsb, float tx_pwr_slope, int16_t tx_pwr_offset)
{
    float ret_val = 0;
    
    ret_val  =  (((float)(( msb << 8 ) | lsb )) * tx_pwr_slope + tx_pwr_offset)/ 10000;
    return ret_val;
}

float calculate_temperature_in_degree_celsius(int8_t msb, uint8_t lsb, float temp_slope, int16_t temp_offset)
{
    float temperature_value = 0;
    
    temperature_value  = ((float) (temp_slope * ((msb << 8) | lsb) + temp_offset) )/ 0x100;
    return temperature_value;
}
float calculate_rx_power_in_milli_watt(uint8_t msb, uint8_t lsb, float* coeffient_array)
{
    float ret_val = 0;
    uint32_t temp_pwr = 0;
    int i =0;
    
    temp_pwr = ((uint32_t) ( msb << 8 ) | lsb ) ;

    /*  for ext calibration */
    /*Rx_PWR[4] * Rx_Value^4  + Rx_PWR[3] * Rx_Value^3 + Rx_PWR[2] * Rx_Value^2  + Rx_PWR[1] * Rx_Value^1  +            Rx_PWR[0]
*/
    for ( i = 0; i < 5; i++)
    {
        ret_val += coeffient_array[i]* (float) pow((float)temp_pwr, (float)i);
    }

    /* convert to mW */
    ret_val = (ret_val/ 10000);
    return ret_val;
}
int transceiver_get_msb_lsb( DagCardPtr card, uint32_t port_index, uint16_t serial_addr, uint8_t byte_addr, uint8_t *ptr_msb, uint8_t* ptr_lsb)
{
    GenericReadWritePtr sfp_grw = NULL;
    uint32_t address = 0;
    int ret_value = 0;
    address = serial_addr << 8;
    address |= (port_index << 16);
    address |= byte_addr;
    
    sfp_grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
    if ( sfp_grw == NULL)
        return -1;
    *ptr_msb = (int8_t) grw_read(sfp_grw);
    address++;
    grw_set_address(sfp_grw, address);
    *ptr_lsb = grw_read(sfp_grw);
    if ( grw_get_last_error( sfp_grw) != kGRWNoError)
    {
        ret_value = -1;
    }
    grw_dispose(sfp_grw);
    return ret_value;
}

void
transceiver_power_to_string_routine(AttributePtr attribute)
{
    void *value_ptr  = NULL;
    char buffer[1024] ={0};
    
    if ( 1 != valid_attribute(attribute) )
        return;

    value_ptr  = (float*)attribute_get_value(attribute);
    if ( NULL == value_ptr)
    {
        snprintf(buffer,1024, "Error");
    }
    else // ( NULL != value_ptr)
    {
        float value_in_dbm = 0;
        float value = 0 ;
        uint8_t is_oma = 0;
        dag_attribute_code_t attr_code = kAttributeInvalid;
        value = *(float*)value_ptr; /* in milli watts */
        value_in_dbm =  (value == 0)? 0:(log(value)/log((float)10)) * 10;
        attr_code = attribute_get_attribute_code(attribute);
        if ( ( kFloatAttributeTransceiverRxPower == attr_code) ||
                ( kFloatAttributeTransceiverRxPowerHigh == attr_code) ||
                ( kFloatAttributeTransceiverRxPowerLow == attr_code) )
        {
            /* TODO if in OMA, we may have to convert to avg power in _get_value function */
            /* For the time being, jus printing that its in OMA. Not yet seen a module with OMA rx powr*/
            is_oma = is_rx_power_in_oma(attribute);
        }
        snprintf(buffer, 1024, "%.4f mW %s (%.1f dBm)",value, (is_oma?"(OMA)":""),value_in_dbm);
    }
    attribute_set_to_string(attribute, buffer);
    return;
}

void
transceiver_temperature_to_string_routine(AttributePtr attribute)
{
    char buffer[1024];
    float *value_ptr = NULL;

    if (1 != valid_attribute(attribute))
        return;
    value_ptr = (float*)attribute_get_value(attribute);
    
    if ( NULL == value_ptr)
    {
        snprintf(buffer,1024, "Error");
    }
    else // (value_ptr != NULL)
    {
        snprintf(buffer, 1024, "%.2f degrees Celsius", *value_ptr);
    }
    attribute_set_to_string(attribute, buffer);
}

void
transceiver_voltage_to_string_routine(AttributePtr attribute)
{
    char buffer[1024];
    float *value_ptr = NULL;

    if (1 != valid_attribute(attribute))
        return;
    value_ptr = (float*)attribute_get_value(attribute);
    
    if ( NULL == value_ptr)
    {
        snprintf(buffer,1024, "Error");
    }
    else // (value_ptr != NULL)
    {
        snprintf(buffer, 1024, "%.4f V", *value_ptr);
    }
    attribute_set_to_string(attribute, buffer);
}

int transceiver_get_single_precision_float( DagCardPtr card, uint32_t port_index, uint16_t serial_addr, uint8_t byte_addr, float *ptr_float)
{
    GenericReadWritePtr sfp_grw = NULL;
    uint32_t address = 0;
    int ret_value = 0;
    uint8_t *temp_array_char = (uint8_t*)ptr_float;
    int i = 0;

    address = serial_addr << 8;
    address |= (port_index << 16);
    address |= byte_addr;
    
    sfp_grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
    if ( sfp_grw == NULL)
        return -1;
    /* Order is MSB first, LSB last  */
    for( i = 3; i >= 0; i--)
    {
        temp_array_char[i] = grw_read(sfp_grw);
        if ( grw_get_last_error( sfp_grw) != kGRWNoError)
        {
            ret_value = -1;
            break;
        }
        address++;
        grw_set_address(sfp_grw, address);
    }
    grw_dispose(sfp_grw);
    return ret_value;
}

uint8_t xfp_get_supply_voltage_aux_input_number(AttributePtr attribute)
{
    GenericReadWritePtr sfp_grw = NULL;
    uint32_t address = 0;
    uint8_t read_byte = 0;
    xfp_state_t* xfp_state = NULL;
    uint8_t ret_val = 0;
    
    xfp_state = (xfp_state_t*)component_get_private_state(attribute_get_component(attribute));
    if ( NULL == xfp_state)
        return 0;

    
    address = 0xa0 << 8;
    address |= (xfp_state->mPortNumber << 16);
    address |= 222;

    sfp_grw = grw_init(attribute_get_card(attribute), address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
    read_byte = grw_read(sfp_grw);
    if ( grw_get_last_error( sfp_grw) != kGRWNoError)
    {
        ret_val = 0;
    }
    /* check if aux1 is 3.3V ( Bit7-4) */
    else if ( ((read_byte >> 4) & 0xf) == 0x7)
    {
        ret_val = 1;
    }
    else if ((read_byte  & 0xf) == 0x7)
    {
        /* aux2 is 3.3V ( Bit3-0) */
        ret_val = 2;
    }
    grw_dispose(sfp_grw);
    return ret_val;
}

int  xfp_select_upper_mem_map_page( DagCardPtr card, uint32_t port_index, uint8_t page)
{
    GenericReadWritePtr sfp_grw = NULL;
    uint32_t address = 0;
    int ret_value = 0;
    
    address = 0xa0 << 8;
    address |= (port_index << 16);
    address |= 127;
    sfp_grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
    grw_write(sfp_grw, page);
    
    if ( grw_get_last_error( sfp_grw) != kGRWNoError)
    {
        ret_value = -1;
    }
    grw_dispose(sfp_grw);
    return ret_value;
}

uint8_t is_rx_power_in_oma(AttributePtr attribute)
{
    GenericReadWritePtr sfp_grw = NULL;
    uint32_t address = 0;
    uint8_t value = 1;
    uint8_t read_byte = 0;
    module_identifier_t *ptr_type  = NULL;
    AttributePtr attr_mod_type  = NULL;
    DagCardPtr card = attribute_get_card(attribute);
    ComponentPtr component = attribute_get_component(attribute); 
    xfp_state_t *state = (xfp_state_t*) component_get_private_state(component);


    attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);  
    ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
    if( NULL == ptr_type  )
    {
       return 0;
    }
    else if( kXFP == *ptr_type )
    {
        address = 0xa0 << 8;
        address |= (state->mPortNumber << 16);
        address |= 220;
    }
    else // kSFP
    {
        address = 0xa0 << 8;
        address |= (state->mPortNumber << 16);
        address |= 92;
    }

    sfp_grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
    assert(sfp_grw);
    read_byte = grw_read(sfp_grw);
    if ( read_byte & BIT3 )
    {
        /* if BIT 3 is set , then avg rx power is represented */
        value = 0;
    }
    grw_dispose(sfp_grw);
    return value;
}
static void* enable_full_rate_get_value(AttributePtr attribute)
{
  DagCardPtr card = NULL;
  GenericReadWritePtr grw = NULL;
  uint32_t address = 0;
  uint8_t read_byte = 0;
  uint8_t enable_full_rate = 0;
  ComponentPtr component = attribute_get_component(attribute);
  xfp_state_t *state = (xfp_state_t*) component_get_private_state(component);
  
  address = 0x6e;
  address |= (0xa2 <<8);
  address |= (state->mPortNumber << 16);

  card = attribute_get_card(attribute);
  grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
  assert(grw);
  read_byte = grw_read(grw);
  enable_full_rate = ((read_byte & BIT3) >> 3);
  grw_dispose(grw);
  attribute_set_value_array(attribute,&enable_full_rate,sizeof(uint8_t));
  return (void*)attribute_get_value_array(attribute);
}

static void enable_full_rate_set_value(AttributePtr attribute,void *value,int length)
{
  DagCardPtr card = NULL;
  GenericReadWritePtr grw = NULL;
  uint32_t address = 0;
  uint8_t read_byte = 0;
  ComponentPtr component = attribute_get_component(attribute);
  xfp_state_t *state = (xfp_state_t*) component_get_private_state(component);
  
  address = 0x6e;
  address |= (0xa2 <<8);
  address |= (state->mPortNumber << 16);

  card = attribute_get_card(attribute);
  grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
  assert(grw);
  read_byte = grw_read(grw);
  if (1 == *(uint8_t*)value)
  {
    read_byte |= BIT3;
  }
  else
  {
    read_byte &= ~BIT3;
  }
  grw_write(grw,read_byte);
  grw_dispose(grw);
}

void* transceiver_power_level_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        GenericReadWritePtr sfp_grw = NULL;
        uint32_t address = 0;
        DagCardPtr card = attribute_get_card(attribute);
        ComponentPtr component = NULL;
        uint8_t read_byte  = 0;
        uint32_t value = 0;
        xfp_state_t* xfp_state =   NULL;
        AttributePtr attr_mod_type; 
        module_identifier_t module_type = kInvalidModuleType;
        module_identifier_t *ptr_type = NULL;

        component = attribute_get_component(attribute);
        xfp_state = (xfp_state_t*)component_get_private_state(component);
        attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
        if( NULL != ptr_type  )
        {
           module_type = *ptr_type;
        }
        if( kSFP == module_type)
        {
            address = 0xa0 << 8;
            address |= (xfp_state->mPortNumber << 16);
            address |= 64;

            sfp_grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
            read_byte = grw_read(sfp_grw);
            if ( read_byte & BIT1 )
            {
                value = 2; /* SFP power level 2 */
            }
            else
            {
                value = 1; /* SFP power level 1 */
            }
        }
        else if ( kXFP == module_type )
        {
            xfp_select_upper_mem_map_page(card, xfp_state->mPortNumber, 0x01);
            address = 0xa0 << 8;
            address |= (xfp_state->mPortNumber << 16);
            address |= 129;
            sfp_grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
            read_byte = grw_read(sfp_grw);

            value = ((read_byte & ( BIT6|BIT7)) >> 6)+1;
        }
        grw_dispose(sfp_grw);
        attribute_set_value_array(attribute, &value, sizeof(value));
        return attribute_get_value_array(attribute);
    }
    return NULL;
}

void* transceiver_power_level_state_get_value(AttributePtr attribute)
{
    if (1 == valid_attribute(attribute))
    {
        GenericReadWritePtr sfp_grw = NULL;
        uint32_t address = 0;
        DagCardPtr card = attribute_get_card(attribute);
        ComponentPtr component = NULL;
        uint8_t read_byte  = 0;
        uint32_t value = 0;
        xfp_state_t* xfp_state =   NULL;
        AttributePtr attr_mod_type; 
        module_identifier_t module_type = kInvalidModuleType;
        module_identifier_t *ptr_type = NULL;

        component = attribute_get_component(attribute);
        xfp_state = (xfp_state_t*)component_get_private_state(component);
        attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
        if( NULL != ptr_type  )
        {
           module_type = *ptr_type;
        }
        if( kSFP == module_type)
        {
            component = attribute_get_component(attribute);
            xfp_state = (xfp_state_t*)component_get_private_state(component);
            address = 0xa2 << 8;
            address |= (xfp_state->mPortNumber << 16);
            address |= 118;

            sfp_grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
            read_byte = grw_read(sfp_grw);
            if ( read_byte & BIT1 )
            {
                value = 2; /* SFP power level 2 */
            }
            else
            {
                value = 1; /* SFP power level 1 */
            }
        }
        else if ( kXFP == module_type )
        {
            /* same as power_level */
            xfp_select_upper_mem_map_page(card, xfp_state->mPortNumber, 0x01);
            address = 0xa0 << 8;
            address |= (xfp_state->mPortNumber << 16);
            address |= 129;
            sfp_grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
            read_byte = grw_read(sfp_grw);

            value = ((read_byte & ( BIT6|BIT7)) >> 6)+1;
        }
        grw_dispose(sfp_grw);
        attribute_set_value_array(attribute, &value, sizeof(value));
        return attribute_get_value_array(attribute);
    }
    return NULL;
}
void transceiver_power_level_state_set_value(AttributePtr attribute,void *value,int length)
{
    if (1 == valid_attribute(attribute))
    {
        GenericReadWritePtr sfp_grw = NULL;
        uint32_t address = 0;
        DagCardPtr card = attribute_get_card(attribute);
        ComponentPtr component = NULL;
        uint8_t read_byte  = 0;
        uint32_t uint32_value = 0;
        xfp_state_t* xfp_state =   NULL;
        AttributePtr attr_mod_type; 
        module_identifier_t module_type = kInvalidModuleType;
        module_identifier_t *ptr_type = NULL;

        component = attribute_get_component(attribute);
        xfp_state = (xfp_state_t*)component_get_private_state(component);
        attr_mod_type = component_get_attribute(component, kUint32AttributeTransceiverIdentifier);
        ptr_type = (module_identifier_t *) module_identifier_get_value(attr_mod_type);
        if( NULL != ptr_type  )
        {
           module_type = *ptr_type;
        }
        uint32_value = *((uint32_t*) value);
        if( kSFP == module_type)
        {
            component = attribute_get_component(attribute);
            xfp_state = (xfp_state_t*)component_get_private_state(component);
            address = 0xa2 << 8;
            address |= (xfp_state->mPortNumber << 16);
            address |= 118;

            sfp_grw = grw_init(card, address, grw_xfp_sfp_raw_smbus_read, grw_xfp_sfp_raw_smbus_write);
            read_byte = grw_read(sfp_grw);
            if ( 2 == uint32_value )
            {
                read_byte |= BIT0; /* pwoer level 2 */
            }
            else if ( 1 == uint32_value)
            {
                read_byte &= ~(BIT0);/* SFP power level 1 */
            }
            grw_write(sfp_grw,read_byte);
            grw_dispose(sfp_grw);
        }
        else if ( kXFP == module_type )
        {
			/* dont do anything*/
        }
    }
}
