/** @file

  Copyright (c) 2016 - 2017, Socionext Inc. All rights reserved.<BR>
  Copyright (c) 2017, Linaro, Ltd. All rights reserved.<BR>

  SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#include "ogma_config.h"
#include "ogma_internal.h"
#include "ogma_basic_access.h"
#include "ogma_misc_internal.h"

#include <Library/IoLib.h>

ogma_global_t ogma_global = {
    OGMA_FALSE,
    0,
    NULL
};


static const ogma_uint32 hw_ver_reg_addr = OGMA_REG_ADDR_HW_VER;
static const ogma_uint32 mc_ver_reg_addr = OGMA_REG_ADDR_MC_VER;

static const ogma_uint32 desc_ring_irq_status_reg_addr[OGMA_DESC_RING_ID_MAX + 1] = {
    OGMA_REG_ADDR_NRM_TX_STATUS,
    OGMA_REG_ADDR_NRM_RX_STATUS,
};

static const ogma_uint32 desc_ring_config_reg_addr[OGMA_DESC_RING_ID_MAX + 1] = {
    OGMA_REG_ADDR_NRM_TX_CONFIG,
    OGMA_REG_ADDR_NRM_RX_CONFIG,

};


/* Internal function definition*/
#ifndef OGMA_CONFIG_DISABLE_CLK_CTRL
STATIC void ogma_set_clk_en_reg (
    ogma_ctrl_t *ctrl_p
    );
#endif /* OGMA_CONFIG_DISABLE_CLK_CTRL */
STATIC void ogma_global_init ( void);

STATIC ogma_err_t ogma_probe_hardware (
    void *base_addr
    );

STATIC void ogma_reset_hardware (
    ogma_ctrl_t *ctrl_p
    );

STATIC void ogma_set_microcode(
    ogma_ctrl_t *ctrl_p,
    const void *dma_hm_mc_addr,
    ogma_uint32 dma_hm_mc_len,
    const void *dma_mh_mc_addr,
    ogma_uint32 dma_mh_mc_len,
    const void *pktc_mc_addr,
    ogma_uint32 pktc_mc_len
    );

STATIC ogma_uint32 ogma_calc_pkt_ctrl_reg_param (
    const ogma_pkt_ctrl_param_t *pkt_ctrl_param_p
    );

STATIC void ogma_internal_terminate (
    ogma_ctrl_t *ctrl_p
    );

#ifdef OGMA_CONFIG_DISABLE_CLK_CTRL

#define ogma_set_clk_en_reg( ctrl_p)

#else /* OGMA_CONFIG_DISABLE_CLK_CTRL */
STATIC void ogma_set_clk_en_reg (
    ogma_ctrl_t *ctrl_p
    )
{
    ogma_uint32 value = 0;

    if ( ctrl_p->clk_ctrl.mac_req_num != 0) {
        value |= OGMA_CLK_EN_REG_DOM_G;
    }

    ogma_write_reg( ctrl_p, OGMA_REG_ADDR_CLK_EN, value);
}
#endif /* OGMA_CONFIG_DISABLE_CLK_CTRL */

void ogma_push_clk_req (
    ogma_ctrl_t *ctrl_p,
    ogma_uint32 domain
    )
{
    pfdep_hard_lock_ctx_t clk_ctrl_hard_lock_ctx;

    pfdep_acquire_hard_lock (
        &ctrl_p->clk_ctrl_hard_lock,
        &clk_ctrl_hard_lock_ctx);

    if ( ( domain & OGMA_CLK_EN_REG_DOM_G) != 0) {
        ++ctrl_p->clk_ctrl.mac_req_num;
    }

    ogma_set_clk_en_reg( ctrl_p);

    pfdep_release_hard_lock(
        &ctrl_p->clk_ctrl_hard_lock,
        &clk_ctrl_hard_lock_ctx);
}

void ogma_pop_clk_req(
    ogma_ctrl_t *ctrl_p,
    ogma_uint32 domain
    )
{
    pfdep_hard_lock_ctx_t clk_ctrl_hard_lock_ctx;

    pfdep_acquire_hard_lock(
        &ctrl_p->clk_ctrl_hard_lock,
        &clk_ctrl_hard_lock_ctx);

    if ( ( domain & OGMA_CLK_EN_REG_DOM_G) != 0) {
        --ctrl_p->clk_ctrl.mac_req_num;
    }

    ogma_set_clk_en_reg( ctrl_p);

    pfdep_release_hard_lock(
        &ctrl_p->clk_ctrl_hard_lock,
        &clk_ctrl_hard_lock_ctx);
}

/* Internal function */
STATIC void ogma_global_init ( void)
{
    ogma_global.valid_flag = OGMA_TRUE;
}

STATIC ogma_err_t ogma_probe_hardware (
    void *base_addr
    )
{

    ogma_uint32 value;

    /* Read HW_VER Register */
    value = pfdep_iomem_read((void *)
                             ((pfdep_cpu_addr_t)base_addr +
                              (OGMA_REG_ADDR_HW_VER << 2)));

    if ( value != OGMA_VER_NETSEC) {
        pfdep_print(PFDEP_DEBUG_LEVEL_WARNING,
                    "Hardware version check warning. Actual:0x%08x, Expected:0x%08x\n",
                    (unsigned int)value,
                    (unsigned int)OGMA_VER_NETSEC);
    }

    if ( OGMA_VER_MAJOR_NUM(value) != OGMA_VER_MAJOR_NUM(OGMA_VER_NETSEC) ) {
        pfdep_print(PFDEP_DEBUG_LEVEL_FATAL,
                    "Hardware Major version check failed. Actual:0x%08x, Expected:0x%08x\n",
                    (unsigned int)OGMA_VER_MAJOR_NUM(value),
                    (unsigned int)OGMA_VER_MAJOR_NUM(OGMA_VER_NETSEC) );
        return OGMA_ERR_NOTAVAIL;
    }

    /* Print hardware version information. */
    pfdep_print(PFDEP_DEBUG_LEVEL_NOTICE,
                "NETSEC found. Hardware version: %08x\n",
                value);


    return OGMA_ERR_OK;
}

