Пример #1
1
/* CHIP       : Arsenal5                                                */
cs_status arn5_dev_print_stats(cs_uint8 dev_id)
/* INPUTS     : o Device Id                                             */
/* OUTPUTS    : ----                                                    */
/* RETURNS    : CS_OK or CS_ERROR                                       */
/* DESCRIPTION:                                                         */
/* Prints statistics for the device.                                    */
/* It prints the Statistics of all the blocks that are registered and   */
/* are active in the current mode.                                      */
/* $rtn_hdr_end                                                         */
/************************************************************************/
{
  cs_uint32     error = 0 ;

  if (ARN5_IS_DEVICE_VALID(dev_id, &error) != TRUE) {
    CS_HNDL_ERROR(dev_id, error, NULL) ;
    return (CS_ERROR) ;
  }

  CS_PRINT("\n") ;
  if ( arn5_drvr_is_esc_code_enbld() ) {
    CS_PRINT("\033[7m Device-%d  STATISTICS :\033[m\n",
             dev_id) ;
  }
  else {
    CS_PRINT(" Device-%d  STATISTICS :\n", dev_id) ;
  }

  if ( ARN5_STATS_IS_BLK_REGISTERED((cs_uint16)dev_id, ARN5_DEVICE,
                                  ARN5_ID_HOST_IF) ) {
    arn5_dev_print_blk_stats(dev_id, ARN5_ID_HOST_IF) ;
  }

  return (CS_OK) ;
}
Пример #2
1
/*****************************************
 * Print Port Configuration Summary      *
 *****************************************/
static
void arn5_port_dump_cfg_summ(cs_uint16 port_id, arn5_port_summ_t * pSumm)
{
  if (pSumm == NULL) {
    CS_PRINT("Port-0x%x %s() ERROR: pSumm is NULL\n", port_id,
             __FUNCTION__) ;
    return ;
  }

  CS_PRINT(
  "==============================================================\n"
  ) ;
  if ( arn5_drvr_is_esc_code_enbld() ) {
    CS_PRINT("\033[4m") ; /* underline */
    CS_PRINT("\t\t Arsenal5 Port-0x%x Configuration Summary\n\n",
             port_id) ;
    CS_PRINT("\033[m") ; /* back to normal printing */
  }
  else {
    CS_PRINT("\t\t Arsenal5 Port-0x%x Configuration Summary\n\n",
             port_id) ;
  }

  CS_PRINT("Line Rate    = %s,   L2 Protocol   = %s\n",
           ARN5_GET_LINE_RATE_NAME(pSumm->line_rate),
           ARN5_GET_L2_PROT_NAME(pSumm->l2_prot)) ;
  CS_PRINT(
  "==============================================================\n"
  ) ;
}
Пример #3
0
/* CHIP       : Arsenal5                                        */
cs_status arn5_dev_dump_running_cfg(cs_uint8 dev_id)
/* INPUTS     : o Device Id                                     */
/* OUTPUTS    : ----                                            */
/* RETURNS    : CS_OK or CS_ERROR                               */
/* DESCRIPTION:                                                 */
/* Retrieves and prints the current run-time hardware           */
/* configuration for the specified device.                      */
/* $rtn_hdr_end                                                 */
/****************************************************************/
{
  arn5_dev_runcfg_t     * pRunCfg = NULL ;
  cs_uint32             err_code ;
  cs_status             status = CS_OK ;

  if ( !(ARN5_IS_DEVICE_VALID(dev_id, &err_code)) ) {
    CS_HNDL_ERROR(dev_id, err_code, NULL) ;
    return(CS_ERROR) ;
  }

  pRunCfg = (arn5_dev_runcfg_t *) CS_MALLOC( sizeof(arn5_dev_runcfg_t) ) ;

  if (pRunCfg == NULL) {
    CS_PRINT("ARN5 dev-%d ERROR: pRunCfg is NULL\n", dev_id) ;
    return (CS_ERROR) ;
  }

  if ( arn5_dev_get_running_cfg(dev_id, pRunCfg) != CS_OK ) {
    status = CS_ERROR ;
    goto RTN_EXIT ;
  }

  arn5_print_drvr_ver() ;  /* first print driver rel info */
  CS_PRINT("\n") ;
  CS_PRINT("\t\t *************************************\n") ;
  CS_PRINT("\t\t * DEVICE-%02d  RUNNING CONFIGURATION  *\n", dev_id) ;
  CS_PRINT("\t\t *************************************\n") ;

  CS_PRINT("Chip JTAG-Id= 0x%08x\n", pRunCfg->jtag_id) ;
  arn5_dev_dump_cfg_summ(dev_id, &pRunCfg->summ) ;

  CS_PRINT("\t GPIO alarm status pins = 0x%02x, output pins = 0x%04x,\n",
           pRunCfg->gpio.alm_status_map, pRunCfg->gpio.io_map) ;
  CS_PRINT("\t\t\t\t output values = 0x%04x\n",
           pRunCfg->gpio.output_values) ;

  CS_PRINT("=================================================\n") ;
  CS_PRINT("\t\t SPI Block\n\n") ;
  if ( arn5_spi_dev_dump_running_cfg(dev_id, pRunCfg)
       != CS_OK ) {
    status = CS_ERROR ;
    goto RTN_EXIT ;
  }

  RTN_EXIT :
    if (pRunCfg) CS_FREE(pRunCfg) ;
  return(status) ;
}
Пример #4
0
/*****************************************
 * Print Device Configuration Summary    *
 *****************************************/
static
void arn5_dev_dump_cfg_summ(cs_uint8 dev_id, arn5_dev_summ_t * pSumm)
{
  if (pSumm == NULL) {
    CS_PRINT("dev-%d %s() ERROR: pSumm is NULL!\n",
             dev_id, __FUNCTION__) ;
    return ;
  }

  CS_PRINT(
  "==============================================================\n"
  ) ;
  if ( arn5_drvr_is_esc_code_enbld() ) {
    CS_PRINT("\033[4m") ; /* underline */
    CS_PRINT("\t\t Arsenal5 Device-%d Configuration  Summary\n\n",
             dev_id) ;
    CS_PRINT("\033[m") ; /* back to normal printing */
  }
  else {
    CS_PRINT("\t\t Arsenal5 Device-%d Configuration Summary\n\n",
             dev_id) ;
  }

  CS_PRINT("Host Interface         = %s\n",
           ARN5_GET_HOST_IF_NAME(pSumm->host_if)) ;
  CS_PRINT(
  "==============================================================\n"
  ) ;
}
Пример #5
0
uint32_t objToBin(const char* _filePath
                  , bx::WriterSeekerI* _writer
                  , uint32_t _packUv
                  , uint32_t _packNormal
                  , bool _ccw
                  , bool _flipV
                  , bool _hasTangent
                  , float _scale
                 )
{
    FILE* file = fopen(_filePath, "rb");
    if (NULL == file)
    {
        CS_PRINT("Unable to open input file '%s'.", _filePath);
        return 0;
    }

    uint32_t size = (uint32_t)dm::fsize(file);
    char* data = new char[size+1];
    size = (uint32_t)fread(data, 1, size, file);
    data[size] = '\0';
    fclose(file);

    const uint32_t dataSize = objToBin((uint8_t*)data, _writer, _packUv, _packNormal, _ccw, _flipV, _hasTangent, _scale);

    delete [] data;

    return dataSize;
}
Пример #6
0
/*********************************************************************
 * Create Port-Id(or Port Handle)                                    *
 * Port-Id is created by OR'ing (dev_id << 8) and port-num.          *
 * On successful assignment of the Port-Id, memory for the Port      *
 * Control Block(PCB) will be dynamically allocated and returned     *
 * to the user.                                                      *
 *********************************************************************/
cs_status  arn5_dev_create_port_id(cs_uint8 dev_id,
                                  arn5_port_summ_t * pSumm,
                                  cs_uint16 * p_port_id,
                                  arn5_port_cb_t ** p_ppcb,
                                  cs_uint8 slice_num)
{
  arn5_dev_cb_t  * pdevcb = ARN5_DEV_ID_TO_DEVCB_PTR(dev_id) ;

  if (pdevcb == NULL || p_port_id == NULL || p_ppcb == NULL) {
    return (CS_ERROR) ;
  }

  if (slice_num > ARN5_MAX_NUM_PORTS) {
    return (CS_ERROR) ;
  }

  *p_port_id = ARN5_INVALID_PORT_ID ;
  *p_ppcb    = NULL ;

  if (pdevcb->ppcb[slice_num]) { /* check if it is already in-use */
    CS_PRINT("Dev-%d ERROR: slice-%d already in use!\n",
             dev_id, slice_num) ;
    return (CS_ERROR) ;
  }

  *p_ppcb = (arn5_port_cb_t *) CS_MALLOC( sizeof(arn5_port_cb_t) ) ;
  if (*p_ppcb == NULL) {
    CS_HNDL_ERROR(dev_id, EARN5_DEV_MALLOC_FAILED, NULL) ;
    return (CS_ERROR) ;
  }
  pdevcb->ppcb[slice_num] = *p_ppcb ;
  *p_port_id = ( (dev_id << 8) | slice_num ) ;
  return (CS_OK) ;
}
Пример #7
0
/* CHIP       : Arsenal5                                                */
cs_status arn5_dev_print_sect_stats(cs_uint8 dev_id,
                        arn5_module_id_t mod_id, cs_uint16 sect_id)
