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