STATIC void ogma_reset_hardware (
    ogma_ctrl_t *ctrl_p
    )
{
    ogma_write_reg( ctrl_p,
                    OGMA_REG_ADDR_CLK_EN,
                    OGMA_CLK_EN_REG_DOM_ALL);


    /*
     * Stop dma engines if cores are enabled
     */
    if (ogma_read_reg(ctrl_p, OGMA_REG_ADDR_DIS_CORE) == 0) {

        ogma_write_reg( ctrl_p,
                        OGMA_REG_ADDR_DMA_HM_CTRL,
                        OGMA_DMA_CTRL_REG_STOP);

        ogma_write_reg( ctrl_p,
                        OGMA_REG_ADDR_DMA_MH_CTRL,
                        OGMA_DMA_CTRL_REG_STOP);

        while ( ( ogma_read_reg( ctrl_p, OGMA_REG_ADDR_DMA_HM_CTRL)
                  & OGMA_DMA_CTRL_REG_STOP) != 0) {
            ;
        }

        while ( ( ogma_read_reg( ctrl_p, OGMA_REG_ADDR_DMA_MH_CTRL)
                  & OGMA_DMA_CTRL_REG_STOP) != 0) {
            ;
        }
    }

    if ( ctrl_p->param.use_gmac_flag) {

        /* Reset F_GMAC4MT */
        ogma_set_mac_reg( ctrl_p,
                          OGMA_GMAC_REG_ADDR_BMR,
                          OGMA_GMAC_BMR_REG_RESET);

    }

    ogma_write_reg( ctrl_p,
                    OGMA_REG_ADDR_SOFT_RST,
                    OGMA_SOFT_RST_REG_RESET);

    ogma_write_reg( ctrl_p,
                    OGMA_REG_ADDR_SOFT_RST,
                    OGMA_SOFT_RST_REG_RUN);

    ogma_write_reg( ctrl_p,
                    OGMA_REG_ADDR_COM_INIT,
                    OGMA_COM_INIT_REG_ALL);

    while (ogma_read_reg(ctrl_p, OGMA_REG_ADDR_COM_INIT) != 0) {
        ;
    }

    if ( ctrl_p->param.use_gmac_flag) {


        /* MAC desc init */
        ogma_write_reg( ctrl_p,
                        OGMA_REG_ADDR_MAC_DESC_INIT,
                        OGMA_MAC_DESC_INIT_REG_INIT);

        /* Wait MAC desc init done */
        while ( ( ogma_read_reg( ctrl_p, OGMA_REG_ADDR_MAC_DESC_INIT)
                  & OGMA_MAC_DESC_INIT_REG_INIT) != 0) {
            ;
        }


        /* set MAC_INTF_SEL */
        ogma_write_reg( ctrl_p,
                        OGMA_REG_ADDR_MAC_INTF_SEL,
                        ctrl_p->param.gmac_config.phy_interface);


    }
}

#define OGMA_ROUND_UP(numerator,denominator) (((numerator) + (denominator)) - 1 / (denominator))

STATIC void ogma_set_microcode (
    ogma_ctrl_t *ctrl_p,
    const void *dma_hm_mc_addr,
    ogma_uint32 dma_hm_mc_len,
    const void *dma_mh_mc_addr,
    ogma_uint32 dma_mh_mc_len,
    const void *pktc_mc_addr,
    ogma_uint32 pktc_mc_len
    )
{
    ogma_uint i;

    const UINT32 *dmac_hm_cmd_data = (const UINT32 *)dma_hm_mc_addr;
    const UINT32 *dmac_mh_cmd_data = (const UINT32 *)dma_mh_mc_addr;
    const UINT32 *core_cmd_data = (const UINT32 *)pktc_mc_addr;

    /* Loads microcodes to microengines. */
    for( i = 0; i < dma_hm_mc_len; i++) {
        UINT32 data = MmioRead32((UINTN)dmac_hm_cmd_data);
        ogma_write_reg( ctrl_p,
                        OGMA_REG_ADDR_DMAC_HM_CMD_BUF,
                        data );
        dmac_hm_cmd_data++;
    }

    for( i = 0; i < dma_mh_mc_len; i++) {
        UINT32 data = MmioRead32((UINTN)dmac_mh_cmd_data);
        ogma_write_reg( ctrl_p,
                        OGMA_REG_ADDR_DMAC_MH_CMD_BUF,
                        data );
        dmac_mh_cmd_data++;
    }

    for( i = 0; i < pktc_mc_len; i++) {
        UINT32 data = MmioRead32((UINTN)core_cmd_data);
        ogma_write_reg( ctrl_p,
                        OGMA_REG_ADDR_PKTC_CMD_BUF,
                        data );
        core_cmd_data++;
    }

}

STATIC ogma_uint32 ogma_calc_pkt_ctrl_reg_param (
    const ogma_pkt_ctrl_param_t *pkt_ctrl_param_p
    )
{
    ogma_uint32 param = 0;

    if ( pkt_ctrl_param_p->log_chksum_er_flag) {
        param |= OGMA_PKT_CTRL_REG_LOG_CHKSUM_ER;
    }

    if ( pkt_ctrl_param_p->log_hd_imcomplete_flag) {
        param |= OGMA_PKT_CTRL_REG_LOG_HD_INCOMPLETE;
    }

    if ( pkt_ctrl_param_p->log_hd_er_flag) {
        param |= OGMA_PKT_CTRL_REG_LOG_HD_ER;
    }

    if ( pkt_ctrl_param_p->drp_no_match_flag) {
        param |= OGMA_PKT_CTRL_REG_DRP_NO_MATCH;
    }

    return param;
}