/* INPUTS     : o Device Id                                             */
/*              o Module ID                                             */
/*              o Section ID                                            */
/* OUTPUTS    : ----                                                    */
/* RETURNS    : CS_OK or CS_ERROR                                       */
/* DESCRIPTION:                                                         */
/* Prints the Stats for the user specified section of the device.       */
/* Stats within a block are organised as a collection of section stats. */
/* Each section is identified by mod_id and section_id combo.           */
/* Refer to the individual header files for the section ID defines.     */
/*                                                                      */
/* The [mod_id] parameter is specified as  ARN5_ID_HOST_IF only         */
/* $rtn_hdr_end                                                         */
/************************************************************************/
{
  cs_uint32             error = 0 ;
  arn5_stats_sect_cb_t  * sect_cb = NULL ;
  arn5_stats_blk_cb_t   * blk_cb ;

  if (ARN5_IS_DEVICE_VALID(dev_id, &error) != TRUE) {
    CS_HNDL_ERROR(dev_id, error, NULL) ;
    return (CS_ERROR) ;
  }

  if (sect_id >= ARN5_STATS_MAX_SECT) {
    CS_HNDL_ERROR(dev_id, EARN5_DEV_RANGE_ERR, NULL) ;
    return (CS_ERROR) ;
  }

  blk_cb = arn5_stats_get_blk_cb((cs_uint16)dev_id, ARN5_DEVICE, mod_id) ;
  if (blk_cb == NULL) {
    CS_HNDL_ERROR(dev_id, EARN5_DEV_TBL_NULL,
           "%s not registered for Statistics\n", ARN5_GET_MOD_NAME(mod_id)) ;
    return (CS_ERROR) ;
  }

  if ((sect_cb = blk_cb->p_sect_cb[sect_id]) == NULL) {
    CS_HNDL_ERROR(dev_id, EARN5_DEV_TBL_NULL,
           "Section not registered for Statistics (%d)\n", sect_id) ;
    return (CS_ERROR) ;
  }

  if (sect_cb->enabled == FALSE) {
    CS_PRINT("STATISTICS DISABLED FOR %s section %s\n",
             blk_cb->blk_name, sect_cb->sect_name) ;
    return (CS_ERROR) ;
  }

  arn5_stats_print_sect_hdr((cs_uint16)dev_id, ARN5_DEVICE,
                           sect_cb->sect_name) ;

  arn5_stats_sect_cmn_op((cs_uint16)dev_id, ARN5_DEVICE, mod_id, sect_id,
                        sect_cb, ARN5_STATS_PRINT, CS_RX_AND_TX) ;

  return (CS_OK) ;
}
Пример #8
0
/* CHIP       : Arsenal5                                                */
cs_status arn5_dev_clear_sect_dir_stats(cs_uint8 dev_id,
                        arn5_module_id_t mod_id,
                        cs_uint16 sect_id, cs_dir_t dir)
/* INPUTS     : o Device Id                                             */
/*              o Module ID                                             */
/*              o Section ID                                            */
/*              o CS_RX or CS_TX or CS_RX_AND_TX                        */
/* OUTPUTS    : ----                                                    */
/* RETURNS    : CS_OK or CS_ERROR                                       */
/* DESCRIPTION:                                                         */
/* Clears the Stats for the section in user specified block's section.  */
/* It clears the stats and hw register for the direction specified.     */
/* Refer to the individual header files for the section ID defines.     */
/*                                                                      */
/* The [mod_id] parameter is specified as  ARN5_ID_HOST_IF only         */
/* $rtn_hdr_end                                                         */
/************************************************************************/
{
  cs_uint32             error = 0 ;
  arn5_stats_sect_cb_t  * stats_sect_cb = NULL ;
  arn5_stats_blk_cb_t   * stats_blk_cb ;

  if (ARN5_IS_DEVICE_VALID(dev_id, &error) != TRUE) {
    CS_HNDL_ERROR(dev_id, error, "\n") ;
    return (CS_ERROR) ;
  }

  if (sect_id >= ARN5_STATS_MAX_SECT) {
    CS_HNDL_ERROR(dev_id, EARN5_DEV_RANGE_ERR, NULL ) ;
    return (CS_ERROR) ;
  }

  stats_blk_cb = arn5_stats_get_blk_cb((cs_uint16)dev_id, ARN5_DEVICE,
                                      mod_id) ;
  if (stats_blk_cb == NULL) {
    CS_HNDL_ERROR(dev_id, EARN5_DEV_TBL_NULL,
           "%s not registered for Statistics\n", ARN5_GET_MOD_NAME(mod_id)) ;
    return (CS_ERROR) ;
  }

  if ((stats_sect_cb = stats_blk_cb->p_sect_cb[sect_id]) == NULL) {
    CS_HNDL_ERROR( dev_id, EARN5_DEV_TBL_NULL,
           "Section not registered for Statistics\n") ;
    return (CS_ERROR) ;
  }

  if (stats_sect_cb->enabled == FALSE) {
    CS_PRINT("STATISTICS DISABLED FOR %s section %s\n",
             stats_blk_cb->blk_name, stats_sect_cb->sect_name) ;
    return (CS_ERROR) ;
  }

  arn5_stats_sect_cmn_op((cs_uint16)dev_id, ARN5_DEVICE, mod_id,
                        sect_id, stats_sect_cb,
                        ARN5_STATS_CLEAR, dir) ;
  return (CS_OK) ;
}
Пример #9
0
/* CHIP       : Arsenal5                                        */
cs_status  arn5_dev_unregister(cs_uint8 dev_id)
/* INPUTS     : o Device Id                                     */
/* OUTPUTS    : ----                                            */
/* RETURNS    : CS_OK or CS_ERROR                               */
/* DESCRIPTION:                                                 */
/* Unregisters the device, by setting its state to init state.  */
/* All port and device API's related to this device should NOT  */
/* be called after this.                                        */
/* $rtn_hdr_end                                                 */
/****************************************************************/
{
  cs_uint32     ii ;
  arn5_dev_cb_t  * pdevcb ;
  arn5_dev_cb_t  ** p_pdevcb ;
  cs_uint32     err_code ;

  if ( !(ARN5_IS_DEVICE_VALID(dev_id, &err_code)) ) {
    CS_HNDL_ERROR(dev_id, err_code, ":dev_id(%d)\n",
                  dev_id) ;
    return (CS_ERROR) ;
  }

  p_pdevcb = &( (ARN5_GET_DEVCB_TBL())[dev_id] ) ;
  pdevcb =  *p_pdevcb ;

  /* need to check if this device is registered */
  if ( pdevcb == NULL)return (CS_OK) ;

  for (ii = 0; ii < ARN5_MAX_NUM_PORTS; ii++) {
    if (pdevcb->ppcb[ii]) {
      arn5_port_close( ARN5_DEV_PORT_NUM_TO_PORT_ID(dev_id, ii) ) ;
    }
  }

#ifdef POSIX_PTHREAD
  if (pdevcb->dbt.irq_poll.tid) {
    arn5_stop_irq_polling(dev_id) ; /* cancel irq polling thread */
  }
#endif /* POSIX_PTHREAD */

  CS_SEM_DESTROY(&pdevcb->sem.mpif);
  CS_SEM_DESTROY(&pdevcb->sem.host_if);

  arn5_stats_clean_all((cs_uint16)dev_id, ARN5_DEVICE) ;

  CS_FREE(pdevcb) ;
  *p_pdevcb = NULL ;

  CS_PRINT("\tARN5 device(%d) unregistered!\n", dev_id) ;

#ifndef RELEASE_PLATFORM
  cs_lab_dev_unregister(CS_CHIP_ARSENAL5, (cs_uint16)dev_id) ;
#endif

  return (CS_OK) ;
}
Пример #10
0
/*****************************************
 *         Verify port summary           *
 * Check that all the parameters in the  *
 * port configuration summary section    *
 * are valid.                            *
 *****************************************/
static
cs_status arn5_port_verify_summ(cs_uint8 dev_id, cs_uint16 port_id,
                               arn5_port_summ_t * pSumm)
{
  if (pSumm->l2_prot == ARN5_PORT_PROT_ETHERNET) {
    if (pSumm->line_rate != ARN5_PORT_RATE_GIGE) {
      CS_PRINT("Port-0x%x %s() ERROR: l2_prot(%d) is invalid!\n",
             port_id, __FUNCTION__, pSumm->l2_prot) ;
      return (CS_ERROR) ;
    }
  }
  else {
    if (pSumm->line_rate == ARN5_PORT_RATE_GIGE) {
      CS_PRINT("Port-0x%x %s() ERROR: l2_prot(%d) is invalid!\n",
             port_id, __FUNCTION__, pSumm->l2_prot) ;
      return (CS_ERROR) ;
    }
  }
  return (CS_OK) ;
}
Пример #11
0
/*****************************************
 *     Verify device summary             *
 * Check that all the parameters in the  *
 * device configuration summary section  *
 * are valid.                            *
 *****************************************/
static
cs_status arn5_dev_verify_summ(cs_uint8 dev_id, arn5_dev_summ_t * pSumm)
{
  if ( !(CS_IN_TEST_ENV()) ) {
    if ( (pSumm->host_if == ARN5_HOST_IF_SPI42) &&
         (!arn5_spi_dev_is_in_spi42_mode(dev_id))) {
      CS_PRINT(
        "dev-%d ERROR: Actual Host IF is not in SPI4.2 mode.\n",
        dev_id) ;
      return (CS_ERROR) ;
    }

    if ( (pSumm->host_if == ARN5_HOST_IF_SPI3) &&
         (!arn5_spi_dev_is_in_spi3_mode(dev_id))) {
      CS_PRINT(
        "dev-%d ERROR: Actual Host IF is not in SPI3 mode.\n",
        dev_id) ;
      return (CS_ERROR) ;
    }
  }

  return (CS_OK) ;
}
Пример #12
0
/*************************************
 * Verify port configuration         *
 *************************************/
static
cs_status arn5_port_verify_cfg(cs_uint16 port_id, arn5_port_cfg_t * pCfg)
{
  arn5_dev_cb_t  * pdevcb ;

  pdevcb   =  ARN5_PORT_ID_TO_DEVCB_PTR(port_id) ;

  if (pCfg->summ.line_rate == ARN5_PORT_RATE_GIGE) {
    if (pCfg->framer_valid) {
      CS_PRINT("Port-0x%x %s() ERROR: framer_valid s/b FALSE in GIGE mode!\n",
             port_id, __FUNCTION__) ;
      return (CS_ERROR) ;
    }
  }
  else {
    if (pCfg->eth_valid) {
      CS_PRINT("Port-0x%x %s() ERROR: eth_valid s/b FALSE in SONET/SDH mode!\n",
             port_id, __FUNCTION__) ;
      return (CS_ERROR) ;
    }
  }

  return (CS_OK) ;
}
Пример #13
0
/* CHIP       : Arsenal5                                                */
cs_status arn5_dev_print_blk_stats(cs_uint8 dev_id,
                        arn5_module_id_t mod_id)
