Exemple #1
0
/**
 * Opens a logical GLink based on the specified config params
 *
 * @param[in]    cfg_ptr  Pointer to the configuration structure for the
 *                        GLink. See glink.h
 * @param[out]   handle   GLink handle associated with the logical channel
 *
 * @return       Standard GLink error codes
 *
 * @sideeffects  Allocates channel resources and informs remote host about
 *               channel open.
 */
glink_err_type glink_open
(
  glink_open_config_type *cfg_ptr,
  glink_handle_type      *handle
)
{
  glink_transport_if_type *if_ptr, *req_if_ptr;
  glink_channel_ctx_type  *ch_ctx;
  unsigned int            remote_host;

  /* Param validation */
  if(cfg_ptr == NULL)
  {
    GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, NULL, "", "",
        GLINK_STATUS_INVALID_PARAM);
    return GLINK_STATUS_INVALID_PARAM;
  }

  if(cfg_ptr->remote_ss == NULL             ||
     cfg_ptr->name == NULL                  ||
     cfg_ptr->notify_state == NULL)
  {
    GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, NULL, "", "",
        GLINK_STATUS_INVALID_PARAM);
    return GLINK_STATUS_INVALID_PARAM;
  }

  /* Evaluate the equivalent edge name->enum for future use */
  remote_host = glinki_find_remote_host(cfg_ptr->remote_ss);

  if(remote_host == GLINK_NUM_HOSTS ) {
    /* Unknown transport name trying to register with GLink */
    GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, cfg_ptr->name, "",
        cfg_ptr->remote_ss, GLINK_STATUS_INVALID_PARAM);

    return GLINK_STATUS_INVALID_PARAM;
  }

  /* Allocate and initialize channel info structure */
  ch_ctx = glink_os_calloc(sizeof(glink_channel_ctx_type));
  if(ch_ctx == NULL) {
    GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, cfg_ptr->name, "",
        "", GLINK_STATUS_OUT_OF_RESOURCES);
    return GLINK_STATUS_OUT_OF_RESOURCES;
  }

  /* Fill in the channel info structure */
  glink_os_string_copy(ch_ctx->name, cfg_ptr->name, sizeof(ch_ctx->name));
  ch_ctx->priv = cfg_ptr->priv;
  ch_ctx->notify_rx = cfg_ptr->notify_rx;
  ch_ctx->notify_rxv = cfg_ptr->notify_rxv;
  ch_ctx->notify_tx_done = cfg_ptr->notify_tx_done;
  ch_ctx->notify_state = cfg_ptr->notify_state;
  ch_ctx->notify_rx_intent_req = cfg_ptr->notify_rx_intent_req;
  ch_ctx->notify_rx_intent = cfg_ptr->notify_rx_intent;
  ch_ctx->notify_rx_sigs = cfg_ptr->notify_rx_sigs;
  ch_ctx->ch_open_options = cfg_ptr->options;
  ch_ctx->notify_rx_abort = cfg_ptr->notify_rx_abort;
  ch_ctx->notify_tx_abort = cfg_ptr->notify_tx_abort;

  if (ch_ctx->notify_rx_sigs == NULL) {
    /* set default callback */
    ch_ctx->notify_rx_sigs = glink_default_notify_rx_sigs;
  }

  glink_os_cs_acquire(glink_transport_q_cs);

  /* Check to see if requested transport is available */
  for (if_ptr = smem_list_first(&glink_registered_transports[remote_host]);
       if_ptr != NULL;
       if_ptr = smem_list_next(if_ptr))
  {
    glink_core_xport_ctx_type *xport_ctx = if_ptr->glink_core_priv;
    glink_channel_ctx_type    *allocated_ch_ctx;

    if (xport_ctx->status == GLINK_XPORT_LINK_UP &&
        (cfg_ptr->transport == NULL ||
         0 == strcmp(cfg_ptr->transport, xport_ctx->xport)) &&
        xport_ctx->verify_open_cfg(ch_ctx))
    {
      glink_err_type status;

      if(cfg_ptr->transport == NULL)
      {
        /* get best available transport */
        if_ptr = req_if_ptr = glink_get_best_xport(remote_host);
      }
      else
      {
        if(cfg_ptr->options & GLINK_OPT_INITIAL_XPORT)
        {
          /* xport suggested by client is optional.
           * get best available xport */
          req_if_ptr = glink_get_best_xport(remote_host);
        }
        else
        {
          req_if_ptr = if_ptr;
        }
      }
      /* Xport match found */
      status = glinki_add_ch_to_xport( if_ptr,
                                       req_if_ptr,
                                       ch_ctx,
                                       &allocated_ch_ctx,
                                       TRUE,
                                       TRUE,
                                       if_ptr->glink_priority );

      if (status == GLINK_STATUS_SUCCESS) {
        /* Set the handle and return */
        *handle = allocated_ch_ctx;
      }
      else {
        *handle = NULL;
      }

      glink_os_cs_release(glink_transport_q_cs);

      GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, ch_ctx->name, xport_ctx->xport,
        xport_ctx->remote_ss, status);
      return status;
    }
  } /* end for() */

  glink_os_cs_release(glink_transport_q_cs);

  /* Code gets here if we are not able to find reqeusted transport */
  GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, cfg_ptr->name, cfg_ptr->transport,
      cfg_ptr->remote_ss, GLINK_STATUS_NO_TRANSPORT);
  glink_os_free(ch_ctx);
  return GLINK_STATUS_NO_TRANSPORT;
}
Exemple #2
0
/**
 * Queue one or more Rx intent for the logical GPIC Link channel.
 *
 * @param[in]    handle   GLink handle associated with the logical channel
 *
 * @param[in]   *pkt_priv Per packet private data
 *
 * @param[in]   size      Size of buffer
 *
 * @return       Standard GLink error codes
 *
 * @sideeffects  GLink XAL allocates rx buffers for receiving packets
 */