STATIC
void
ogma_pre_init_microengine (
  ogma_handle_t ogma_handle
  )
{
  UINT16 Data;

  /* Remove dormant settings */
  Data = ogma_get_phy_reg (ogma_handle, OGMA_PHY_REG_ADDR_CONTROL) &
         ~((1U << OGMA_PHY_CONTROL_REG_POWER_DOWN) |
         (1U << OGMA_PHY_CONTROL_REG_ISOLATE));

  ogma_set_phy_reg (ogma_handle, OGMA_PHY_REG_ADDR_CONTROL, Data);

  while ((ogma_get_phy_reg (ogma_handle, OGMA_PHY_REG_ADDR_CONTROL) &
          ((1U << OGMA_PHY_CONTROL_REG_POWER_DOWN) |
           (1U << OGMA_PHY_CONTROL_REG_ISOLATE))) != 0);

  /* Put phy in loopback mode to guarantee RXCLK input */
  Data |= (1U << OGMA_PHY_CONTROL_REG_LOOPBACK);

  ogma_set_phy_reg (ogma_handle, OGMA_PHY_REG_ADDR_CONTROL, Data);

  while ((ogma_get_phy_reg (ogma_handle, OGMA_PHY_REG_ADDR_CONTROL) &
          (1U << OGMA_PHY_CONTROL_REG_LOOPBACK)) == 0);
}

STATIC
void
ogma_post_init_microengine (
  IN ogma_handle_t ogma_handle
  )
{
  UINT16 Data;

  /* Get phy back to normal operation */
  Data = ogma_get_phy_reg (ogma_handle, OGMA_PHY_REG_ADDR_CONTROL) &
         ~(1U << OGMA_PHY_CONTROL_REG_LOOPBACK);

  ogma_set_phy_reg (ogma_handle, OGMA_PHY_REG_ADDR_CONTROL, Data);

  while ((ogma_get_phy_reg (ogma_handle, OGMA_PHY_REG_ADDR_CONTROL) &
          (1U << OGMA_PHY_CONTROL_REG_LOOPBACK)) != 0);

  Data |= (1U << OGMA_PHY_CONTROL_REG_RESET);

  /* Apply software reset */
  ogma_set_phy_reg (ogma_handle, OGMA_PHY_REG_ADDR_CONTROL, Data);

  while ((ogma_get_phy_reg (ogma_handle, OGMA_PHY_REG_ADDR_CONTROL) &
          (1U << OGMA_PHY_CONTROL_REG_RESET)) != 0);
}

