/************************************************************************* * * FUNCTION * * mcapi_pktchan_free * * DESCRIPTION * * Non-blocking API routine to return a system buffer. * * INPUTS * * *buffer A pointer to the buffer to return. * *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. * *************************************************************************/ void mcapi_pktchan_free(void *buffer, mcapi_status_t *mcapi_status) { MCAPI_BUFFER *cur_buf; /* Validate mcapi_status input parameter. */ if (mcapi_status) { /* Validate buffer input parameter. */ if (buffer) { /* Get the lock. */ mcapi_lock_node_data(); /* Get a pointer to the first buffer on the wait list. */ cur_buf = MCAPI_Buf_Wait_List.head; /* Find the buffer structure associated with this buffer. */ while (cur_buf) { /* If the buffer matches the buffer being free. */ if (cur_buf->buf_ptr == ((unsigned char*)buffer - MCAPI_HEADER_LEN)) { /* Remove this buffer from the Wait List. */ mcapi_remove(&MCAPI_Buf_Wait_List, cur_buf); /* Return the buffer to the list of free buffers. */ ((MCAPI_INTERFACE*)(cur_buf->mcapi_dev_ptr))-> mcapi_recover_buffer(cur_buf); break; } /* Get a pointer to the next buffer. */ cur_buf = (MCAPI_BUFFER*)(cur_buf->next_buf); } /* The buffer was found on the list. */ if (cur_buf) { *mcapi_status = MCAPI_SUCCESS; } /* The buffer was not found. */ else { *mcapi_status = MCAPI_ERR_BUF_INVALID; } /* Release the lock. */ mcapi_unlock_node_data(); } /* The buffer is not valid. */ else { *mcapi_status = MCAPI_ERR_BUF_INVALID; } } }
/************************************************************************* * * 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); }
/************************************************************************* * * 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); }
/************************************************************************* * * 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(); } }
/************************************************************************* * * 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); }
/************************************************************************* * * 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; } } }
/************************************************************************* * * 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; } } }