/* INPUTS     : o Device Id                                             */
/*              o Module ID                                             */
/* OUTPUTS    : ----                                                    */
/* RETURNS    : CS_OK or CS_ERROR                                       */
/* DESCRIPTION:                                                         */
/* Prints the block's statistics for the device.                        */
/*                                                                      */
/* The [mod_id] parameter is specified as  ARN5_ID_HOST_IF only         */
/* $rtn_hdr_end                                                         */
/************************************************************************/
{
  cs_uint32             error = 0, ii ;
  arn5_stats_blk_cb_t   * blk_cb ;

  if (ARN5_IS_DEVICE_VALID(dev_id, &error) != TRUE) {
    CS_HNDL_ERROR(dev_id, error, NULL) ;
    return (CS_ERROR) ;
  }

  blk_cb = arn5_stats_get_blk_cb((cs_uint16)dev_id, ARN5_DEVICE,  mod_id) ;
  if ( blk_cb == NULL ) {
    CS_HNDL_ERROR(dev_id, EARN5_DEV_TBL_NULL,
                  "%s not registered for Statistics\n",
                  ARN5_GET_MOD_NAME(mod_id)) ;
    return (CS_ERROR) ;
  }

  if (blk_cb->enabled == FALSE) {
    CS_PRINT("STATISTICS DISABLED FOR %s\n", blk_cb->blk_name) ;
    return (CS_ERROR) ;
  }

  arn5_stats_print_blk_hdr((cs_uint16)dev_id, ARN5_DEVICE,
                          blk_cb->blk_name) ;

  for (ii = 0; ii < ARN5_STATS_MAX_SECT; ii++) {
    /* Print Section stats if valid and are enabled */
    if ((blk_cb->p_sect_cb[ii]) &&
        (blk_cb->p_sect_cb[ii]->enabled)) {
      arn5_dev_print_sect_stats(dev_id, mod_id, ii) ;
    }
  }

  return (CS_OK) ;
}
Пример #14
0
/* CHIP       : Arsenal5                                              */
cs_status  arn5_lif_dump_running_cfg(cs_uint16 port_id,
                        arn5_port_runcfg_t * pRunCfg)
/* INPUTS     : o Port Id                                             */
/*              o Pointer to running configuration structure          */
/* OUTPUTS    : ----                                                  */
/* RETURNS    : CS_OK or CS_ERROR                                     */
/* DESCRIPTION:                                                       */
/* Prints the current run-time hardware configuration for the         */
/* this block.                                                        */
/*                                                                    */
/* The [pRunCfg] parameter is a pointer to the running                */
/* configuration data-structure allocated by the caller with          */
/* the configuration data from HW already retrieved and filled        */
/* in, prior to calling this API.                                     */
/* $_hdr_end                                                          */
/**********************************************************************/
{
  char                  * pS ;
  arn5_lif_runcfg_t     * pCfg = &pRunCfg->lif ;

  switch (pCfg->ref_clk) {
    case ARN5_LIF_REF_CLK_155 :
      pS = "155.52 MHz";
      break;

    case ARN5_LIF_REF_CLK_78 :
      pS = "77.76 MHz";
      break;

    case ARN5_LIF_REF_CLK_311 :
      pS = "311.04 MHz";
      break;

    case ARN5_LIF_REF_CLK_622 :
      pS = "622.08 MHz";
      break;

    default :
      pS = "Unknown";
      break;
  }
  CS_PRINT("Ref Clk                 = %s\n",
           pS);

  switch (pCfg->tx_clk_mode) {
    case ARN5_LIF_TX_CLK_LOCAL :
      pS = "Local";
      break;

    case ARN5_LIF_TX_CLK_LOOP_INTERNAL :
      pS = "Internal Loop";
      break;

    case ARN5_LIF_TX_CLK_LOOP_EXTERNAL :
      pS = "External Loop";
      break;

    default :
      pS = "Unknown";
      break;
  }
  CS_PRINT("Tx Clock Mode           = %s\n",
           pS);

  CS_PRINT("Clk Div1/2              = 0x%x/0x%x\n",
           pCfg->div1, pCfg->div2);

  CS_PRINT("Rx Clkout Ctrl          = %s\n",
           pCfg->rx_clkout_ctl ? "Enabled" : "Disabled");

  CS_PRINT("Rx Clkout Sel           = 0x%x\n",
           pCfg->rx_clkout_sel);

  CS_PRINT("Tx Clkout Ctrl          = %s\n",
           pCfg->tx_clkout_ctl ? "Enabled" : "Disabled");

  CS_PRINT("Tx Clkout Sel           = 0x%x\n",
           pCfg->tx_clkout_sel);

  CS_PRINT("Analog Terminal Lpbk    = %s\n",
           pCfg->analog_term_lb ? "Enabled" : "Disabled");

  CS_PRINT("Line Lpbk               = %s\n",
           pCfg->line_loopback ? "Enabled" : "Disabled");

  CS_PRINT("Terminal Lpbk           = %s\n",
           pCfg->terminal_loopback ? "Enabled" : "Disabled");

  return(CS_OK) ;
}
Пример #15
0
/*****************************************
 *   Initialize device hardware          *
 * All common sections of the chip that  *
 * are shared by all the ports will be   *
 * initialized.                          *
 *****************************************/
static
cs_status arn5_dev_init_hw(cs_uint8 dev_id, arn5_dev_cfg_t * pDevCfg)
{
  cs_uint32     jtag_id ;

  jtag_id = arn5_get_chip_jtag_id(dev_id) ;
  if ( !(ARN5_IS_JTAG_ID_CORRECT(jtag_id)) ) {
    CS_HNDL_ERROR(dev_id, EARN5_CHIP_JTAG_ID_MISMATCH,
                  ":chip's JTAG Id is 0x%x\n", jtag_id) ;
    return (CS_ERROR) ;
  }

//  CS_PRINT("JTAG ID: 0x%x\n", jtag_id);

// bypass bist temperory
#if 1
  if ( CS_IN_CUSTOMER_ENV() || CS_IN_LAB_ENV() ) {
    if ( arn5_wait_for_bist_done(dev_id, FALSE, TRUE, 50)
         != CS_OK ) {
      return (CS_ERROR) ;
    }

    if ( arn5_check_bist_status(dev_id, FALSE, TRUE) != CS_OK ) {
      CS_PRINT("\n*************************************************\n") ;
      CS_PRINT("SELF-TEST AND REPAIR(STAR) BIST ERROR !!!!!!\n") ;
      CS_PRINT("*************************************************\n\n") ;
    }
  }
#endif

  if ( arn5_dev_verify_summ(dev_id, &pDevCfg->summ) != CS_OK ) {
    return (CS_ERROR) ;
  }

  if ( arn5_dev_verify_cfg(dev_id, pDevCfg) != CS_OK ) {
    return (CS_ERROR) ;
  }

  /* sync slice enable state with hardware, assume slice 0 must be */
  /* powered on                                                    */
  if ( arn5_slice_ctl_pwr_down(dev_id, 0, CS_DISABLE)
       != CS_OK ) {
    return (CS_ERROR) ;
  }

  /* from now on, the slice enable is cached for driver to reference */
  /* Hard reset the chip */
  if ( arn5_dev_hard_reset(dev_id, ARN5_ID_ALL_BLOCKS, CS_RESET_TOGGLE)
       != CS_OK ) {
    return (CS_ERROR) ;
  }

  /* Configure GPIO */
  if ( arn5_mpif_cfg_gpio_alm_status(dev_id, pDevCfg->gpio.alm_status_map,
        0xff) != CS_OK ) {
    return (CS_ERROR) ;
  }

  if ( arn5_mpif_cfg_gpio_io(dev_id,
        (pDevCfg->gpio.io_map | (cs_uint16)pDevCfg->gpio.alm_status_map),
        0xffff) != CS_OK ) {
    return (CS_ERROR) ;
  }

  if ( arn5_mpif_write_gpio_output(dev_id,
        pDevCfg->gpio.output_values,
        0xffff) != CS_OK ) {
    return (CS_ERROR) ;
  }

  if ( arn5_mpif_dev_init_irq_cfg(dev_id, &pDevCfg->mpif)
        != CS_OK ) {
    return (CS_ERROR) ;
  }

  if ( arn5_spi_dev_init_cfg(dev_id, pDevCfg)
        != CS_OK ) {
    return (CS_ERROR) ;
  }

  return (CS_OK) ;
}
Пример #16
0
/* CHIP       : Arsenal5                                        */
cs_status arn5_dev_dump_vital_status(cs_uint8 dev_id)
/* INPUTS     : o Device Id                                     */
/* OUTPUTS    : ----                                            */
/* RETURNS    : CS_OK or CS_ERROR                               */
/* DESCRIPTION:                                                 */
/* Retrieves and prints the current status at a glance          */
/* This is mainly for debug purpose as most of status are       */
/* available via individual API's call.                         */
/* $rtn_hdr_end                                                 */
/****************************************************************/
{
  arn5_dev_cb_t         * pdevcb ;
  cs_uint8              * str = NULL ;
  cs_uint32             err_code ;
  cs_status             status = CS_OK ;

  if ( !(ARN5_IS_DEVICE_VALID(dev_id, &err_code)) ) {
    CS_HNDL_ERROR(dev_id, err_code, NULL) ;
    return(CS_ERROR) ;
  }

  pdevcb =  ARN5_DEV_ID_TO_DEVCB_PTR(dev_id) ;
  if (pdevcb->state != ARN5_DEV_STATE_INITIALIZED) { /* hwcfg not done */
    CS_HNDL_ERROR(dev_id, EARN5_DEV_INVALID_USER_ARG,
                  ": device hw cfg not done yet!\n") ;
    return (CS_ERROR) ;
  }

  CS_PRINT("\n") ;
  CS_PRINT("\t *** DEVICE-%d  Vital Status  ***\n", dev_id) ;
  CS_PRINT("=================================================\n") ;

  if (arn5_spi_dev_is_in_spi42_mode(dev_id)) {
    arn5_spi42_sync_t    spi42Status ;

    spi42Status = arn5_spi42_dev_get_sync_state(dev_id, CS_TX) ;
    if (spi42Status == ARN5_SPI42_IN_SYNC) {
      str = "In Sync" ;
    }
    else if (spi42Status == ARN5_SPI42_INIT_STATE) {
      str = "Init State" ;
    }
    else {
      str = "Out Of Sync" ;
    }
    CS_PRINT("Host SPI4.2 TX Status  = %s\n", str) ;

    spi42Status = arn5_spi42_dev_get_sync_state(dev_id, CS_RX) ;
    if (spi42Status == ARN5_SPI42_IN_SYNC) {
      str = "In Sync" ;
    }
    else if (spi42Status == ARN5_SPI42_INIT_STATE) {
      str = "Init State" ;
    }
    else {
      str = "Out Of Sync" ;
    }
    CS_PRINT("Host SPI4.2 RX status  = %s\n", str) ;
  }

  return(status) ;
}
Пример #17
0
/* CHIP       : Arsenal5                                        */
cs_status arn5_dev_get_running_cfg(cs_uint8 dev_id,
                                  arn5_dev_runcfg_t * pRunCfg)