ogma_err_t ogma_init (
    void *base_addr,
    pfdep_dev_handle_t dev_handle,
    const ogma_param_t *param_p,
    const void *dma_hm_mc_addr,
    ogma_uint32 dma_hm_mc_len,
    const void *dma_mh_mc_addr,
    ogma_uint32 dma_mh_mc_len,
    const void *pktc_mc_addr,
    ogma_uint32 pktc_mc_len,
    ogma_handle_t *ogma_handle_p
    )
{
    ogma_int i;
    ogma_uint32 domain = 0, value;
    ogma_err_t ogma_err;
    ogma_ctrl_t *ctrl_p = NULL;

    ogma_bool inten_reg_hard_lock_init_flag = OGMA_FALSE;
    ogma_bool clk_ctrl_hard_lock_init_flag = OGMA_FALSE;

    ogma_bool all_lock_init_done_flag = OGMA_FALSE;

    pfdep_err_t pfdep_err;

    if ( ( param_p == NULL) ||
         ( ogma_handle_p == NULL) ) {
        return OGMA_ERR_PARAM;
    }

    if ( ogma_global.list_entry_num + 1 > OGMA_INSTANCE_NUM_MAX) {
        return OGMA_ERR_INVALID;
    }

    if ((! param_p->desc_ring_param[OGMA_DESC_RING_ID_NRM_TX].valid_flag) &&
        (! param_p->desc_ring_param[OGMA_DESC_RING_ID_NRM_RX].valid_flag)) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_init.\n"
                     "Please set invalid packet desc_ring_param valid_flag.\n");
        return OGMA_ERR_DATA;
    }

    if ( param_p->use_gmac_flag) {
        if ( ( param_p->gmac_config.phy_interface !=
              OGMA_PHY_INTERFACE_GMII) &&
            ( param_p->gmac_config.phy_interface !=
              OGMA_PHY_INTERFACE_RGMII) &&
            ( param_p->gmac_config.phy_interface !=
              OGMA_PHY_INTERFACE_RMII) ) {
            pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                         "An error occurred at ogma_init.\n"
                         "Please set phy_interface to valid value.\n");
            return OGMA_ERR_DATA;
        }
    } else {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_init.\n"
                     "Please set use_gmac_flag OGMA_TRUE.\n");
        return OGMA_ERR_DATA;
    }

    if ( param_p->phy_addr >= 32) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "Error: phy_addr out of range\n");
        return OGMA_ERR_DATA;
    }

    ogma_err = ogma_probe_hardware( base_addr);

    if ( ogma_err != OGMA_ERR_OK) {
        return ogma_err;
    }

    if ( !ogma_global.valid_flag) {
        ogma_global_init();
    }

    if ( ( ctrl_p = pfdep_malloc( sizeof( ogma_ctrl_t) ) ) == NULL) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_init.\n"
                     "Failed to ogma_handle memory allocation.\n");
        return OGMA_ERR_ALLOC;
    }

    pfdep_memset( ctrl_p, 0, sizeof( ogma_ctrl_t) );

    ctrl_p->base_addr = base_addr;

    ctrl_p->dev_handle = dev_handle;

    pfdep_memcpy( ( void *)&ctrl_p->param,
                  ( void *)param_p,
                  sizeof( ogma_param_t) );

    /* Initialize hardware lock */
    pfdep_err = pfdep_init_hard_lock( &ctrl_p->inten_reg_hard_lock);
    if ( pfdep_err != PFDEP_ERR_OK) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_init.\n"
                     "Failed to inten_reg_hard_lock's initialization.\n");
       ogma_err = OGMA_ERR_ALLOC;
       goto err;
    }
    inten_reg_hard_lock_init_flag = OGMA_TRUE;

    pfdep_err = pfdep_init_hard_lock( &ctrl_p->clk_ctrl_hard_lock);
    if ( pfdep_err != PFDEP_ERR_OK) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_init.\n"
                     "Failed to clk_ctrl_hard_lock's initialization.\n");
        ogma_err = OGMA_ERR_ALLOC;
        goto err;
    }
    clk_ctrl_hard_lock_init_flag = OGMA_TRUE;

    all_lock_init_done_flag = OGMA_TRUE;

    pfdep_err = pfdep_dma_malloc( dev_handle,
                                  OGMA_DUMMY_DESC_ENTRY_LEN,
                                  &ctrl_p->dummy_desc_entry_addr,
                                  &ctrl_p->dummy_desc_entry_phys_addr);

    if ( pfdep_err != PFDEP_ERR_OK) {
        ogma_err = OGMA_ERR_ALLOC;
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_init.\n"
                     "Failed to dummy_desc_entry's memory allocation.\n");
        goto err;
    }

    /* clear dummy desc entry */
    pfdep_memset( ctrl_p->dummy_desc_entry_addr,
                  0,
                  OGMA_DUMMY_DESC_ENTRY_LEN);

    ogma_reset_hardware( ctrl_p);

    if ( param_p->use_gmac_flag) {
        domain |= OGMA_CLK_EN_REG_DOM_G;
    }

    ogma_push_clk_req( ctrl_p, domain);

    /* set PKT_CTRL */
    value = ogma_calc_pkt_ctrl_reg_param( &param_p->pkt_ctrl_param);

    ogma_write_reg( ctrl_p,
                    OGMA_REG_ADDR_PKT_CTRL,
                    value);

    if ( param_p->use_jumbo_pkt_flag) {

        ctrl_p->rx_pkt_buf_len = OGMA_RX_JUMBO_PKT_BUF_LEN;

        value = ogma_read_reg( ctrl_p,
                               OGMA_REG_ADDR_PKT_CTRL);

        value |= OGMA_PKT_CTRL_REG_EN_JUMBO;

        ogma_write_reg( ctrl_p,
                        OGMA_REG_ADDR_PKT_CTRL,
                        value);
    } else {

        ctrl_p->rx_pkt_buf_len = OGMA_RX_PKT_BUF_LEN;

    }

    /* set pkt desc ring config */
    for ( i = 0; i <= OGMA_DESC_RING_ID_MAX; i++) {
        if (  ctrl_p->param.desc_ring_param[i].valid_flag) {
            value =
                ( ctrl_p->param.desc_ring_param[i].tmr_mode_flag <<
                  OGMA_REG_DESC_RING_CONFIG_TMR_MODE) |
                ( ctrl_p->param.desc_ring_param[i].little_endian_flag <<
                  OGMA_REG_DESC_RING_CONFIG_DAT_ENDIAN) ;

            ogma_write_reg( ctrl_p,
                            desc_ring_config_reg_addr[i],
                            value);

        }
    }

    /* set microengines */
    ogma_set_microcode(ctrl_p,
                       dma_hm_mc_addr,
                       dma_hm_mc_len,
                       dma_mh_mc_addr,
                       dma_mh_mc_len,
                       pktc_mc_addr,
                       pktc_mc_len);

    /* alloc desc_ring*/
    for( i = 0; i <= OGMA_DESC_RING_ID_MAX; i++) {
        ogma_err = ogma_alloc_desc_ring( ctrl_p, (ogma_desc_ring_id_t)i);
        if ( ogma_err != OGMA_ERR_OK) {
            pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                         "An error occurred at ogma_init.\n"
                         "Failed to ring id NO.%d memory allocation.\n",
                         i);
            goto err;
        }
    }

    if ( param_p->desc_ring_param[OGMA_DESC_RING_ID_NRM_RX].valid_flag) {
        if ( ( ogma_err = ogma_setup_rx_desc_ring(
                   ctrl_p,
                   &ctrl_p->desc_ring[OGMA_DESC_RING_ID_NRM_RX] ) )
             != OGMA_ERR_OK) {
            pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                         "An error occurred at ogma_init.\n"
                         "Failed to NRM_RX packet memory allocation.\n");
            goto err;
        }
    }

    /* microengines need domain G */
    ogma_push_clk_req( ctrl_p, OGMA_CLK_EN_REG_DOM_G);

    /* set DMA tmr ctrl*/
    ogma_write_reg( ctrl_p, OGMA_REG_ADDR_DMA_TMR_CTRL,
                    ( ogma_uint32)( ( OGMA_CONFIG_CLK_HZ / OGMA_CLK_MHZ) - 1) );

    /*
     * Do pre-initialization tasks for microengine
     *
     * In particular, we put phy in loopback mode
     * in order to make sure RXCLK keeps provided to mac
     * irrespective of phy link status,
     * which is required for microengine intialization.
     * This will be disabled once microengine initialization complete.
     */
    ogma_pre_init_microengine (ctrl_p);

    /* start microengines */
    ogma_write_reg( ctrl_p, OGMA_REG_ADDR_DIS_CORE, 0);

    if ( pfdep_msleep(1) != PFDEP_ERR_OK) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_init.\n"
                     "Failed to waiting for microcode initialize end.\n");
        ogma_err = OGMA_ERR_INTERRUPT;
        goto err;
    }

    /* check microcode load end & start core */
    value = ogma_read_reg( ctrl_p, OGMA_REG_ADDR_TOP_STATUS);

    if ( ( value & OGMA_TOP_IRQ_REG_ME_START) == 0) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_init.\n"
                     "Failed to microcode loading.\n");
        ogma_err = OGMA_ERR_INVALID;
        goto err;
    }

    /*
     * Do post-initialization tasks for microengine
     *
     * We put phy in normal mode and apply reset.
     */
    ogma_post_init_microengine (ctrl_p);

    /* clear microcode load end status */
    ogma_write_reg( ctrl_p, OGMA_REG_ADDR_TOP_STATUS,
                    OGMA_TOP_IRQ_REG_ME_START);

    ogma_pop_clk_req( ctrl_p, OGMA_CLK_EN_REG_DOM_G);

    ctrl_p->core_enabled_flag = OGMA_TRUE;

    ctrl_p->next_p = ogma_global.list_head_p;

    ogma_global.list_head_p = ctrl_p;

    ++ogma_global.list_entry_num;

    *ogma_handle_p = ctrl_p;

