/** * 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; }
/** * 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; }
/*=========================================================================== 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; }
/*=========================================================================*/ 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; }