/* INPUTS     : o Device Id                                     */
/*              o Pointer to Device Running Configuration       */
/* OUTPUTS    : ----                                            */
/* RETURNS    : CS_OK or CS_ERROR                               */
/* DESCRIPTION:                                                 */
/* Get the current run-time hardware configuration for the      */
/* specified device(chip).                                      */
/*                                                              */
/* The [pRunCfg] parameter is a pointer to the running          */
/* configuration data-structure allocated by the caller.        */
/* The driver is responsible for filling in ALL the fields in   */
/* the datastructure by reading from HW.                        */
/* $rtn_hdr_end                                                 */
/****************************************************************/
{
  ARN5_t          * pDev ;
  arn5_dev_cb_t   * pdevcb ;
  arn5_dev_summ_t * pSumm ;
  cs_uint32      err_code ;

  if ( !(ARN5_IS_DEVICE_VALID(dev_id, &err_code)) ) {
    CS_HNDL_ERROR(dev_id, err_code, NULL) ;
    return(CS_ERROR) ;
  }

  if ( pRunCfg == NULL ) {
    CS_HNDL_ERROR(dev_id, EARN5_DEV_CFG_NULL, NULL) ;
    return (CS_ERROR) ;
  }

  pDev = ARN5_DEV_ID_TO_DEV_BASE(dev_id) ;
  pdevcb =  ARN5_DEV_ID_TO_DEVCB_PTR(dev_id) ;
  CS_MEMSET( (void *)pRunCfg, 0, sizeof(arn5_dev_runcfg_t) ) ;
  CS_PRINT("ARN5 dev-%d: Retrieving device running configuration..\n",
           dev_id) ;

  /*
   * Get chip's JTAG-Id
   */
  pRunCfg->jtag_id = arn5_get_chip_jtag_id(dev_id) ;

  /*
   * Get device summary
   */
  pSumm = &pRunCfg->summ ;
  pSumm->host_if = ( arn5_spi_dev_is_in_spi42_mode(dev_id) ?
                     ARN5_HOST_IF_SPI42 : ARN5_HOST_IF_SPI3 ) ;

  /* set block valid flags */

  /* GPIO pin configuration */
  pRunCfg->gpio.alm_status_map = CS_REG_READ(&pDev->MicroIF.GPIOAlarmControl.wrd) ;
  pRunCfg->gpio.io_map =
    ((CS_REG_READ(&pDev->MicroIF.GPIODirection1.wrd) & 0x00ff) << 8) |
    ((CS_REG_READ(&pDev->MicroIF.GPIODirection0.wrd) & 0x00ff)) ;

  pRunCfg->gpio.output_values =
    ((CS_REG_READ(&pDev->MicroIF.GPIOOutput1.wrd) & 0x00ff) << 8) |
    ((CS_REG_READ(&pDev->MicroIF.GPIOOutput0.wrd) & 0x00ff)) ;

  /* Block configurations */
  if (arn5_spi_dev_get_running_cfg(dev_id, pRunCfg) != CS_OK) {
    return (CS_ERROR) ;
  }

  return (CS_OK) ;
}
Пример #18
0
/* CHIP       : Arsenal5                                        */
cs_status  arn5_dev_init(cs_uint8 dev_id, arn5_dev_cfg_t * pDevCfg)
/* INPUTS     : o Device Id                                     */
/* OUTPUTS    : ----                                            */
/* RETURNS    : CS_OK or CS_ERROR                               */
/* DESCRIPTION:                                                 */
/* Initializes the device state to ready after verifying the    */
/* JTAG Id of the chip and hard-resetting and configuring any   */
/* HW blocks that are common and shared by all the ports.       */
/*                                                              */
/* It does NOT do any port related initialization.              */
/*                                                              */
/* This API should be called only after the device corresponding*/
/* to this port has been registered.                            */
/* $rtn_hdr_end                                                 */
/****************************************************************/
{
  arn5_dev_cb_t  * pdevcb ;
  cs_uint32     err_code ;

  if ( !(ARN5_IS_DEVICE_VALID(dev_id, &err_code)) ) {
    CS_HNDL_ERROR(dev_id, err_code, NULL) ;
    return (CS_ERROR) ;
  }

  pdevcb =  ARN5_DEV_ID_TO_DEVCB_PTR(dev_id) ;
  if (pdevcb == NULL) {
    CS_PRINT("ARN5 dev-%d %s() ERROR: pdevcb is NULL\n",
             dev_id, __FUNCTION__) ;
    return(CS_ERROR) ;
  }

  if (pdevcb->state == ARN5_DEV_STATE_INVALID) {
    CS_PRINT("ARN5 dev-%d %s() ERROR: Device not registered\n",
             dev_id, __FUNCTION__) ;
    return(CS_ERROR) ;
  }

  if (pdevcb->state == ARN5_DEV_STATE_INITIALIZED) {
    cs_uint32  base_addr = pdevcb->base_addr ;

    /* re-init'ing the device - do unreg/reg device again */
    arn5_dev_unregister(dev_id) ;
    arn5_dev_register(dev_id, base_addr) ;

    /* Need to re-get the pointer because previous structure */
    /* has been rebuilt.                                     */
    pdevcb =  ARN5_DEV_ID_TO_DEVCB_PTR(dev_id) ;
  }

  //CS_PRINT(" before arn5_dev_init_data.\n");

  if ( arn5_dev_init_data(dev_id, pDevCfg) != CS_OK ) {
    return (CS_ERROR) ;
  }
 
  //CS_PRINT(" before arn5_dev_init_hw..\n");  
 
  if ( arn5_dev_init_hw(dev_id, pDevCfg) != CS_OK ) {
    return (CS_ERROR) ;
  }
  
  //CS_PRINT("\tARN5 dev-%d initialized: base addr = 0x%x\n",
  //         dev_id, pdevcb->base_addr) ;

#ifndef RELEASE_PLATFORM
  cs_lab_dev_init(CS_CHIP_ARSENAL5, (cs_uint16)dev_id) ;
#endif

  pdevcb->state = ARN5_DEV_STATE_INITIALIZED ;
  return (CS_OK) ;
}
Пример #19
0
/* CHIP       : Arsenal5                                        */
cs_status  arn5_dev_get_default_cfg(cs_uint8 dev_id,
                                   arn5_dev_cfg_t * pDevCfg)
/* INPUTS     : o Device Id                                     */
/* OUTPUTS    : ----                                            */
/* RETURNS    : CS_OK or CS_ERROR                               */
/* DESCRIPTION:                                                 */
/* Get the driver's default DEVICE configuration based on the   */
/* configuration summary provided(inside the config data-       */
/* structure).                                                  */
/* This information will be used by the driver in providing a   */
/* default chip configuration.                                  */
/*                                                              */
/* Note that, this API does not access or configure the chip and*/
/* only recommends to the caller a recommended configuration.   */
/* The caller can choose to use it as is, or with necessary     */
/* modifications when initializing the device.                  */
/* $rtn_hdr_end                                                 */
/****************************************************************/
{
  if ( !(ARN5_DRVR_IS_LOADED()) ) {
    CS_HNDL_ERROR(dev_id, EARN5_DRVR_NOT_LOADED, NULL) ;
    return (CS_ERROR) ;
  }

  if (dev_id >= ARN5_MAX_NUM_DEVICES) {
    CS_HNDL_ERROR( dev_id, EARN5_DEV_ID_OUT_OF_RANGE, NULL ) ;
    return(CS_ERROR) ;
  }

  if (pDevCfg == NULL) {
    CS_PRINT("ARN5 dev-%d: %s() ERROR - pDevCfg is NULL!\n",
             dev_id, __FUNCTION__) ;
    return (CS_ERROR) ;
  }

  /*
   * Ensure it is a valid summary before composing the default
   * configuration.
   */
  if ( arn5_dev_verify_summ(dev_id, &pDevCfg->summ) != CS_OK ) {
    return (CS_ERROR) ;
  }

  /* General Purpose I/O - GPIO[7:0] inputs and GPIO[15:8] outputs */
  pDevCfg->gpio.alm_status_map = 0 ;
 /* pDevCfg->gpio.io_map = 0x00ff ;*/
  pDevCfg->gpio.io_map = 0x00f0;
  pDevCfg->gpio.output_values = 0x0000 ;

  /* MPIF default IRQ's */
  if ( arn5_mpif_dev_get_default_irq_cfg(dev_id, &pDevCfg->summ, &pDevCfg->mpif)
         != CS_OK ) {
    return (CS_ERROR) ;
  }

  if ( arn5_spi_dev_get_default_cfg(dev_id, pDevCfg) != CS_OK ) {
    return (CS_ERROR) ;
  }

  return (CS_OK) ;
}
Пример #20
0
/* CHIP       : Arsenal5                                        */
cs_status  arn5_port_close(cs_uint16 port_id)
/* INPUTS     : o Port Id                                       */
/* OUTPUTS    : ----                                            */
/* RETURNS    : Port Id (or port handle)                        */
/* DESCRIPTION:                                                 */
/* This API deletes the port instance specified. It frees up    */
/* all the port data-structures that were dynamically           */
/* allocated.                                                   */
/* $rtn_hdr_end                                                 */
/****************************************************************/
{
  cs_uint32             err_code ;
  arn5_port_cb_t        * ppcb ;
  arn5_dev_cb_t         * pdcb ;
  cs_uint8              slice_num, dev_id ;


  if ( !(ARN5_IS_PORT_VALID(port_id, &err_code)) ) {
    CS_HNDL_ERROR(port_id, err_code, NULL) ;
    return (CS_ERROR) ;
  }

  pdcb = ARN5_PORT_ID_TO_DEVCB_PTR(port_id) ;
  ppcb = ARN5_PORT_ID_TO_PCB_PTR(port_id) ;

  switch (ppcb->summ.line_rate) {
    case ARN5_PORT_RATE_OC12C :
      if (pdcb->oc12_num) (pdcb->oc12_num)-- ;
      pdcb->total_rate_units -= 4 ;
      break ;

    case ARN5_PORT_RATE_OC3C :
      if (pdcb->oc3_num) (pdcb->oc3_num)-- ;
      pdcb->total_rate_units -= 1 ;
      break ;

    case ARN5_PORT_RATE_GIGE :
      if (pdcb->gige_num) (pdcb->gige_num)-- ;
      pdcb->total_rate_units -= 7 ;
      break ;

    default :
      if (pdcb->oc48_num) (pdcb->oc48_num)-- ;
      pdcb->total_rate_units -= 16 ;
      break ;
  }

  /* shut down the slice upon port close */
  /* drop the corresponding api chan as well */
  slice_num = ARN5_PORT_ID_TO_SLICE_NUM(port_id) ;
  dev_id = ARN5_PORT_ID_TO_DEV_ID(port_id) ;
  arn5_spi_drop_chan_data_ctl(dev_id, slice_num, TRUE) ;
  arn5_slice_ctl_pwr_down(dev_id, slice_num, CS_ENABLE) ;

  /* Deallocate the semaphores */
  arn5_port_destroy_sem(port_id) ;

  /* Free any dynamically allocated memory */
  arn5_port_free_mem(port_id) ;

  /* Finally, delete the port_id and de-allocate the Port PCB */
  arn5_dev_delete_port_id(port_id) ;

  CS_PRINT("\tPort-0x%04x closed\n", port_id) ;
  return (CS_OK) ;
}
Пример #21
0
/* CHIP       : Arsenal5                                        */
cs_status arn5_port_get_running_cfg(cs_uint16 port_id,
                        arn5_port_runcfg_t * pRunCfg)