#if 1
    {

#define OGMA_PKT_CTRL_REG_MODE_TAIKI        (1UL << 28)
#define OGMA_DMA_MH_CTRL_REG_MODE_TRANS (1UL << 20)
#define OGMA_TOP_IRQ_REG_MODE_TRANS_COMP (1UL <<  4)
#define OGMA_MODE_TRANS_COMP_IRQ_T2N (1UL << 19)

        /* Read Pkt ctrl register */
        value = ogma_read_reg( ctrl_p, OGMA_REG_ADDR_PKT_CTRL);
        value |= OGMA_PKT_CTRL_REG_MODE_TAIKI;

        /* change to noromal mode */
        ogma_write_reg( ctrl_p,
                        OGMA_REG_ADDR_DMA_MH_CTRL,
                        OGMA_DMA_MH_CTRL_REG_MODE_TRANS);

        ogma_write_reg( ctrl_p,
                        OGMA_REG_ADDR_PKT_CTRL,
                        value);

        while ((ogma_read_reg(ctrl_p, OGMA_REG_ADDR_MODE_TRANS_COMP_STATUS) &
                OGMA_MODE_TRANS_COMP_IRQ_T2N) == 0) {
            ;
        }

    }
#endif

    /* Print microcode version information. */
    pfdep_print(PFDEP_DEBUG_LEVEL_NOTICE,
                "Microcode version: %08x\n",
                ogma_read_reg( ctrl_p,
                               mc_ver_reg_addr) );

    return OGMA_ERR_OK;

err:
    if ( !all_lock_init_done_flag) {


        if ( clk_ctrl_hard_lock_init_flag) {
            pfdep_uninit_hard_lock( &ctrl_p->clk_ctrl_hard_lock);
        }

        if ( inten_reg_hard_lock_init_flag) {
            pfdep_uninit_hard_lock( &ctrl_p->inten_reg_hard_lock);
        }

    } else {

        ogma_internal_terminate( ctrl_p);

    }

    pfdep_free( ctrl_p);

    return ogma_err;
}

STATIC void ogma_internal_terminate (
    ogma_ctrl_t *ctrl_p
    )
{
    ogma_int i;

    ogma_reset_hardware( ctrl_p);

    /* free desc_ring */
    for( i = 0; i <= OGMA_DESC_RING_ID_MAX; i++) {
        ogma_free_desc_ring( ctrl_p, &ctrl_p->desc_ring[i] );
    }

    if ( ctrl_p->dummy_desc_entry_addr != NULL) {
        pfdep_dma_free( ctrl_p->dev_handle,
                        OGMA_DUMMY_DESC_ENTRY_LEN,
                        ctrl_p->dummy_desc_entry_addr,
                        ctrl_p->dummy_desc_entry_phys_addr);
    }

    pfdep_uninit_hard_lock ( &ctrl_p->inten_reg_hard_lock);


    pfdep_uninit_hard_lock ( &ctrl_p->clk_ctrl_hard_lock);

}

void ogma_terminate (
    ogma_handle_t ogma_handle
    )
{

    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;
    ogma_ctrl_t *tmp_ctrl_p = NULL, *old_tmp_ctrl_p = NULL;
    ogma_uint32 domain = 0;

    if ( ( ctrl_p == NULL) ||
         ( ogma_global.list_entry_num == 0) ) {
       return;
    }

    pfdep_assert( ogma_global.list_head_p != NULL);

    if ( ctrl_p->param.use_gmac_flag) {
        domain |= OGMA_CLK_EN_REG_DOM_G;
    }

    /* pop domain clock */
    ogma_pop_clk_req( ctrl_p, domain);

    tmp_ctrl_p = ogma_global.list_head_p;

    while(1) {
        if ( tmp_ctrl_p == NULL) {
            /* Could not found ctrl_p specified from the list */
            return;
        }
        if ( ctrl_p == tmp_ctrl_p) {
            if ( old_tmp_ctrl_p != NULL) {
                old_tmp_ctrl_p->next_p = ctrl_p->next_p;
            } else {
                ogma_global.list_head_p = ctrl_p->next_p;
            }
            break;
        }
        old_tmp_ctrl_p = tmp_ctrl_p;
        tmp_ctrl_p = tmp_ctrl_p->next_p;
    }

    ogma_internal_terminate( ctrl_p);

    --ogma_global.list_entry_num;

    pfdep_free( ctrl_p);
    return;
}

ogma_err_t ogma_enable_top_irq (
    ogma_handle_t ogma_handle,
    ogma_uint32 irq_factor
    )
{
    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;


    if ( ctrl_p == NULL) {
        return OGMA_ERR_PARAM;
    }

    /* set irq_factor*/
    ogma_write_reg( ctrl_p, OGMA_REG_ADDR_TOP_INTEN_SET, irq_factor);

    return OGMA_ERR_OK;
}

