コード例 #1
0
ファイル: create_endpoint.c プロジェクト: qttest1/PDK_GoBian
/*************************************************************************
*
*   FUNCTION
*
*       mcapi_check_foreign_resume
*
*   DESCRIPTION
*
*       Checks if any pending requests from foreign nodes should be resumed.
*
*   INPUTS
*
*       type                    The type of request to check.
*       endpoint                The endpoint for which the request is
*                               suspended on some action.
*       status                  The status to set in the request structure.
*
*   OUTPUTS
*
*       None.
*
*************************************************************************/
void mcapi_check_foreign_resume(int type, mcapi_endpoint_t endpoint,
                                mcapi_status_t status)
{
    mcapi_request_t     *request, *next_ptr;
    MCAPI_GLOBAL_DATA   *node_data;

    /* Get a pointer to the global node list. */
    node_data = mcapi_get_node_data();

    /* Get a pointer to the first entry in the request queue. */
    request = node_data->mcapi_foreign_req_queue.flink;

    /* Check each request to see if the operation has been completed. */
    while (request)
    {
        /* Get a pointer to the next entry. */
        next_ptr = request->mcapi_next;

        switch (type)
        {
            /* An endpoint associated with a pending request has been
             * created.
             */
            case MCAPI_REQ_CREATED:

                /* If the request structure is waiting for an endpoint to be
                 * created.
                 */
                if ( (request->mcapi_type == MCAPI_REQ_CREATED) &&
                     (mcapi_encode_endpoint(request->mcapi_target_node_id,
                                            request->mcapi_target_port_id) == endpoint) )
                {
                    /* Remove this item from the list. */
                    mcapi_remove(&node_data->mcapi_foreign_req_queue, request);

                    /* Set the status to success. */
                    request->mcapi_status = MCAPI_SUCCESS;

                    /* Send the response. */
                    mcapi_tx_response(node_data, request);

                    /* Set this request structure back to available. */
                    mcapi_release_request_struct(request);
                }

                break;

            default:

                break;
        }

        /* Get the next request entry in the list. */
        request = next_ptr;
    }

}
コード例 #2
0
/*************************************************************************
*
*   FUNCTION
*
*       mcapi_create_endpoint
*
*   DESCRIPTION
*
*       API routine to create an endpoint on the local node.  If the port
*       ID field is set to MCAPI_PORT_ANY, an endpoint will be created using
*       the next available port in the system.
*
*   INPUTS
*
*       port_id                 The port ID of the endpoint, or MCAPI_PORT_ANY
*                               to create an endpoint with the next available
*                               port ID.
*       *mcapi_status           A pointer to memory that will be filled in
*                               with the status of the call.
*
*   OUTPUTS
*
*       The newly created endpoint.
*
*************************************************************************/
mcapi_endpoint_t mcapi_create_endpoint(mcapi_port_t port_id,
                                       mcapi_status_t *mcapi_status)
{
    mcapi_endpoint_t    endpoint = 0;
    MCAPI_GLOBAL_DATA   *node_data;
    MCAPI_NODE          *node_ptr = MCAPI_NULL;
    int                 node_idx;

    /* Ensure mcapi_status is valid. */
    if (mcapi_status)
    {
        /* Ensure the port ID is only 16-bits in length. */
        if ( (port_id == (unsigned int)MCAPI_PORT_ANY) || (port_id <= 65535) )
        {

//#if defined(__ALI_LINUX__)
            /* Get the lock. */
            mcapi_lock_node_data();
//#endif
            /* Get a pointer to the global node list. */
            node_data = mcapi_get_node_data();

            /* Get a pointer to the local node. */
            node_idx = mcapi_find_node(MCAPI_Node_ID, node_data);

            /* If the node has been initialized. */
            if (node_idx != -1)
            {
                /* Get a pointer to the node structure. */
                node_ptr = &node_data->mcapi_node_list[node_idx];

                /* Create the endpoint. */
                endpoint = create_endpoint(node_ptr, port_id, mcapi_status);
            }

            /* The node has not been initialized. */
            else
            {
                *mcapi_status = MCAPI_ERR_NODE_NOTINIT;
            }
//#if defined(__ALI_LINUX__)
            /* Release the lock. */
            mcapi_unlock_node_data();
//#endif
        }

        /* Ports can be only 16-bits in length. */
        else
        {
            *mcapi_status = MCAPI_ERR_PORT_INVALID;
        }
    }

    return (endpoint);

}
コード例 #3
0
/*************************************************************************
*
*   FUNCTION
*
*       mcapi_sclchan_available
*
*   DESCRIPTION
*
*       Non-blocking API routine to check for data on a connected scalar
*       channel.
*
*   INPUTS
*
*       receive_handle          The local handle identifer being checked
*                               for incoming data.
*       *mcapi_status           A pointer to memory that will be filled in
*                               with the status of the call.
*
*   OUTPUTS
*
*       The number of receive operations that are guaranteed to not block
*       waiting for incoming data.
*
*************************************************************************/
mcapi_uint_t mcapi_sclchan_available(mcapi_sclchan_recv_hndl_t receive_handle,
                                     mcapi_status_t *mcapi_status)
{
    MCAPI_GLOBAL_DATA   *node_data;
    mcapi_port_t        port_id;
    mcapi_node_t        node_id;
    mcapi_uint_t        msg_count = 0;
    MCAPI_ENDPOINT      *endp_ptr;

    /* Ensure the status pointer is valid. */
    if (mcapi_status)
    {
        /* Get the lock. */
        mcapi_lock_node_data();

        /* Get a pointer to the global node list. */
        node_data = mcapi_get_node_data();

        /* Get a pointer to the endpoint. */
        endp_ptr = mcapi_decode_local_endpoint(node_data, &node_id, &port_id,
                                               receive_handle, mcapi_status);

        if (endp_ptr)
        {
            /* Get the data. */
            mcapi_data_available(endp_ptr, MCAPI_CHAN_SCAL_TYPE, &msg_count,
                                 mcapi_status);
        }

        else if (*mcapi_status == MCAPI_ERR_ENDP_INVALID)
        {
            *mcapi_status = MCAPI_ERR_CHAN_INVALID;
        }

        /* Release the lock. */
        mcapi_unlock_node_data();
    }

    return (msg_count);

}
コード例 #4
0
/*************************************************************************
*
*   FUNCTION
*
*       mcapi_sclchan_send_close_i
*
*   DESCRIPTION
*
*       Non-blocking API routine to close the send side of a scalar
*       channel.  Close calls are required on both the send and receive
*       side to properly close the channel.  Pending scalars at the
*       receiver are not discarded until the receive side is closed.
*       Attempts to transmit more data from a closed send side will
*       elicit an error.
*
*   INPUTS
*
*       send_handle             The local send handle identifier for
*                               the send side of the connection being
*                               closed.
*       *request                A pointer to memory that will be filled in
*                               with data relevant to the operation, so the
*                               status of the operation can later be checked.
*       *mcapi_status           A pointer to memory that will be filled in
*                               with the status of the call.
*
*   OUTPUTS
*
*       None.
*
*************************************************************************/
void mcapi_sclchan_send_close_i(mcapi_sclchan_send_hndl_t send_handle,
                                mcapi_request_t *request,
                                mcapi_status_t *mcapi_status)
{
    MCAPI_GLOBAL_DATA   *node_data;
    mcapi_port_t        port_id;
    mcapi_node_t        node_id;
    MCAPI_ENDPOINT      *endp_ptr;

    /* Ensure the status pointer is valid. */
    if (mcapi_status)
    {
        /* Get the lock. */
        mcapi_lock_node_data();

        /* Get a pointer to the global node list. */
        node_data = mcapi_get_node_data();

        /* Get a pointer to the endpoint. */
        endp_ptr = mcapi_decode_local_endpoint(node_data, &node_id, &port_id,
                                               send_handle, mcapi_status);

        if (endp_ptr)
        {
            /* Close the receive side of the connection. */
            mcapi_close(endp_ptr, MCAPI_CHAN_SCAL_TYPE, request,
                        MCAPI_ENDP_TX, mcapi_status);
        }

        else if (*mcapi_status == MCAPI_ERR_ENDP_INVALID)
        {
            *mcapi_status = MCAPI_ERR_CHAN_INVALID;
        }

        /* Release the lock. */
        mcapi_unlock_node_data();
    }

}
コード例 #5
0
/*************************************************************************
*
*   FUNCTION
*
*       mcapi_get_node_id
*
*   DESCRIPTION
*
*       API routine to retrieve the node ID associated with the local node.
*
*   INPUTS
*
*       *mcapi_status           A pointer to memory that will be filled in
*                               with the status of the call.
*
*   OUTPUTS
*
*       The unique ID of the local node.
*
*************************************************************************/
mcapi_node_t mcapi_get_node_id(mcapi_status_t *mcapi_status)
{
    MCAPI_GLOBAL_DATA   *node_data;
    mcapi_node_t        node_id = 0;
    int                 i;

    /* Validate the status pointer. */
    if (mcapi_status)
    {
        /* Get the lock. */
        mcapi_lock_node_data();

        /* Get a pointer to the global node list. */
        node_data = mcapi_get_node_data();

        /* Get the index of the node associated with the node ID. */
        i = mcapi_find_node(MCAPI_Node_ID, node_data);

        /* If the node was found. */
        if (i != -1)
        {
            /* Return the node ID. */
            node_id = MCAPI_Node_ID;

            *mcapi_status = MCAPI_SUCCESS;
        }

        /* The local node has not been initialized yet. */
        else
        {
            *mcapi_status = MCAPI_ERR_NODE_NOTINIT;
        }

        mcapi_unlock_node_data();
    }

    return (node_id);

}
コード例 #6
0
ファイル: suspend.c プロジェクト: qttest1/PDK_GoBian
/*************************************************************************
*
*   FUNCTION
*
*       mcapi_check_resume
*
*   DESCRIPTION
*
*       Checks if any pending requests in the system should be resumed.
*
*   INPUTS
*
*       type                    The type of request to check.
*       endpoint                The endpoint for which the request is
*                               suspended on some action.
*       *endp_ptr               If data was received, a pointer to the
*                               endpoint for which data was received.
*       byte_count              If the type is MCAPI_REQ_TX_FIN or
*                               MCAPI_REQ_RX_FIN, the number of bytes
*                               pending on the endpoint.
*       status                  The status to set in the request structure.
*
*   OUTPUTS
*
*       None.
*
*************************************************************************/
void mcapi_check_resume(int type, mcapi_endpoint_t endpoint,
                        MCAPI_ENDPOINT *endp_ptr, size_t byte_count,
                        mcapi_status_t status)
{
    mcapi_request_t     *request, *next_ptr;
    MCAPI_GLOBAL_DATA   *node_data;
    MCAPI_BUFFER        *rx_buf;
    mcapi_boolean_t     data_copied = 0;

    /* Get a pointer to the global node list. */
    node_data = mcapi_get_node_data();

    /* Get a pointer to the first entry in the request queue. */
    request = node_data->mcapi_local_req_queue.flink;

    /* Check each request to see if the operation has been completed. */
    while (request)
    {
        /* Get a pointer to the next entry. */
        next_ptr = request->mcapi_next;

        switch (type)
        {
            /* An endpoint associated with a request structure has been
             * deleted.
             */
            case MCAPI_REQ_DELETED:

		//mcapi_printf("~~~~~Suspend received MCAPI_REQ_DELETED\n");
                /* If the operation is waiting for something to happen
                 * on the send side, and the endpoint matches the send
                 * endpoint.
                 */
                if ( ((request->mcapi_type == MCAPI_REQ_TX_FIN) ||
                      (request->mcapi_type == MCAPI_REQ_TX_OPEN) ||
                      (request->mcapi_type == MCAPI_REQ_CONNECTED)) &&
                      (request->mcapi_target_endp == endpoint) )
                {
                    mcapi_resume(node_data, request, status);
                }

                /* If the operation is waiting for something to happen
                 * on the receive side, and the endpoint matches the receive
                 * endpoint.
                 */
                else if ( ((request->mcapi_type == MCAPI_REQ_RX_FIN) ||
                           (request->mcapi_type == MCAPI_REQ_RX_OPEN) ||
                           (request->mcapi_type == MCAPI_REQ_CONNECTED)) &&
                          (request->mcapi_target_endp == endpoint) )
                {
                    mcapi_resume(node_data, request, status);
                }

                break;

            /* The connection has been closed. */
            case MCAPI_REQ_CLOSED:
		//mcapi_printf("~~~~~Suspend received MCAPI_REQ_CLOSED\n");
                /* No matter what the reason the thread is suspended, if the
                 * connection has been closed, resume the thread.
                 */
                if (request->mcapi_target_endp == endpoint)
                {
                    /* Resume the task. */
                    mcapi_resume(node_data, request, status);
                }

                break;

            /* The send side of an endpoint has been opened. */
            case MCAPI_REQ_TX_OPEN:
		 //mcapi_printf("~~~~~Suspend received MCAPI_REQ_TX_OPEN\n");
                /* If the request structure is waiting for the send side
                 * of the connection to open.
                 */
                if (request->mcapi_target_endp == endpoint)
                {
                    /* Resume the task. */
                    mcapi_resume(node_data, request, status);
                }

                break;

            /* Data associated with a request structure has been transmitted
             * successfully, or the transmit has been canceled.
             */
            case MCAPI_REQ_TX_FIN:
		//mcapi_printf("~~~~~Suspend received MCAPI_REQ_TX_FIN\n");
                /* If the request structure is waiting for outgoing data to be
                 * successfully transmitted.
                 */
                if ( (request->mcapi_type == MCAPI_REQ_TX_FIN) &&
                     (request->mcapi_target_endp == endpoint) )
                {

                    /* Resume the task. */
                    mcapi_resume(node_data, request, status);
                }

                break;

            /* The receive side of an endpoint has been opened. */
            case MCAPI_REQ_RX_OPEN:
		//mcapi_printf("~~~~~Suspend received MCAPI_REQ_RX_OPEN\n");
                /* If the request structure is waiting for the receive side
                 * of the connection to open.
                 */
                if (request->mcapi_target_endp == endpoint)
                {
                    /* Resume the task. */
                    mcapi_resume(node_data, request, status);
                }

                break;

            /* Data associated with a request structure has been received
             * successfully, or the receive has been canceled.
             */
            case MCAPI_REQ_RX_FIN:
		//mcapi_printf("~~~~~Suspend received MCAPI_REQ_RX_FIN\n");
                /* If the request structure is waiting for data to be
                 * received on the endpoint.
                 */
                if ( (request->mcapi_type == MCAPI_REQ_RX_FIN) &&
                     (request->mcapi_target_endp == endpoint) )
                {
                    switch (request->mcapi_chan_type)
                    {
                        case MCAPI_MSG_TYPE:

                            /* Ensure the data will fit in the buffer. */
                            if (byte_count <= request->mcapi_buf_size)
                            {
                                /* Copy the data into the user buffer. */
                                request->mcapi_byte_count =
                                    msg_recv_copy_data(endp_ptr, request->mcapi_buffer);

                                /* Data has been successfully copied. */
                                data_copied = MCAPI_TRUE;
                            }

                            /* The data is too big for the user buffer.  Leave
                             * the data on the receive queue for a subsequent
                             * receive call.
                             */
                            else
                            {
                                status = MCAPI_ERR_MSG_TRUNCATED;
                            }

                            break;

                        case MCAPI_CHAN_PKT_TYPE:

                            /* Get a pointer to the head buffer. */
                            rx_buf = endp_ptr->mcapi_rx_queue.head;

                            /* Set the user buffer to the incoming buffer. */
                            *(request->mcapi_pkt) =
                                &rx_buf->buf_ptr[MCAPI_HEADER_LEN];

                            /* Set the size of the incoming buffer. */
                            request->mcapi_byte_count =
                                rx_buf->buf_size - MCAPI_HEADER_LEN;

                            /* Data has been successfully copied. */
                            data_copied = MCAPI_TRUE;

                            break;

                        default:

                            break;
                    }

                    /* Resume the task. */
                    mcapi_resume(node_data, request, status);
                }

                break;

            /* An endpoint associated with a pending request has been
             * created.
             */
            case MCAPI_REQ_CREATED:
		//mcapi_printf("~~~~~Suspend received MCAPI_REQ_CREATED\n");
                /* If the request structure is waiting for an endpoint to be
                 * created.
                 */
                if ( (request->mcapi_type == MCAPI_REQ_CREATED) &&
                     (mcapi_encode_endpoint(request->mcapi_target_node_id,
                                            request->mcapi_target_port_id) == endpoint) )
                {
                    /* If this is a local call, fill in the endpoint pointer. */
                    if (request->mcapi_endp_ptr)
                    {
                        *(request->mcapi_endp_ptr) = endpoint;
                    }

                    mcapi_resume(node_data, request, status);
                }

                break;

            /* A connection between two endpoints has been made. */
            case MCAPI_REQ_CONNECTED:
		//mcapi_printf("~~~~~Suspend received MCAPI_REQ_CONNECTED\n");
		g_connect_finish = 1;
                /* If the request structure is waiting for a connection
                 * between two endpoints to be made.
                 */
                if ( (request->mcapi_type == MCAPI_REQ_CONNECTED) &&
                     (request->mcapi_target_endp == endpoint) )
                {
                    /* Resume the task. */
                    mcapi_resume(node_data, request, status);
                }

                break;

            default:

                break;
        }

        /* Get the next request entry in the list. */
        request = next_ptr;
    }

    /* Multiple request structures could have been suspended on the same
     * receive operation; therefore, the data must not be removed from
     * the queue until all request structures have been serviced.
     */
    if (data_copied)
    {
        /* Remove the buffer from the receive queue. */
        rx_buf = mcapi_dequeue(&endp_ptr->mcapi_rx_queue);

        if (endp_ptr->mcapi_chan_type == MCAPI_CHAN_PKT_TYPE)
        {
            /* Add the receive buffer structure to the list of
             * buffers waiting to be freed by the application.
             */
            mcapi_enqueue(&MCAPI_Buf_Wait_List, rx_buf);
        }

        else
        {
	    /*Enhanced by tony on 2013/12/13*/
#if 0
            /* Return the message buffer to the pool of available buffers. */
            ((MCAPI_INTERFACE*)(rx_buf->mcapi_dev_ptr))->
                mcapi_recover_buffer(rx_buf);
#endif
	    shm_free_buffer(rx_buf);
        }
    }

}
コード例 #7
0
/*************************************************************************
*
*   FUNCTION
*
*       mcapi_set_endpoint_attribute
*
*   DESCRIPTION
*
*       API routine to set attributes specific to a local endpoint.
*
*   INPUTS
*
*       endpoint                The endpoint identifier on the local node
*                               of which to set the attribute.
*       attribute_num           The attribute to set.
*       *attribute              The new value of the attribute being set.
*       attribute_size          The number of bytes contained in *attribute.
*       *mcapi_status           A pointer to memory that will be filled in
*                               with the status of the call.
*
*   OUTPUTS
*
*       None.
*
*************************************************************************/
void mcapi_set_endpoint_attribute(mcapi_endpoint_t endpoint,
                                  mcapi_uint_t attribute_num,
                                  void *attribute,
                                  size_t attribute_size,
                                  mcapi_status_t *mcapi_status)
{
    MCAPI_GLOBAL_DATA   *node_data;
    MCAPI_ENDPOINT      *endp_ptr = MCAPI_NULL;
    mcapi_port_t        port_id;
    mcapi_node_t        node_id;

    /* Validate mcapi_status input parameter. */
    if (mcapi_status)
    {
        /* Validate attribute input parameter. */
        if (attribute)
        {
            /* Get the lock. */
            mcapi_lock_node_data();

            /* Get a pointer to the global node list. */
            node_data = mcapi_get_node_data();

            /* Get a pointer to the endpoint. */
            endp_ptr = mcapi_decode_local_endpoint(node_data, &node_id, &port_id,
                                                   endpoint, mcapi_status);

            /* Ensure the endpoint is valid. */
            if ( (*mcapi_status == MCAPI_SUCCESS) &&
                 (endp_ptr->mcapi_state != MCAPI_ENDP_CLOSED) )
            {
                /* Ensure the endpoint is not already connected. */
                if (!(endp_ptr->mcapi_state & MCAPI_ENDP_CONNECTING))
                {
                    switch (attribute_num)
                    {
                        case MCAPI_ATTR_ENDP_PRIO:

                            /* If the priority is the correct size */
                            if (attribute_size == sizeof(endp_ptr->mcapi_priority))
                            {
                                /* Ensure the priority is valid. */
                                if (*(mcapi_uint32_t*)attribute < MCAPI_PRIO_COUNT)
                                {
                                    /* Update the priority of the endpoint. */
                                    endp_ptr->mcapi_priority = *(mcapi_uint32_t*)attribute;

                                    *mcapi_status = MCAPI_SUCCESS;
                                }

                                else
                                {
                                    *mcapi_status = MCAPI_ERR_PARAMETER;
                                }
                            }

                            /* The priority value is the wrong size. */
                            else
                            {
                                *mcapi_status = MCAPI_ERR_ATTR_SIZE;
                            }

                            break;

                    default:

                        /* If there is a route associated with the endpoint. */
                        if (endp_ptr->mcapi_route)
                        {
                            /* If there is an interfae associated with the
                             * route.
                             */
                            if (endp_ptr->mcapi_route->mcapi_rt_int)
                            {
                                /* Call the interface-specific ioctl command. */
                                *mcapi_status =
                                    endp_ptr->mcapi_route->mcapi_rt_int->mcapi_ioctl(attribute_num,
                                                                                     attribute,
                                                                                     attribute_size);
                            }
                        }

                        else
                        {
                            /* Unknown attribute. */
                            *mcapi_status = MCAPI_ERR_ATTR_NUM;
                        }

                        break;
                    }
                }

                /* Attributes of an endpoint cannot be changed once the
                 * endpoint has been connected.
                 */
                else
                {
                    *mcapi_status = MCAPI_ERR_CHAN_CONNECTED;
                }
            }

            /* Release the lock. */
            mcapi_unlock_node_data();
        }

        /* The pointer for attribute is invalid. */
        else
        {
            *mcapi_status = MCAPI_ERR_PARAMETER;
        }
    }

}
コード例 #8
0
ファイル: pkt_snd.c プロジェクト: altera-opensource/openmcapi
/*************************************************************************
*
*   FUNCTION
*
*       pkt_send
*
*   DESCRIPTION
*
*       Send a packet over a connected channel.  Called by both
*       blocking and non-blocking transmission routines.
*
*   INPUTS
*
*       send_handle             The transmission handle.
*       *buffer                 A pointer to the data to transmit.
*       buffer_size             The number of bytes of data to transmit.
*       *request                A pointer to memory that will be filled in
*                               with data relevant to the operation, so the
*                               status of the operation can later be checked.
*       *mcapi_status           A pointer to memory that will be filled in
*                               with the status of the call.
*       timeout                 The amount of time to block for the operation
*                               to complete.
*
*   OUTPUTS
*
*       None.
*
*************************************************************************/
void pkt_send(mcapi_pktchan_send_hndl_t send_handle, void *buffer,
              size_t buffer_size, mcapi_request_t *request,
              mcapi_status_t *mcapi_status, mcapi_uint32_t timeout)
{
    MCAPI_GLOBAL_DATA   *node_data;
    MCAPI_ENDPOINT      *tx_endp_ptr = MCAPI_NULL;
    MCAPI_BUFFER        *tx_buf;
    mcapi_port_t        port_id;
    mcapi_node_t        node_id;

    /* Validate the status parameter. */
    if (mcapi_status)
    {
        /* Validate the input parameters. */
        if ( (request) && ((buffer) || ((!buffer) && (buffer_size == 0))) )
        {
            /* Lock the global data structure. */
            mcapi_lock_node_data();

            /* Get a pointer to the global node list. */
            node_data = mcapi_get_node_data();

            /* Get a pointer to the endpoint that is sending data. */
            tx_endp_ptr = mcapi_decode_local_endpoint(node_data, &node_id,
                                                      &port_id,
                                                      send_handle,
                                                      mcapi_status);

            /* Ensure the transmit endpoint is valid. */
            if (tx_endp_ptr)
            {
                /* Ensure the length of the buffer is valid. */
                if (buffer_size + MCAPI_HEADER_LEN <=
                    tx_endp_ptr->mcapi_route->mcapi_rt_int->mcapi_max_buf_size)
                {
                    /* Ensure this is a send handle and the connection
                     * is still good.
                     */
                    if ( (tx_endp_ptr->mcapi_state & MCAPI_ENDP_TX) &&
                         (tx_endp_ptr->mcapi_state & MCAPI_ENDP_CONNECTED) )
                    {
                        /* Ensure the handle is for a packet channel. */
                        if (tx_endp_ptr->mcapi_chan_type == MCAPI_CHAN_PKT_TYPE)
                        {
                            /* Get a transmission buffer. */
                            tx_buf = tx_endp_ptr->mcapi_route->mcapi_rt_int->
                                mcapi_get_buffer(tx_endp_ptr->mcapi_foreign_node_id,
                                                 buffer_size + MCAPI_HEADER_LEN,
                                                 tx_endp_ptr->mcapi_priority);

                            if (tx_buf)
                            {
                                /* Save a pointer to the tx interface. */
                                tx_buf->mcapi_dev_ptr =
                                    (MCAPI_POINTER)(tx_endp_ptr->mcapi_route->mcapi_rt_int);

                                /* Initialize the request structure. */
                                mcapi_init_request(request, MCAPI_REQ_TX_FIN);

                                /* Set up the request structure. */
                                request->mcapi_target_endp = send_handle;

                                /* Set the source node in the packet. */
                                MCAPI_PUT16(tx_buf->buf_ptr, MCAPI_SRC_NODE_OFFSET,
                                            tx_endp_ptr->mcapi_node_id);

                                /* Set the source port in the packet. */
                                MCAPI_PUT16(tx_buf->buf_ptr, MCAPI_SRC_PORT_OFFSET,
                                            tx_endp_ptr->mcapi_port_id);

                                /* Set the destination node in the packet. */
                                MCAPI_PUT16(tx_buf->buf_ptr, MCAPI_DEST_NODE_OFFSET,
                                            tx_endp_ptr->mcapi_foreign_node_id);

                                /* Set the destination port in the packet. */
                                MCAPI_PUT16(tx_buf->buf_ptr, MCAPI_DEST_PORT_OFFSET,
                                            tx_endp_ptr->mcapi_foreign_port_id);

                                /* Set the priority of the packet. */
                                MCAPI_PUT16(tx_buf->buf_ptr, MCAPI_PRIO_OFFSET,
                                            tx_endp_ptr->mcapi_priority);

                                /* Zero out the unused bits. */
                                MCAPI_PUT16(tx_buf->buf_ptr, MCAPI_UNUSED_OFFSET, 0);

                                /* Copy the data into the MCAPI buffer. */
                                memcpy(&tx_buf->buf_ptr[MCAPI_HEADER_LEN], buffer,
                                       buffer_size);

                                /* Set the length of the data in the buffer. */
                                tx_buf->buf_size = buffer_size + MCAPI_HEADER_LEN;

                                /* Pass the data to the transport layer driver. */
                                *mcapi_status = tx_endp_ptr->mcapi_route->mcapi_rt_int->
                                    mcapi_tx_output(tx_buf, buffer_size,
                                                    tx_endp_ptr->mcapi_priority,
                                                    tx_endp_ptr);

                                /* The data was transmitted. */
                                if (*mcapi_status == MCAPI_SUCCESS)
                                {
                                    /* Set the status to success. */
                                    request->mcapi_status = MCAPI_SUCCESS;

                                    /* Record the number of bytes sent. */
                                    request->mcapi_byte_count = buffer_size;
                                }

                                /* The data could not be transmitted. */
                                else
                                {
                                    request->mcapi_status = *mcapi_status;

                                    /* Indicate that no data was sent. */
                                    request->mcapi_byte_count = 0;

                                    /* Return the transmission buffer to the list
                                     * of free buffers in the system.
                                     */
                                    ((MCAPI_INTERFACE*)(tx_buf->mcapi_dev_ptr))->
                                        mcapi_recover_buffer(tx_buf);
                                }
                            }

                            /* There are no transmission buffers available to
                             * process this request.
                             */
                            else
                            {
                                *mcapi_status = MCAPI_ERR_TRANSMISSION;
                            }
                        }

                        /* Trying to send a packet over a scalar channel. */
                        else
                        {
                            *mcapi_status = MCAPI_ERR_CHAN_TYPE;
                        }
                    }

                    /* Attempting to send over a receive channel. */
                    else
                    {
                        /* If this is a receive channel. */
                        if (tx_endp_ptr->mcapi_state & MCAPI_ENDP_RX)
                        {
                            *mcapi_status = MCAPI_ERR_CHAN_DIRECTION;
                        }

                        /* Otherwise, the connection has been closed. */
                        else
                        {
                            *mcapi_status = MCAPI_ERR_CHAN_INVALID;
                        }
                    }
                }

                /* The data size is too big. */
                else
                {
                    *mcapi_status = MCAPI_ERR_PKT_SIZE;
                }
            }

            /* One of the endpoints is invalid. */
            else
            {
                *mcapi_status = MCAPI_ERR_CHAN_INVALID;
            }

            /* Unlock the global data structure. */
            mcapi_unlock_node_data();
        }

        /* The buffer is invalid. */
        else
        {
            *mcapi_status = MCAPI_ERR_PARAMETER;
        }
    }

}