/* INPUTS     : o Port Id                                       */
/*              o Pointer to Port Running Configuration         */
/* OUTPUTS    : ----                                            */
/* RETURNS    : CS_OK or CS_ERROR                               */
/* DESCRIPTION:                                                 */
/* Get the current run-time hardware configuration for the      */
/* specified device(chip).                                      */
/*                                                              */
/* The [pRunCfg] parameter is a pointer to the running          */
/* configuration data-structure allocated by the caller.        */
/* The driver is responsible for filling in ALL the fields in   */
/* the datastructure by reading from HW.                        */
/* $rtn_hdr_end                                                 */
/****************************************************************/
{
  cs_uint8            dev_id, port_num ;
  arn5_port_cb_t      * ppcb ;
  cs_uint32           err_code ;

  if ( pRunCfg == NULL ) {
    CS_HNDL_ERROR(port_id, EARN5_PORT_CFG_NULL, NULL) ;
    return (CS_ERROR) ;
  }

  if ( !(ARN5_IS_PORT_VALID(port_id, &err_code)) ) {
    CS_HNDL_ERROR(port_id, err_code, NULL) ;
    return(CS_ERROR) ;
  }

  dev_id    = ARN5_PORT_ID_TO_DEV_ID(port_id) ;
  port_num  = ARN5_PORT_ID_TO_PORT_NUM(port_id) ;
  ppcb      = ARN5_PORT_ID_TO_PCB_PTR(port_id) ;

  CS_MEMSET( (void *)pRunCfg, 0, sizeof(arn5_port_runcfg_t) ) ;
  CS_PRINT("ARN5 port-0x%x: Retrieving port running cfg...\n",
           port_id) ;

  /*
   * Get driver's dev_id
   */
   pRunCfg->dev_id = dev_id ;
  /*
   * Get port summary
   */
  pRunCfg->summ.line_rate = ARN5_GET_LINE_RATE_FROM_HW(port_id) ;
  pRunCfg->summ.l2_prot = ARN5_GET_L2_PROT_FROM_HW(port_id) ;
  pRunCfg->eth_valid = (pRunCfg->summ.line_rate == ARN5_PORT_RATE_GIGE) ;
  pRunCfg->framer_valid = !pRunCfg->eth_valid ;
  pRunCfg->lif_valid = TRUE ;
  pRunCfg->pprbs_valid = TRUE ;

  /*
   * Get port configuration
   */
  /* spi will get eth info if needed */
  if (arn5_spi_get_running_cfg(port_id, pRunCfg) != CS_OK) {
    return (CS_ERROR) ;
  }

  if (pRunCfg->framer_valid) {
    if (arn5_framer_get_running_cfg(port_id, pRunCfg) != CS_OK) {
      return (CS_ERROR) ;
    }
  }

  if (pRunCfg->eth_valid) {
    if (arn5_eth_get_running_cfg(port_id, pRunCfg) != CS_OK) {
      return (CS_ERROR) ;
    }
  }

  if (arn5_lif_get_running_cfg(port_id, pRunCfg) != CS_OK) {
    return (CS_ERROR) ;
  }

  if (pRunCfg->pprbs_valid) {
    if (arn5_pprbs_get_running_cfg(port_id, pRunCfg) != CS_OK) {
      return (CS_ERROR) ;
    }
  }

  return (CS_OK) ;
}
Пример #22
0
/* CHIP       : Arsenal5                                                */
cs_status arn5_dev_print_unit_stats(cs_uint8 dev_id,
                        arn5_module_id_t mod_id,
                        cs_uint16 sect_id, cs_uint16 unit_id)