ogma_err_t ogma_disable_top_irq (
    ogma_handle_t ogma_handle,
    ogma_uint32 irq_factor
    )
{
    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;

    if ( ctrl_p == NULL) {
        return OGMA_ERR_PARAM;
    }

    /* clear irq_factor*/
    ogma_write_reg( ctrl_p, OGMA_REG_ADDR_TOP_INTEN_CLR, irq_factor);

    return OGMA_ERR_OK;
}

ogma_err_t ogma_enable_desc_ring_irq (
    ogma_handle_t ogma_handle,
    ogma_desc_ring_id_t ring_id,
    ogma_uint32 irq_factor
    )
{
    ogma_err_t ogma_err = OGMA_ERR_OK;
    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;
    ogma_desc_ring_t *desc_ring_p;

    pfdep_err_t pfdep_err;
    pfdep_soft_lock_ctx_t soft_lock_ctx;

    if ( ctrl_p == NULL) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_enable_desc_ring_irq.\n"
                     "Please set valid ogma_handle.\n");
        return OGMA_ERR_PARAM;
    }

    if ( ring_id > OGMA_DESC_RING_ID_MAX) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_enable_desc_ring_irq.\n"
                     "Please select ring id number between 0 and %d.\n",
                     OGMA_DESC_RING_ID_MAX);
        return OGMA_ERR_PARAM;
    }

    if ( !ctrl_p->desc_ring[ring_id].param.valid_flag) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_enable_desc_ring_irq.\n"
                     "Please select valid desc ring.\n");
        return OGMA_ERR_NOTAVAIL;
    }

    desc_ring_p = &ctrl_p->desc_ring[ring_id];

    /* get soft lock */
    pfdep_err = pfdep_acquire_soft_lock (
        &desc_ring_p->soft_lock,
        &soft_lock_ctx);

    if ( pfdep_err != PFDEP_ERR_OK) {
        return OGMA_ERR_INTERRUPT;
    }

    if ( !desc_ring_p->running_flag) {
        pfdep_release_soft_lock( &desc_ring_p->soft_lock,
                                 &soft_lock_ctx);
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_enable_desc_ring_irq.\n"
                     "Please select running desc ring.\n");
        return OGMA_ERR_NOTAVAIL;
    }

    /* set irq_factor*/
    ogma_write_reg( ctrl_p,
                    desc_ring_irq_inten_set_reg_addr[ring_id],
                    irq_factor);

    /* free soft_lock*/
    pfdep_release_soft_lock( &desc_ring_p->soft_lock,
                             &soft_lock_ctx);
    return ogma_err;
}

ogma_err_t ogma_disable_desc_ring_irq (
    ogma_handle_t ogma_handle,
    ogma_desc_ring_id_t ring_id,
    ogma_uint32 irq_factor
    )
{
    ogma_err_t ogma_err = OGMA_ERR_OK;
    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;

    if ( ctrl_p == NULL) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_disable_desc_ring_irq.\n"
                     "Please set valid ogma_handle.\n");
        return OGMA_ERR_PARAM;
    }

    if ( ring_id > OGMA_DESC_RING_ID_MAX) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_disable_desc_ring_irq.\n"
                     "Please select ring id number between 0 and %d.\n",
                     OGMA_DESC_RING_ID_MAX);
        return OGMA_ERR_PARAM;
    }

    if ( !ctrl_p->desc_ring[ring_id].param.valid_flag) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_disable_desc_ring_irq.\n"
                     "Please select valid desc ring.\n");
        return OGMA_ERR_NOTAVAIL;
    }

    /* Clear irq factor*/
    ogma_write_reg( ctrl_p,
                    desc_ring_irq_inten_clr_reg_addr[ring_id],
                    irq_factor);

    return ogma_err;
}

ogma_err_t ogma_enable_pkt_irq (
    ogma_handle_t ogma_handle,
    ogma_uint32 irq_factor
    )
{
    ogma_err_t ogma_err = OGMA_ERR_OK;
    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;

    if ( ctrl_p == NULL) {
        return OGMA_ERR_PARAM;
    }

    /* set irq_factor*/
    ogma_write_reg( ctrl_p, OGMA_REG_ADDR_PKT_INTEN_SET,
                    ( irq_factor & OGMA_PKT_IRQ_ALL) );

    return ogma_err;
}

ogma_err_t ogma_disable_pkt_irq (
    ogma_handle_t ogma_handle,
    ogma_uint32 irq_factor
    )
{
    ogma_err_t ogma_err = OGMA_ERR_OK;
    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;

    if ( ctrl_p == NULL) {
        return OGMA_ERR_PARAM;
    }

    /* clear irq_factor*/
    ogma_write_reg( ctrl_p,
                    OGMA_REG_ADDR_PKT_INTEN_CLR,
                    ( irq_factor & OGMA_PKT_IRQ_ALL) );

    return ogma_err;
}


ogma_uint32 ogma_get_top_irq_enable (
    ogma_handle_t ogma_handle
    )
{
    ogma_uint32 value;
    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;

    if ( ctrl_p == NULL) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_get_top_irq_enable.\n"
                     "Please set valid ogma_handle.\n");
        return 0;
    }

    value = ogma_read_reg( ctrl_p, OGMA_REG_ADDR_TOP_INTEN);

    return value;

}


ogma_uint32 ogma_get_top_irq_status (
    ogma_handle_t ogma_handle,
    ogma_bool mask_flag
    )
{
    ogma_uint32 value;
    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;

    if ( ctrl_p == NULL) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_get_top_irq_status.\n"
                     "Please set valid ogma_handle.\n");
        return 0;
    }

    value = ogma_read_reg( ctrl_p, OGMA_REG_ADDR_TOP_STATUS);

    if ( mask_flag) {
        value &= ogma_read_reg( ctrl_p, OGMA_REG_ADDR_TOP_INTEN);
    }

    return value;
}