glink_err_type glink_queue_rx_intent
(
  glink_handle_type handle,
  const void        *pkt_priv,
  size_t            size
)
{
  glink_err_type         status;
  glink_rx_intent_type   *lc_intent;
  glink_core_xport_ctx_type *xport_ctx = handle->if_ptr->glink_core_priv;
  size_t tmp;

  /* Input validation */
  if(handle == NULL || size == 0) {
    GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, NULL, "",
        "", GLINK_STATUS_INVALID_PARAM);
    return GLINK_STATUS_INVALID_PARAM;
  }

  /* short circuit for intentless mode */
  if(xport_ctx->xport_capabilities & GLINK_CAPABILITY_INTENTLESS) {
    return GLINK_STATUS_FAILURE;
  }

  /* Make sure channel is in OPEN state */
  if(handle->state != GLINK_CH_STATE_OPEN)
  {
    GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name, xport_ctx->xport,
      xport_ctx->remote_ss, GLINK_STATUS_FAILURE);
    return GLINK_STATUS_FAILURE;
  }

  /* Allocate an intent structure */
  lc_intent = glink_os_calloc(sizeof(glink_rx_intent_type));
  if(lc_intent == NULL) {
    GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name, xport_ctx->xport,
        xport_ctx->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);
    return GLINK_STATUS_OUT_OF_RESOURCES;
  }

  glink_os_cs_acquire(&handle->if_ptr->glink_core_priv->liid_cs);

  /* Call transport API to allocate rx intent buffer */
  status = handle->if_ptr->allocate_rx_intent(handle->if_ptr, size, lc_intent);
  if(status != GLINK_STATUS_SUCCESS) {
    glink_os_free(lc_intent);
    glink_os_cs_release(&handle->if_ptr->glink_core_priv->liid_cs);
    GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name, xport_ctx->xport,
        xport_ctx->remote_ss, status);
    return status;
  }

  if (handle->notify_rxv == NULL &&
     (lc_intent->vprovider(lc_intent->iovec, 0, &tmp) == NULL || tmp < size)) {
    /* Allocate bounce buffer for non-vectored Rx */
    lc_intent->data = glink_os_malloc(size);

    if(lc_intent->data == NULL) {
      handle->if_ptr->deallocate_rx_intent(handle->if_ptr, lc_intent);
      glink_os_free(lc_intent);
      glink_os_cs_release(&handle->if_ptr->glink_core_priv->liid_cs);
      GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name,
        xport_ctx->xport, xport_ctx->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);
      return GLINK_STATUS_OUT_OF_RESOURCES;
    }
  }

  /* push the intent on local queue. Do this before calling tx cmd
     as transport may try to read data into the newly queued rx_buffer */
  lc_intent->iid = handle->if_ptr->glink_core_priv->liid;
  lc_intent->size = size;
  lc_intent->pkt_priv = pkt_priv;
  glink_os_cs_acquire(&handle->pintents->intent_q_cs);
  smem_list_append(&handle->pintents->local_intent_q, lc_intent);
  glink_os_cs_release(&handle->pintents->intent_q_cs);

  /* Call transport API to queue rx intent */
  /* Increment the local intent ID counter associated with this channel */
  handle->if_ptr->glink_core_priv->liid++;

  status = handle->if_ptr->tx_cmd_local_rx_intent(handle->if_ptr,
              handle->lcid, size, lc_intent->iid);
  if(status != GLINK_STATUS_SUCCESS) {
    /* Failure */
    glink_os_cs_acquire(&handle->pintents->intent_q_cs);
    smem_list_delete(&handle->pintents->local_intent_q, lc_intent);
    glink_os_cs_release(&handle->pintents->intent_q_cs);

    handle->if_ptr->deallocate_rx_intent(handle->if_ptr, lc_intent);
    glink_os_free(lc_intent->data);
    glink_os_free(lc_intent);
  }
  glink_os_cs_release(&handle->if_ptr->glink_core_priv->liid_cs);

  GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name, xport_ctx->xport,
      xport_ctx->remote_ss, status);
  return status;
}
Exemple #3
0
/*===========================================================================
FUNCTION      glink_core_register_transport

DESCRIPTION   Transport calls this API to register its interface with GLINK
              Core

ARGUMENTS   *if_ptr   Pointer to interface instance; must be unique
                      for each edge

            *cfg      Pointer to transport configuration structure.

RETURN VALUE  Standard GLINK error codes.

SIDE EFFECTS  None
===========================================================================*/
glink_err_type glink_core_register_transport
(
  glink_transport_if_type       *if_ptr,
  glink_core_transport_cfg_type *cfg
)
{
  unsigned int remote_host = 0;
  glink_core_xport_ctx_type *xport_ctx;
  /* Param validation */
  if(if_ptr == NULL || cfg == NULL)
  {
    GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, "", "",
        GLINK_STATUS_INVALID_PARAM);
    return GLINK_STATUS_INVALID_PARAM;
  }

  if(cfg->name == NULL       ||
     cfg->remote_ss == NULL  ||
     cfg->version == NULL    ||
     cfg->version_count == 0 ||
     cfg->max_cid == 0)
  {
    GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, "", "",
        GLINK_STATUS_INVALID_PARAM);
    return GLINK_STATUS_INVALID_PARAM;
  }


  if(if_ptr->tx_cmd_version == NULL             ||
     if_ptr->tx_cmd_version_ack == NULL         ||
     if_ptr->set_version == NULL                ||
     if_ptr->tx_cmd_ch_open == NULL             ||
     if_ptr->tx_cmd_ch_close == NULL            ||
     if_ptr->tx_cmd_ch_remote_open_ack == NULL  ||
     if_ptr->tx_cmd_ch_remote_close_ack == NULL ||
     if_ptr->tx_cmd_set_sigs  == NULL           ||
     if_ptr->ssr  == NULL)
  {
    GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, cfg->name,
        cfg->remote_ss, GLINK_STATUS_INVALID_PARAM);
    return GLINK_STATUS_INVALID_PARAM;;
  }


  /* Allocate/fill out the GLink Core interface structure */
  {
    glink_core_if_type *core_if = glink_os_calloc(sizeof(glink_core_if_type));
    if(core_if == NULL) {
      GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, cfg->name,
          cfg->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);
      return GLINK_STATUS_OUT_OF_RESOURCES;
    }
    core_if->link_up = glink_link_up;
    core_if->rx_cmd_version = glink_rx_cmd_version;
    core_if->rx_cmd_version_ack = glink_rx_cmd_version_ack;
    core_if->rx_cmd_ch_remote_open = glink_rx_cmd_ch_remote_open;
    core_if->rx_cmd_ch_open_ack = glink_rx_cmd_ch_open_ack;
    core_if->rx_cmd_ch_close_ack = glink_rx_cmd_ch_close_ack;
    core_if->rx_cmd_ch_remote_close = glink_rx_cmd_ch_remote_close;
    core_if->ch_state_local_trans = glink_ch_state_local_trans;
    core_if->rx_put_pkt_ctx = glink_rx_put_pkt_ctx;
    core_if->rx_cmd_remote_sigs = glink_rx_cmd_remote_sigs;
    core_if->tx_resume = glink_tx_resume;
    core_if->set_core_version = glink_set_core_version;

    /* Set the glink_core_if_ptr to point to the allocated structure */
    if_ptr->glink_core_if_ptr = core_if;
  }

  /* Allocate/fill out the GLink private context data */
  {
     xport_ctx = glink_os_calloc(sizeof(glink_core_xport_ctx_type));
    if(xport_ctx == NULL) {
      /* Free previously allocated memory */
      glink_os_free(if_ptr->glink_core_if_ptr);

      GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, cfg->name,
          cfg->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);

      return GLINK_STATUS_OUT_OF_RESOURCES;
    }

    glink_os_string_copy(xport_ctx->xport, cfg->name,
        sizeof(xport_ctx->xport));
    glink_os_string_copy(xport_ctx->remote_ss, cfg->remote_ss,
        sizeof(xport_ctx->xport));
    xport_ctx->free_lcid = 1; /* lcid 0 is reserved for invalid channel */
    xport_ctx->version_array = cfg->version;
    xport_ctx->version_indx = cfg->version_count - 1;

    glink_os_cs_init(&xport_ctx->channel_q_cs);
    glink_os_cs_init(&xport_ctx->liid_cs);

    glink_os_cs_acquire(&xport_ctx->channel_q_cs);
    smem_list_init(&xport_ctx->open_list);
    glink_os_cs_release(&xport_ctx->channel_q_cs);

    /* Set the glink_core_if_ptr to point to the allocated structure */
    if_ptr->glink_core_priv = xport_ctx;
    xport_ctx->status = GLINK_XPORT_REGISTERED;
  }

  /* Push the transport interface into appropriate queue */
  remote_host = glinki_find_remote_host(cfg->remote_ss);

  if(remote_host == GLINK_NUM_HOSTS ) {
    /* Unknown transport name trying to register with GLink */
    GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, xport_ctx->xport,
           xport_ctx->remote_ss, GLINK_STATUS_INVALID_PARAM);

    return GLINK_STATUS_INVALID_PARAM;
  }
  glink_os_cs_acquire(glink_transport_q_cs);
  smem_list_append(&glink_registered_transports[remote_host], if_ptr);
  glink_os_cs_release(glink_transport_q_cs);

  GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, xport_ctx->xport,
      xport_ctx->remote_ss, GLINK_STATUS_SUCCESS);

  return GLINK_STATUS_SUCCESS;
}
Exemple #4
0
/*=========================================================================*/
glink_err_type xport_rpm_init(void *arg)
{
  uint32 ind;
  glink_core_transport_cfg_type xport_rpm_cfg = { 0 };
  uint32 *msg_ram_toc = (uint32*)xport_rpm_msg_ram_toc;
  xport_rpm_toc_entry_type *entry;
  uint32 msg_ram_toc_num;
  char* msg_ram_toc_entry_start = (char*)&msg_ram_toc[XPORT_RPM_TOC_ENTRIES_IDX];
  dprintf(SPEW, "%s:%d: RPM Transport INIT\n", __func__, __LINE__);

  if (xport_rpm_config_num == 0)
  {
    return GLINK_STATUS_SUCCESS;
  }

  if (!xport_rpm_is_toc_present())
  {
    /* switch to err fatal once RPM side is integrated */
    dprintf(CRITICAL, "%s:%d: RPM Transport Failure: Invalid ToC cookie\n", __func__, __LINE__);
    return GLINK_STATUS_FAILURE;
  }

  msg_ram_toc_num = msg_ram_toc[XPORT_RPM_TOC_LENGTH_IDX];

  if (msg_ram_toc_num == 0)
  {
    dprintf(SPEW, "%s:%d RPM Transport Success\n", __func__, __LINE__);
    return GLINK_STATUS_SUCCESS;
  }

  xport_rpm_ctx = glink_os_calloc(sizeof(*xport_rpm_ctx)*xport_rpm_config_num);

  if (xport_rpm_ctx == NULL)
  {
    dprintf(INFO, "%s:%d RPM Transport Failed to allocate context\n", __func__, __LINE__);
    ASSERT(0);
  }

  /* Initialize supported version and features */
  xport_rpm_version.version = 1;
  xport_rpm_version.features = 0;
  xport_rpm_version.negotiate_features = &xport_rpm_negotiate_features;

  /* Initialize edges */
  dprintf(SPEW, "%s:%d: Initialize Edges\n", __func__, __LINE__);

  for (ind = 0; ind < xport_rpm_config_num; ind++)
  {
    xport_rpm_ctx[ind].pcfg = xport_rpm_get_config(ind);

    /* Find FIFOs in MSG RAM ToC */
    for (entry = (xport_rpm_toc_entry_type*)msg_ram_toc_entry_start;
         (char*)entry < msg_ram_toc_num*sizeof(*entry) + msg_ram_toc_entry_start &&
           (xport_rpm_ctx[ind].tx_desc == NULL || xport_rpm_ctx[ind].rx_desc == NULL);
         entry++)
    {
      if (entry->fifo_id == xport_rpm_ctx[ind].pcfg->tx_fifo_id)
      {
        xport_rpm_ctx[ind].tx_desc = (xport_rpm_ind_type*)&xport_rpm_msg_ram[entry->fifo_offset];
        xport_rpm_ctx[ind].tx_fifo = (char*)(xport_rpm_ctx[ind].tx_desc + 1);
        xport_rpm_ctx[ind].tx_fifo_size = entry->fifo_size;
      }
      else if (entry->fifo_id == xport_rpm_ctx[ind].pcfg->rx_fifo_id)
      {
        xport_rpm_ctx[ind].rx_desc =(xport_rpm_ind_type*)&xport_rpm_msg_ram[entry->fifo_offset];
        xport_rpm_ctx[ind].rx_fifo = (char*)(xport_rpm_ctx[ind].rx_desc + 1);
        xport_rpm_ctx[ind].rx_fifo_size = entry->fifo_size;
      }
    }

    if (xport_rpm_ctx[ind].tx_desc == NULL || xport_rpm_ctx[ind].rx_desc == NULL)
    {
      /* FIFOs not found in MSG RAM ToC. */
      xport_rpm_ctx[ind].pcfg = NULL;
      continue;
    }

    /* Rx read index should be cleared last */
    xport_rpm_ctx[ind].tx_desc->write_ind = 0;
    xport_rpm_ctx[ind].rx_desc->read_ind = 0;

    /* Initialize context */
    xport_rpm_ctx[ind].tx_link_lock = glink_os_cs_create();
    xport_rpm_ctx[ind].rx_link_lock = glink_os_cs_create();

    /* Initialize GLink transport interface */
    xport_rpm_ctx[ind].xport_if.tx_cmd_version = &xport_rpm_tx_cmd_version;
    xport_rpm_ctx[ind].xport_if.tx_cmd_version_ack = &xport_rpm_tx_cmd_version_ack;
    xport_rpm_ctx[ind].xport_if.set_version = &xport_rpm_set_version;
    xport_rpm_ctx[ind].xport_if.tx_cmd_ch_open = &xport_rpm_tx_cmd_ch_open;
    xport_rpm_ctx[ind].xport_if.tx_cmd_ch_close = &xport_rpm_tx_cmd_ch_close;
    xport_rpm_ctx[ind].xport_if.tx_cmd_ch_remote_open_ack = &xport_rpm_tx_cmd_ch_remote_open_ack;
    xport_rpm_ctx[ind].xport_if.tx_cmd_ch_remote_close_ack = &xport_rpm_tx_cmd_ch_remote_close_ack;
    xport_rpm_ctx[ind].xport_if.tx = &xport_rpm_tx;
    xport_rpm_ctx[ind].xport_if.tx_cmd_set_sigs = &xport_rpm_tx_cmd_set_sigs;
    xport_rpm_ctx[ind].xport_if.ssr = &xport_rpm_ssr;
    xport_rpm_ctx[ind].xport_if.mask_rx_irq = &xport_rpm_mask_interrupt;
    xport_rpm_ctx[ind].xport_if.poll = (poll_fn)&xport_rpm_isr;
    xport_rpm_ctx[ind].xport_if.wait_link_down = &xport_rpm_wait_link_down;

    /* TODO: glink transport priority */
    xport_rpm_ctx[ind].xport_if.glink_priority = GLINK_XPORT_RPM;

    /* Setup GLink configuration */
    xport_rpm_cfg.name = XPORT_RPM_NAME;
    xport_rpm_cfg.remote_ss = xport_rpm_ctx[ind].pcfg->remote_ss;
    xport_rpm_cfg.version = &xport_rpm_version;
    xport_rpm_cfg.version_count = 1;
    xport_rpm_cfg.max_cid = 0xFF;
    xport_rpm_cfg.max_iid = 0;

    if (glink_core_register_transport(&xport_rpm_ctx[ind].xport_if, &xport_rpm_cfg) !=
        GLINK_STATUS_SUCCESS)
    {
      /* Registration failed, set index to invalid. */
      xport_rpm_ctx[ind].pcfg = NULL;
      continue;
    }

    if ( !glink_os_register_isr( xport_rpm_ctx[ind].pcfg->irq_in,
                                (os_isr_cb_fn)xport_rpm_isr,
                                &xport_rpm_ctx[ind]) )
    {
       /* ISR registration failed, set index to invalid.
        * It will never fail */
      xport_rpm_ctx[ind].pcfg = NULL;
      continue;
    }

    /* send link up notification */
    xport_rpm_ctx[ind].xport_if.glink_core_if_ptr->link_up((glink_transport_if_type *)&xport_rpm_ctx[ind].xport_if);
  }

  return GLINK_STATUS_SUCCESS;
}