/* INPUTS     : o Device Id                                             */
/*              o Module ID                                             */
/*              o Section ID                                            */
/*              o Unit ID                                               */
/* OUTPUTS    : ----                                                    */
/* RETURNS    : CS_OK or CS_ERROR                                       */
/* DESCRIPTION:                                                         */
/* Prints the Stats for the user specified unit for the device.         */
/* Statistics for the device are organised as a collection of block     */
/* stats. Each block has number of section stats identified by section  */
/* id. Each section then has unit stats. Unit stat is the atomic entity */
/* of the stats and carry RX and TX stats. Each unit is uniquely        */
/* identified by block_id, section_id and unit_id combo.                */
/* Refer to the individual header files for the section ID and unit_id  */
/* defines.                                                             */
/*                                                                      */
/* The [mod_id] parameter is specified as  ARN5_ID_HOST_IF only         */
/* $rtn_hdr_end                                                         */
/************************************************************************/
{
  cs_uint32             error = 0 ;
  arn5_stats_sect_cb_t  * stats_sect_cb = NULL ;
  arn5_stats_blk_cb_t   * stats_blk_cb ;
  arn5_stats_data_t     * p_unit_data ;

  if (ARN5_IS_DEVICE_VALID(dev_id, &error) != TRUE) {
    CS_HNDL_ERROR(dev_id, error, "\n") ;
    return (CS_ERROR) ;
  }

  if (sect_id >= ARN5_STATS_MAX_SECT) {
    CS_HNDL_ERROR(dev_id, EARN5_DEV_RANGE_ERR, NULL ) ;
    return (CS_ERROR) ;
  }

  stats_blk_cb = arn5_stats_get_blk_cb((cs_uint16)dev_id, ARN5_DEVICE,
                                      mod_id) ;
  if (stats_blk_cb == NULL) {
    CS_HNDL_ERROR(dev_id, EARN5_DEV_TBL_NULL,
           "%s not registered for Statistics\n", ARN5_GET_MOD_NAME(mod_id)) ;
    return (CS_ERROR) ;
  }

  if ((stats_sect_cb = stats_blk_cb->p_sect_cb[sect_id]) == NULL) {
    CS_HNDL_ERROR(dev_id, EARN5_DEV_TBL_NULL,
           "Section not registered for Statistics (%d)\n", sect_id) ;
    return (CS_ERROR) ;
  }

  if ( stats_sect_cb->enabled == FALSE ) {
    CS_PRINT("STATISTICS DISABLED FOR %s section %s\n",
             stats_blk_cb->blk_name, stats_sect_cb->sect_name) ;
    return (CS_ERROR) ;
  }

  p_unit_data = stats_sect_cb->pStats + unit_id ;
  if (*(stats_sect_cb->enbl_tbl + unit_id) == FALSE) {
    CS_PRINT("STATS DISABLED FOR %s : SECT_ID : %d UNIT_ID : %d\n",
             stats_blk_cb->blk_name, sect_id, unit_id) ;
    return (CS_ERROR) ;
  }

  arn5_set_sect_print_flag(0) ;

  return arn5_stats_unit_cmn_op((cs_uint16)dev_id, ARN5_DEVICE,
                               mod_id, sect_id, unit_id,
                               stats_sect_cb, ARN5_STATS_PRINT,
                               CS_RX_AND_TX,
                               FALSE) ;
}
Пример #23
0
/* CHIP       : Arsenal5                                        */
cs_status arn5_port_dump_running_cfg(cs_uint16 port_id)
/* INPUTS     : o Port Id                                       */
/* OUTPUTS    : ----                                            */
/* RETURNS    : CS_OK or CS_ERROR                               */
/* DESCRIPTION:                                                 */
/* Retrieves and prints the current run-time hardware           */
/* configuration for the specified port.                        */
/* $rtn_hdr_end                                                 */
/****************************************************************/
{
  arn5_port_runcfg_t    * pRunCfg = NULL ;
  cs_uint32             err_code ;
  cs_status             status = CS_OK ;

  if ( !(ARN5_IS_PORT_VALID(port_id, &err_code)) ) {
    CS_HNDL_ERROR(port_id, err_code, NULL) ;
    return(CS_ERROR) ;
  }

  pRunCfg = (arn5_port_runcfg_t *) CS_MALLOC( sizeof(arn5_port_runcfg_t) ) ;

  if (pRunCfg == NULL) {
    CS_PRINT("ARN5 port-0x%x ERROR: pRunCfg is NULL\n", port_id) ;
    return (CS_ERROR) ;
  }

  if ( arn5_port_get_running_cfg(port_id, pRunCfg) != CS_OK ) {
    status = CS_ERROR ;
    goto RTN_EXIT ;
  }

  arn5_print_drvr_ver() ;  /* first print driver rel info */
  CS_PRINT("\n") ;
  CS_PRINT("\t\t **************************************\n") ;
  CS_PRINT("\t\t * PORT-0x%04x  RUNNING CONFIGURATION *\n", port_id) ;
  CS_PRINT("\t\t **************************************\n") ;

  CS_PRINT("dev_id= 0x%x\n", pRunCfg->dev_id) ;

  arn5_port_dump_cfg_summ(port_id, &pRunCfg->summ) ;

  CS_PRINT("=================================================\n") ;
  CS_PRINT("\t\t SPI Block\n\n") ;
  if ( arn5_spi_dump_running_cfg(port_id, pRunCfg)
       != CS_OK ) {
    status = CS_ERROR ;
    goto RTN_EXIT ;
  }

  CS_PRINT("=================================================\n") ;
  CS_PRINT("\t\t Framer Block (%s)\n\n",
          (pRunCfg->framer_valid) ? "valid" : "invalid") ;
  if (pRunCfg->framer_valid) {
    if ( arn5_framer_dump_running_cfg(port_id, pRunCfg)
         != CS_OK ) {
      status = CS_ERROR ;
      goto RTN_EXIT ;
    }
  }

  CS_PRINT("=================================================\n") ;
  CS_PRINT("\t\t ETH Block (%s)\n\n",
          (pRunCfg->eth_valid) ? "valid" : "invalid") ;
  if (pRunCfg->eth_valid) {
    if ( arn5_eth_dump_running_cfg(port_id, pRunCfg)
         != CS_OK ) {
      status = CS_ERROR ;
      goto RTN_EXIT ;
    }
  }

  CS_PRINT("=================================================\n") ;
  CS_PRINT("\t\t LIF Block\n\n") ;
  if ( arn5_lif_dump_running_cfg(port_id, pRunCfg)
       != CS_OK ) {
    status = CS_ERROR ;
    goto RTN_EXIT ;
  }

  /* pprbs is valid only when any of pprbs gen or checker is enabled */
  CS_PRINT("=================================================\n") ;
  CS_PRINT("\t\t PPRBS Block (%s)\n\n",
           (pRunCfg->pprbs_valid) ? "valid" : "invalid") ;
  if (pRunCfg->pprbs_valid) {
    if ( arn5_pprbs_dump_running_cfg(port_id, pRunCfg)
         != CS_OK ) {
      status = CS_ERROR ;
      goto RTN_EXIT ;
    }
  }

RTN_EXIT :
  if (pRunCfg) CS_FREE(pRunCfg) ;
  return (status) ;
}
Пример #24
0
/* CHIP       : Arsenal5                                        */
cs_status arn5_port_dump_vital_status(cs_uint16 port_id)
/* INPUTS     : o Port Id                                       */
/* OUTPUTS    : ----                                            */
/* RETURNS    : CS_OK or CS_ERROR                               */
/* DESCRIPTION:                                                 */
/* Retrieves and prints the current status at a glance          */
/* This is mainly for debug purpose as most of status are       */
/* available via individual API's call.                         */
/*                                                              */
/* This API will dump vital status for the device as well.      */
/* $rtn_hdr_end                                                 */
/****************************************************************/
{
  arn5_port_runcfg_t    * pRunCfg = NULL ;
  cs_uint32             err_code ;
  cs_uint8              devId, portNum ;
  cs_status             status = CS_OK ;

  if ( !(ARN5_IS_PORT_VALID(port_id, &err_code)) ) {
    CS_HNDL_ERROR(port_id, err_code, NULL) ;
    return(CS_ERROR) ;
  }

  pRunCfg = (arn5_port_runcfg_t *) CS_MALLOC( sizeof(arn5_port_runcfg_t) ) ;

  if (pRunCfg == NULL) {
    return (CS_ERROR) ;
  }

  if ( arn5_port_get_running_cfg(port_id, pRunCfg) != CS_OK ) {
    status = CS_ERROR ;
    goto RTN_EXIT ;
  }

  devId = ARN5_PORT_ID_TO_DEV_ID(port_id) ;
  portNum = ARN5_PORT_ID_TO_PORT_NUM(port_id) ;

  arn5_dev_dump_vital_status(devId) ;

  CS_PRINT("\n") ;
  CS_PRINT("\t *** PORT-0x%x  Vital Status  ***\n", port_id) ;
  CS_PRINT("=================================================\n") ;

  if (pRunCfg->summ.line_rate == ARN5_PORT_RATE_GIGE) {
    CS_PRINT("ETH Link Status               = %s\n",
      (arn5_eth_get_link_status(port_id) ? "Link Up" : "Link Down")) ;
    if (pRunCfg->eth.auto_neg_cfg.enable) {
      CS_PRINT("ETH Auto_Negotiation Status   = %sCompleted\n",
        (arn5_eth_get_auto_negotiation_status(port_id) ? "" : "Not ")) ;
    }
  }
  else {
    CS_PRINT("Framer In Frame Status        = %s\n",
      (arn5_framer_get_sync_status(port_id) ?
         "In Frame" : "Out of Frame")) ;
    CS_PRINT("Framer Rx Data Path Status    = %sReady\n",
      (arn5_framer_get_rx_data_path_status(port_id) ?
         "" : "Not ")) ;
  }

  if (pRunCfg->pprbs.hostChkr || pRunCfg->pprbs.lineChkr) {
    /* print pprbs header only if we need to */
    CS_PRINT("-- PPRBS --\n") ;
  }
  if (pRunCfg->pprbs.hostChkr) {
    arn5_pprbs_dump_checker(port_id, ARN5_PPRBS_HOST_CHAN) ;
  }
  if (pRunCfg->pprbs.lineChkr) {
    arn5_pprbs_dump_checker(port_id, ARN5_PPRBS_LINE_CHAN) ;
  }

RTN_EXIT :
  if (pRunCfg) CS_FREE(pRunCfg) ;
  return(status) ;
}
Пример #25
0
/* CHIP       : Arsenal5                                        */
cs_uint16  arn5_port_open(cs_uint8 dev_id, arn5_port_cfg_t * pCfg,
                        cs_uint8 slice_num)