ogma_err_t ogma_clear_top_irq_status (
    ogma_handle_t ogma_handle,
    ogma_uint32 value
    )
{
    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;

    if ( ctrl_p == NULL) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_clear_top_irq_status.\n"
                     "Please set valid ogma_handle.\n");
        return OGMA_ERR_PARAM;
    }

    /* Write clear irq top  status */
    ogma_write_reg( ctrl_p,
                    OGMA_REG_ADDR_TOP_STATUS,

                    ( value & OGMA_TOP_IRQ_REG_ME_START) );

    return OGMA_ERR_OK;
}

ogma_uint32 ogma_get_desc_ring_irq_enable (
    ogma_handle_t ogma_handle,
    ogma_desc_ring_id_t ring_id
    )
{
    ogma_uint32 value;
    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;

    if ( ctrl_p == NULL) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_get_desc_ring_irq_enable.\n"
                     "Please set valid ogma_handle.\n");
        return 0;
    }

    if ( ring_id > OGMA_DESC_RING_ID_MAX) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_get_desc_ring_irq_enable.\n"
                     "Please select ring id number between 0 and %d.\n",
                     OGMA_DESC_RING_ID_MAX);
        return 0;
    }

    if ( !ctrl_p->desc_ring[ring_id].param.valid_flag) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_get_desc_ring_irq_enable.\n"
                     "Please select valid desc ring.\n");
        return 0;
    }

    value = ogma_read_reg( ctrl_p,
                           desc_ring_irq_inten_reg_addr[ring_id] );

    return value;
}


ogma_uint32 ogma_get_desc_ring_irq_status (
    ogma_handle_t ogma_handle,
    ogma_desc_ring_id_t ring_id,
    ogma_bool mask_flag
    )
{
    ogma_uint32 value;
    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;

    if ( ctrl_p == NULL) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_get_desc_ring_irq_status.\n"
                     "Please set valid ogma_handle.\n");
        return 0;
    }

    if ( ring_id > OGMA_DESC_RING_ID_MAX) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_get_desc_ring_irq_status.\n"
                     "Please select ring id number between 0 and %d.\n",
                     OGMA_DESC_RING_ID_MAX);
        return 0;
    }

    if ( !ctrl_p->desc_ring[ring_id].param.valid_flag) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_get_desc_ring_irq_status.\n"
                     "Please select valid desc ring.\n");
        return 0;
    }

    value = ogma_read_reg( ctrl_p,
                           desc_ring_irq_status_reg_addr[ring_id] );

    if ( mask_flag) {
        value &= ogma_read_reg( ctrl_p,
                                desc_ring_irq_inten_reg_addr[ring_id] );
    }

    return value;
}



ogma_err_t ogma_clear_desc_ring_irq_status (
    ogma_handle_t ogma_handle,
    ogma_desc_ring_id_t ring_id,
    ogma_uint32 value
    )
{

    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;

    if ( ctrl_p == NULL) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_clear_desc_ring_irq_status.\n"
                     "Please set valid ogma_handle.\n");
        return OGMA_ERR_PARAM;
    }

    if ( ring_id > OGMA_DESC_RING_ID_MAX) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_clear_desc_ring_irq_status.\n"
                     "Please select ring id number between 0 and %d.\n",
                     OGMA_DESC_RING_ID_MAX);
        return OGMA_ERR_PARAM;
    }

    if ( !ctrl_p->desc_ring[ring_id].param.valid_flag) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_clear_desc_ring_irq_status.\n"
                     "Please select valid desc ring.\n");
        return OGMA_ERR_NOTAVAIL;
    }

    /* Write clear descring irq status */
    ogma_write_reg( ctrl_p,
                    desc_ring_irq_status_reg_addr[ring_id],
                    ( value & ( OGMA_CH_IRQ_REG_EMPTY |
                                OGMA_CH_IRQ_REG_ERR) ) );

    return OGMA_ERR_OK;

}


ogma_uint32 ogma_get_pkt_irq_enable (
    ogma_handle_t ogma_handle
    )
{
    ogma_uint32 value;
    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;


    if ( ctrl_p == NULL) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_get_pkt_irq_enable.\n"
                     "Please set valid ogma_handle.\n");
        return 0;
    }

    value = ogma_read_reg( ctrl_p, OGMA_REG_ADDR_PKT_INTEN);

    value &= OGMA_PKT_IRQ_ALL;

    return value;

}

ogma_uint32 ogma_get_pkt_irq_status (
    ogma_handle_t ogma_handle,
    ogma_bool mask_flag
    )
{
    ogma_uint32 value;
    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;

    if ( ctrl_p == NULL) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_get_pkt_irq_statusnon_clear.\n"
                     "Please set valid ogma_handle.\n");
        return 0;
    }

    value = ogma_read_reg( ctrl_p, OGMA_REG_ADDR_PKT_STATUS);

    if ( mask_flag) {
        value &= ogma_read_reg( ctrl_p, OGMA_REG_ADDR_PKT_INTEN);
    }

    return value;
}

ogma_err_t ogma_clear_pkt_irq_status (
    ogma_handle_t ogma_handle,
    ogma_uint32 value
    )
{
    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;

    if ( ctrl_p == NULL) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_clear_pkt_irq_status.\n"
                     "Please set valid ogma_handle.\n");
        return OGMA_ERR_PARAM;
    }

    /* Write clear irq pkt  status */
    ogma_write_reg( ctrl_p,
                    OGMA_REG_ADDR_PKT_STATUS,
                    ( value & ( ( OGMA_PKT_IRQ_MAC_ER        |
                                  OGMA_PKT_IRQ_JUMBO_ER      |
                                  OGMA_PKT_IRQ_CHKSUM_ER     |
                                  OGMA_PKT_IRQ_HD_INCOMPLETE |
                                  OGMA_PKT_IRQ_HD_ER         |
                                  OGMA_PKT_IRQ_DRP_NO_MATCH) ) ) );

    return OGMA_ERR_OK;
}