/* INPUTS     : o Port Id                                       */
/*              o Pointer to port configuration structure       */
/*              o Slice Number[0..7] to be used for the port    */
/* OUTPUTS    : ----                                            */
/* RETURNS    : Port Id (or port handle)                        */
/* DESCRIPTION:                                                 */
/* This API, on successful completion, will create a valid      */
/* port handle(aka port_id) and also provide the caller with    */
/* the driver recommended default configuration for the port.   */
/*                                                              */
/* The caller of this API is expected to allocate memory for    */
/* pCfg and also fill in the summary section in it.             */
/*                                                              */
/* The port_handle(or port_id) created by the driver should be  */
/* used in further invocations of the port-level API's.         */
/* $rtn_hdr_end                                                 */
/****************************************************************/
{
  cs_uint32     err_code ;
  cs_uint16     port_id = ARN5_INVALID_PORT_ID ;
  arn5_port_cb_t        * ppcb ;
  arn5_dev_cb_t         * pdcb ;
  cs_status     status = CS_OK ;
  cs_uint16     rateUnits, desiredRate ;

  if (pCfg == NULL) {
    CS_HNDL_ERROR(dev_id, EARN5_DEV_NULL_PTR, ": pCfg") ;
    return (CS_ERROR) ;
  }

  if ( !(ARN5_IS_DEVICE_VALID(dev_id, &err_code)) ) {
    CS_HNDL_ERROR(dev_id, err_code, NULL) ;
    return (CS_ERROR) ;
  }

  /* also check if the device has been initialized! */
  if (arn5_dev_get_state(dev_id) != ARN5_DEV_STATE_INITIALIZED) {
    CS_HNDL_ERROR(dev_id, EARN5_DEV_NOT_INITED, NULL) ;
    return (CS_ERROR) ;
  }

  pdcb = ARN5_DEV_ID_TO_DEVCB_PTR(dev_id) ;
  switch (pCfg->summ.line_rate) {
    case ARN5_PORT_RATE_OC12C :
      if ((g_ARN5_ver[slice_num] & 0x4) == 0) {
        CS_HNDL_ERROR(dev_id, EARN5_DEV_CAPACITY_EXCEEDED ,
          "\nThe slice %d can't be configured as OC12C.\n", slice_num) ;
        status = CS_ERROR ;
        goto RTN_EXIT ;
      }
      if (pdcb->oc12_num >= g_ARN5_ver[ARN5_MAX_NUM_PORTS + 1]) {
        CS_HNDL_ERROR(dev_id, EARN5_DEV_CAPACITY_EXCEEDED ,
          "\nToo many OC12C ports are opened.\n") ;
        status = CS_ERROR ;
        goto RTN_EXIT ;
      }
      rateUnits = 4 ;
      break ;

    case ARN5_PORT_RATE_OC3C :
      if ((g_ARN5_ver[slice_num] & 0x2) == 0) {
        CS_HNDL_ERROR(dev_id, EARN5_DEV_CAPACITY_EXCEEDED ,
          "\nThe slice %d can't be configured as OC3.\n", slice_num) ;
        status = CS_ERROR ;
        goto RTN_EXIT ;
      }
      if (pdcb->oc3_num >= g_ARN5_ver[ARN5_MAX_NUM_PORTS + 2]) {
        CS_HNDL_ERROR(dev_id, EARN5_DEV_CAPACITY_EXCEEDED ,
          "\nToo many OC3C ports are opened.\n") ;
        status = CS_ERROR ;
        goto RTN_EXIT ;
      }
      rateUnits = 1 ;
      break ;

    case ARN5_PORT_RATE_GIGE :
      if ((g_ARN5_ver[slice_num] & 0x1) == 0) {
        CS_HNDL_ERROR(dev_id, EARN5_DEV_CAPACITY_EXCEEDED ,
          "\nThe slice %d can't be configured as GigE.\n", slice_num) ;
        status = CS_ERROR ;
        goto RTN_EXIT ;
      }
      if (pdcb->gige_num >= g_ARN5_ver[ARN5_MAX_NUM_PORTS + 3]) {
        CS_HNDL_ERROR(dev_id, EARN5_DEV_CAPACITY_EXCEEDED ,
          "\nToo many GigE ports are opened.\n") ;
        status = CS_ERROR ;
        goto RTN_EXIT ;
      }
      rateUnits = 7 ;
      break ;

    default :
      if ((g_ARN5_ver[slice_num] & 0x8) == 0) {
        CS_HNDL_ERROR(dev_id, EARN5_DEV_CAPACITY_EXCEEDED ,
          "\nThe slice %d can't be configured as OC48.\n", slice_num) ;
        status = CS_ERROR ;
        goto RTN_EXIT ;
      }
      if (pdcb->oc48_num >= g_ARN5_ver[ARN5_MAX_NUM_PORTS]) {
        CS_HNDL_ERROR(dev_id, EARN5_DEV_CAPACITY_EXCEEDED ,
          "\nToo many OC48C ports are opened.\n") ;
        status = CS_ERROR ;
        goto RTN_EXIT ;
      }
      rateUnits = 16 ;
      break ;
  }

  desiredRate = pdcb->total_rate_units + rateUnits ;
  if (desiredRate >
        g_ARN5_ver[ARN5_MAX_NUM_PORTS + 4]) {
    CS_HNDL_ERROR(dev_id, EARN5_DEV_CAPACITY_EXCEEDED ,
      "\n** Warning!! Total rate exceeds the maximum.\n") ;
    status = CS_OK ;
  }

  switch (arn5_spi_dev_get_if_mode(dev_id)) {
    case ARN5_SPI3_MODE :
      if (desiredRate > ARN5_SPI3_MAX_RATE_UNIT) {
        CS_HNDL_ERROR(dev_id, EARN5_DEV_CAPACITY_EXCEEDED ,
          "\n** Warning!! Total rate exceeds the maximum.\n") ;
        status = CS_OK ;
      }
      break ;

    case ARN5_SPI42_QUARTER_RATE_MODE :
      if (desiredRate > ARN5_SPI42Q_MAX_RATE_UNIT) {
        CS_HNDL_ERROR(dev_id, EARN5_DEV_CAPACITY_EXCEEDED ,
          "\n** Warning!! Total rate exceeds the maximum.\n") ;
        status = CS_OK ;
      }
      break ;

    default :
      /* no extra check */
      break ;
  }

  CS_MEMSET( (void *) ((cs_uint32)pCfg + sizeof(arn5_port_summ_t)),
             0,
             sizeof(arn5_port_cfg_t) - sizeof(arn5_port_summ_t) ) ;

  if ( arn5_dev_create_port_id(dev_id, &pCfg->summ, &port_id,
        &ppcb, slice_num)
       != CS_OK ) {
    status = CS_ERROR ;
    goto RTN_EXIT ;
  }

  /* clear the Port CB */
  CS_MEMSET( (void *) ppcb, 0, sizeof(arn5_port_cb_t) ) ;

  /* copy some essential info into the port cb */
  ppcb->port_id = port_id ;
  ppcb->state   = ARN5_PORT_STATE_OPENED ;
  ppcb->summ    = pCfg->summ ;

  if ( arn5_port_verify_summ(dev_id, port_id, &pCfg->summ)
       != CS_OK ) {
    status = CS_ERROR ;
    goto RTN_EXIT ;
  }

  /* Provide the user with the driver recommended default config */
  if ( arn5_port_get_default_cfg(port_id, pCfg) != CS_OK ) {
    CS_PRINT("dev-%d %s() ERROR: Cannot get default cfg!\n",
             dev_id, __FUNCTION__) ;
    status = CS_ERROR ;
    goto RTN_EXIT ;
  }

  arn5_port_commit_default_cfg(port_id, pCfg) ;
  //CS_PRINT("\tARN5 Port(port-id = port handle = 0x%04x) successfully opened\n",
  //         port_id) ;

  switch (pCfg->summ.line_rate) {
    case ARN5_PORT_RATE_OC12C :
      (pdcb->oc12_num)++ ;
      break ;

    case ARN5_PORT_RATE_OC3C :
      (pdcb->oc3_num)++ ;
      break ;

    case ARN5_PORT_RATE_GIGE :
      (pdcb->gige_num)++ ;
      break ;

    default :
      (pdcb->oc48_num)++ ;
      break ;
  }
  pdcb->total_rate_units += rateUnits ;

  RTN_EXIT :
    if ( (status != CS_OK) && (port_id != ARN5_INVALID_PORT_ID) ) {
      arn5_dev_delete_port_id(port_id) ;
      port_id = ARN5_INVALID_PORT_ID ;
    }

  return (port_id) ;
}
Пример #26
0
uint32_t objToBin(const uint8_t* _objData
                  , bx::WriterSeekerI* _writer
                  , uint32_t _packUv
                  , uint32_t _packNormal
                  , bool _ccw
                  , bool _flipV
                  , bool _hasTangent
                  , float _scale
                 )
{
    int64_t parseElapsed = -bx::getHPCounter();
    int64_t triReorderElapsed = 0;

    const int64_t begin = _writer->seek();

    Vector3Array positions;
    Vector3Array normals;
    Vector3Array texcoords;
    Index3Map indexMap;
    TriangleArray triangles;
    BgfxGroupArray groups;

    uint32_t num = 0;

    MeshGroup group;
    group.m_startTriangle = 0;
    group.m_numTriangles = 0;
    group.m_name = "";
    group.m_material = "";

    char commandLine[2048];
    uint32_t len = sizeof(commandLine);
    int argc;
    char* argv[64];
    const char* next = (const char*)_objData;
    do
    {
        next = bx::tokenizeCommandLine(next, commandLine, len, argc, argv, BX_COUNTOF(argv), '\n');
        if (0 < argc)
        {
            if (0 == strcmp(argv[0], "#") )
            {
                if (2 < argc
                        &&  0 == strcmp(argv[2], "polygons") )
                {
                }
            }
            else if (0 == strcmp(argv[0], "f") )
            {
                Triangle triangle;
                memset(&triangle, 0, sizeof(Triangle) );

                const int numNormals   = (int)normals.size();
                const int numTexcoords = (int)texcoords.size();
                const int numPositions = (int)positions.size();
                for (uint32_t edge = 0, numEdges = argc-1; edge < numEdges; ++edge)
                {
                    Index3 index;
                    index.m_texcoord = 0;
                    index.m_normal = 0;
                    index.m_vertexIndex = -1;

                    char* vertex = argv[edge+1];
                    char* texcoord = strchr(vertex, '/');
                    if (NULL != texcoord)
                    {
                        *texcoord++ = '\0';

                        char* normal = strchr(texcoord, '/');
                        if (NULL != normal)
                        {
                            *normal++ = '\0';
                            const int nn = atoi(normal);
                            index.m_normal = (nn < 0) ? nn+numNormals : nn-1;
                        }

                        const int tex = atoi(texcoord);
                        index.m_texcoord = (tex < 0) ? tex+numTexcoords : tex-1;
                    }

                    const int pos = atoi(vertex);
                    index.m_position = (pos < 0) ? pos+numPositions : pos-1;

                    uint64_t hash0 = index.m_position;
                    uint64_t hash1 = uint64_t(index.m_texcoord)<<20;
                    uint64_t hash2 = uint64_t(index.m_normal)<<40;
                    uint64_t hash = hash0^hash1^hash2;

                    CS_STL::pair<Index3Map::iterator, bool> result = indexMap.insert(CS_STL::make_pair(hash, index) );
                    if (!result.second)
                    {
                        Index3& oldIndex = result.first->second;
                        BX_UNUSED(oldIndex);
                        BX_CHECK(oldIndex.m_position == index.m_position
                                 && oldIndex.m_texcoord == index.m_texcoord
                                 && oldIndex.m_normal == index.m_normal
                                 , "Hash collision!"
                                );
                    }

                    switch (edge)
                    {
                    case 0:
                    case 1:
                    case 2:
                        triangle.m_index[edge] = hash;
                        if (2 == edge)
                        {
                            if (_ccw)
                            {
                                std::swap(triangle.m_index[1], triangle.m_index[2]);
                            }
                            triangles.push_back(triangle);
                        }
                        break;

                    default:
                        if (_ccw)
                        {
                            triangle.m_index[2] = triangle.m_index[1];
                            triangle.m_index[1] = hash;
                        }
                        else
                        {
                            triangle.m_index[1] = triangle.m_index[2];
                            triangle.m_index[2] = hash;
                        }
                        triangles.push_back(triangle);
                        break;
                    }
                }
            }
            else if (0 == strcmp(argv[0], "g") )
            {
                if (1 >= argc)
                {
                    CS_PRINT("Error parsing *.obj file.\n");
                    return 0;
                }
                group.m_name = argv[1];
            }
            else if (*argv[0] == 'v')
            {
                group.m_numTriangles = (uint32_t)(triangles.size() ) - group.m_startTriangle;
                if (0 < group.m_numTriangles)
                {
                    groups.push_back(group);
                    group.m_startTriangle = (uint32_t)(triangles.size() );
                    group.m_numTriangles = 0;
                }

                if (0 == strcmp(argv[0], "vn") )
                {
                    Vector3 normal;
                    normal.x = (float)atof(argv[1]);
                    normal.y = (float)atof(argv[2]);
                    normal.z = (float)atof(argv[3]);

                    normals.push_back(normal);
                }
                else if (0 == strcmp(argv[0], "vp") )
                {
                    static bool once = true;
                    if (once)
                    {
                        once = false;
                        CS_PRINT("warning: 'parameter space vertices' are unsupported.\n");
                    }
                }
                else if (0 == strcmp(argv[0], "vt") )
                {
                    Vector3 texcoord;
                    texcoord.x = (float)atof(argv[1]);
                    texcoord.y = 0.0f;
                    texcoord.z = 0.0f;
                    switch (argc)
                    {
                    case 4:
                        texcoord.z = (float)atof(argv[3]);
                    // fallthrough
                    case 3:
                        texcoord.y = (float)atof(argv[2]);
                        break;

                    default:
                        break;
                    }

                    texcoords.push_back(texcoord);
                }
                else
                {
                    float px = (float)atof(argv[1]);
                    float py = (float)atof(argv[2]);
                    float pz = (float)atof(argv[3]);
                    float pw = 1.0f;
                    if (argc > 4)
                    {
                        pw = (float)atof(argv[4]);
                    }

                    float invW = _scale/pw;
                    px *= invW;
                    py *= invW;
                    pz *= invW;

                    Vector3 pos;
                    pos.x = px;
                    pos.y = py;
                    pos.z = pz;

                    positions.push_back(pos);
                }
            }
            else if (0 == strcmp(argv[0], "usemtl") )
            {
                std::string material(argv[1]);

                if (material != group.m_material)
                {
                    group.m_numTriangles = (uint32_t)(triangles.size() ) - group.m_startTriangle;
                    if (0 < group.m_numTriangles)
                    {
                        groups.push_back(group);
                        group.m_startTriangle = (uint32_t)(triangles.size() );
                        group.m_numTriangles = 0;
                    }
                }

                group.m_material = material;
            }
// unsupported tags
//              else if (0 == strcmp(argv[0], "mtllib") )
//              {
//              }
//              else if (0 == strcmp(argv[0], "o") )
//              {
//              }
//              else if (0 == strcmp(argv[0], "s") )
//              {
//              }
        }

        ++num;
    }
    while ('\0' != *next);

    group.m_numTriangles = (uint32_t)(triangles.size() ) - group.m_startTriangle;
    if (0 < group.m_numTriangles)
    {
        groups.push_back(group);
        group.m_startTriangle = (uint32_t)(triangles.size() );
        group.m_numTriangles = 0;
    }

    int64_t now = bx::getHPCounter();
    parseElapsed += now;
    int64_t convertElapsed = -now;

    std::sort(groups.begin(), groups.end(), GroupSortByMaterial() );

    bool hasColor = false;
    bool hasNormal;
    bool hasTexcoord;
    {
        Index3Map::const_iterator it = indexMap.begin();
        hasNormal   = 0 != it->second.m_normal;
        hasTexcoord = 0 != it->second.m_texcoord;

        if (!hasTexcoord
                &&  texcoords.size() == positions.size() )
        {
            hasTexcoord = true;

            for (Index3Map::iterator it = indexMap.begin(), itEnd = indexMap.end(); it != itEnd; ++it)
            {
                it->second.m_texcoord = it->second.m_position;
            }
        }

        if (!hasNormal
                &&  normals.size() == positions.size() )
        {
            hasNormal = true;

            for (Index3Map::iterator it = indexMap.begin(), itEnd = indexMap.end(); it != itEnd; ++it)
            {
                it->second.m_normal = it->second.m_position;
            }
        }
    }

    bgfx::VertexDecl decl;
    decl.begin();
    decl.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float);

    if (hasColor)
    {
        decl.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true);
    }

    if (hasTexcoord)
    {
        switch (_packUv)
        {
        default:
        case 0:
            decl.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float);
            break;

        case 1:
            decl.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Half);
            break;
        }
    }

    if (hasNormal)
    {
        _hasTangent &= hasTexcoord;

        switch (_packNormal)
        {
        default:
        case 0:
            decl.add(bgfx::Attrib::Normal, 3, bgfx::AttribType::Float);
            if (_hasTangent)
            {
                decl.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Float);
            }
            break;

        case 1:
            decl.add(bgfx::Attrib::Normal, 4, bgfx::AttribType::Uint8, true, true);
            if (_hasTangent)
            {
                decl.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Uint8, true, true);
            }
            break;
        }
    }
    decl.end();

    uint32_t stride = decl.getStride();
    uint8_t* vertexData = new uint8_t[triangles.size() * 3 * stride];
    uint16_t* indexData = new uint16_t[triangles.size() * 3];
    int32_t numVertices = 0;
    int32_t numIndices = 0;
    int32_t numPrimitives = 0;

    uint8_t* vertices = vertexData;
    uint16_t* indices = indexData;

    std::string material = groups.begin()->m_material;

    BgfxPrimitiveArray primitives;

    Primitive prim;
    prim.m_startVertex = 0;
    prim.m_startIndex  = 0;

    uint32_t positionOffset = decl.getOffset(bgfx::Attrib::Position);
    uint32_t color0Offset   = decl.getOffset(bgfx::Attrib::Color0);

    uint32_t ii = 0;
    for (BgfxGroupArray::const_iterator groupIt = groups.begin(); groupIt != groups.end(); ++groupIt, ++ii)
    {
        for (uint32_t tri = groupIt->m_startTriangle, end = tri + groupIt->m_numTriangles; tri < end; ++tri)
        {
            if (material != groupIt->m_material
                    ||  65533 < numVertices)
            {
                prim.m_numVertices = numVertices - prim.m_startVertex;
                prim.m_numIndices = numIndices - prim.m_startIndex;
                if (0 < prim.m_numVertices)
                {
                    primitives.push_back(prim);
                }

                triReorderElapsed -= bx::getHPCounter();
                for (BgfxPrimitiveArray::const_iterator primIt = primitives.begin(); primIt != primitives.end(); ++primIt)
                {
                    const Primitive& prim = *primIt;
                    triangleReorder(indexData + prim.m_startIndex, prim.m_numIndices, numVertices, 32);
                }
                triReorderElapsed += bx::getHPCounter();

                if (_hasTangent)
                {
                    calculateTangents(vertexData, numVertices, decl, indexData, numIndices);
                }

                write(_writer
                      , vertexData
                      , numVertices
                      , decl
                      , indexData
                      , numIndices
                      , material.c_str()
                      , primitives.data()
                      , (uint32_t)primitives.size()
                     );
                primitives.clear();

                for (Index3Map::iterator indexIt = indexMap.begin(); indexIt != indexMap.end(); ++indexIt)
                {
                    indexIt->second.m_vertexIndex = -1;
                }

                vertices = vertexData;
                indices = indexData;
                numVertices = 0;
                numIndices = 0;
                prim.m_startVertex = 0;
                prim.m_startIndex = 0;
                ++numPrimitives;

                material = groupIt->m_material;
            }

            Triangle& triangle = triangles[tri];
            for (uint32_t edge = 0; edge < 3; ++edge)
            {
                uint64_t hash = triangle.m_index[edge];
                Index3& index = indexMap[hash];
                if (index.m_vertexIndex == -1)
                {
                    index.m_vertexIndex = numVertices++;

                    float* position = (float*)(vertices + positionOffset);
                    memcpy(position, &positions[index.m_position], 3*sizeof(float) );

                    if (hasColor)
                    {
                        uint32_t* color0 = (uint32_t*)(vertices + color0Offset);
                        *color0 = rgbaToAbgr(numVertices%255, numIndices%255, 0, 0xff);
                    }

                    if (hasTexcoord)
                    {
                        float uv[2];
                        memcpy(uv, &texcoords[index.m_texcoord], 2*sizeof(float) );

                        if (_flipV)
                        {
                            uv[1] = -uv[1];
                        }

                        bgfx::vertexPack(uv, true, bgfx::Attrib::TexCoord0, decl, vertices);
                    }

                    if (hasNormal)
                    {
                        float normal[4];
                        bx::vec3Norm(normal, (float*)&normals[index.m_normal]);
                        bgfx::vertexPack(normal, true, bgfx::Attrib::Normal, decl, vertices);
                    }

                    vertices += stride;
                }

                *indices++ = (uint16_t)index.m_vertexIndex;
                ++numIndices;
            }
        }

        if (0 < numVertices)
        {
            prim.m_numVertices = numVertices - prim.m_startVertex;
            prim.m_numIndices = numIndices - prim.m_startIndex;
            bx::strlcpy(prim.m_name, groupIt->m_name.c_str(), 128);
            primitives.push_back(prim);
            prim.m_startVertex = numVertices;
            prim.m_startIndex = numIndices;
        }

        //CS_PRINT("%3d: s %5d, n %5d, %s\n"
        //    , ii
        //    , groupIt->m_startTriangle
        //    , groupIt->m_numTriangles
        //    , groupIt->m_material.c_str()
        //    );
    }

    if (0 < primitives.size() )
    {
        triReorderElapsed -= bx::getHPCounter();
        for (BgfxPrimitiveArray::const_iterator primIt = primitives.begin(); primIt != primitives.end(); ++primIt)
        {
            const Primitive& prim = *primIt;
            triangleReorder(indexData + prim.m_startIndex, prim.m_numIndices, numVertices, 32);
        }
        triReorderElapsed += bx::getHPCounter();

        if (_hasTangent)
        {
            calculateTangents(vertexData, numVertices, decl, indexData, numIndices);
        }

        write(_writer, vertexData, numVertices, decl, indexData, numIndices, material.c_str(), primitives.data(), (uint32_t)primitives.size());
    }

    delete [] indexData;
    delete [] vertexData;

    now = bx::getHPCounter();
    convertElapsed += now;

    const int64_t end = _writer->seek();
    const uint32_t dataSize = uint32_t(end-begin);
    CS_PRINT("size: %u\n", dataSize);

    CS_PRINT("parse %f [s]\ntri reorder %f [s]\nconvert %f [s]\n# %d, g %d, p %d, v %d, i %d\n"
             , double(parseElapsed)/bx::getHPFrequency()
             , double(triReorderElapsed)/bx::getHPFrequency()
             , double(convertElapsed)/bx::getHPFrequency()
             , num
             , uint32_t(groups.size() )
             , numPrimitives
             , numVertices
             , numIndices
            );

    return dataSize;
}