#ifdef OGMA_CONFIG_REC_STAT
ogma_err_t ogma_get_stat_info (
    ogma_handle_t ogma_handle,
    ogma_stat_info_t *stat_info_p,
    ogma_bool clear_flag
    )
{

    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;

    if ( ( ctrl_p == NULL) || (stat_info_p == NULL) ) {
        return OGMA_ERR_PARAM;
    }

    pfdep_memcpy( stat_info_p,
                  &ctrl_p->stat_info,
                  sizeof( ogma_stat_info_t) );


    if ( clear_flag) {
        pfdep_memset( &ctrl_p->stat_info, 0, sizeof( ogma_stat_info_t) );
    }

    return OGMA_ERR_OK;

}
#endif /* OGMA_CONFIG_REC_STAT */

ogma_uint32 ogma_get_hw_ver (
    ogma_handle_t ogma_handle
    )
{
    ogma_uint32 value;
    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;

    if ( ctrl_p == NULL) {
        return 0;
    }

    value = ogma_read_reg( ctrl_p,
                           hw_ver_reg_addr);

    return value;
}


ogma_uint32 ogma_get_mcr_ver (
    ogma_handle_t ogma_handle
    )
{
    ogma_uint32 value;
    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;

    if ( ctrl_p == NULL) {
        return 0;
    }

    value = ogma_read_reg( ctrl_p,
                           mc_ver_reg_addr);

    return value;
}

ogma_uint32 ogma_get_mac_irq_enable (
    ogma_handle_t ogma_handle
    )
{
    ogma_uint32 value;
    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;

    if ( ctrl_p == NULL) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_ogma_get_mac_irq_enable.\n"
                     "Please set valid ogma_handle.\n");
        return 0;
    }

    value = ogma_read_reg( ctrl_p, OGMA_REG_ADDR_MAC_INTEN);


    return value;
}

ogma_uint32 ogma_get_mac_irq_status (
    ogma_handle_t ogma_handle,
    ogma_bool mask_flag
    )
{
    ogma_uint32 value;
    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;

    if ( ctrl_p == NULL) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_get_mac_irq_status.\n"
                     "Please set valid ogma_handle.\n");
        return 0;
    }


    value = ogma_read_reg( ctrl_p, OGMA_REG_ADDR_MAC_STATUS);

    if ( mask_flag) {
        value &= ogma_read_reg( ctrl_p, OGMA_REG_ADDR_MAC_INTEN);
    }


    return value;
}

ogma_err_t ogma_clear_mac_irq_status (
    ogma_handle_t ogma_handle,
    ogma_uint32 value
    )
{
    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;

    if ( ctrl_p == NULL) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_clear_mac_irq_status.\n"
                     "Please set valid ogma_handle.\n");
        return OGMA_ERR_PARAM;
    }


    /* Commented out because no write-clear bit exists now. */
#if 0
    ogma_write_reg( ctrl_p,
                    OGMA_REG_ADDR_MAC_STATUS,
                    ( value & /* T.B.D. */) );
#endif


    return OGMA_ERR_OK;

}

ogma_err_t ogma_enable_mac_irq (
    ogma_handle_t ogma_handle,
    ogma_uint32 irq_factor
    )
{
    ogma_uint32 value;
    ogma_err_t ogma_err = OGMA_ERR_OK;
    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;
    pfdep_hard_lock_ctx_t inten_reg_hard_lock_ctx;

    if ( ctrl_p == NULL) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_enable_mac_irq.\n"
                     "Please set valid ogma_handle.\n");
        return OGMA_ERR_PARAM;
    }

    /* get inten_reg_hard_lock */
    pfdep_acquire_hard_lock( &ctrl_p->inten_reg_hard_lock,
                             &inten_reg_hard_lock_ctx);

   value = ogma_read_reg( ctrl_p,
                          OGMA_REG_ADDR_MAC_INTEN);

   value |= irq_factor;

   ogma_write_reg( ctrl_p,
                   OGMA_REG_ADDR_MAC_INTEN,
                   value);


    /* free inten_reg_hard_lock*/
    pfdep_release_hard_lock( &ctrl_p->inten_reg_hard_lock,
                             &inten_reg_hard_lock_ctx);
    return ogma_err;
}

ogma_err_t ogma_disable_mac_irq (
    ogma_handle_t ogma_handle,
    ogma_uint32 irq_factor
    )
{
    ogma_uint32 value;
    ogma_err_t ogma_err = OGMA_ERR_OK;
    ogma_ctrl_t *ctrl_p = (ogma_ctrl_t *)ogma_handle;

    pfdep_hard_lock_ctx_t inten_reg_hard_lock_ctx;


    if ( ctrl_p == NULL) {
        pfdep_print( PFDEP_DEBUG_LEVEL_FATAL,
                     "An error occurred at ogma_disable_mac_irq.\n"
                     "Please set valid ogma_handle.\n");
        return OGMA_ERR_PARAM;
    }

    /* get inten_reg_hard_lock */
    pfdep_acquire_hard_lock( &ctrl_p->inten_reg_hard_lock,
                             &inten_reg_hard_lock_ctx);

   value = ogma_read_reg( ctrl_p,
                          OGMA_REG_ADDR_MAC_INTEN);

   value &= (~irq_factor);

   ogma_write_reg( ctrl_p,
                   OGMA_REG_ADDR_MAC_INTEN,
                   value);


    /* free inten_reg_hard_lock*/
    pfdep_release_hard_lock( &ctrl_p->inten_reg_hard_lock,
                             &inten_reg_hard_lock_ctx);
    return ogma_err;

}
