| /* |
| * Copyright (c) 1997-2010, 2013-2014 Wind River Systems, Inc. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * 1) Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * |
| * 2) Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * 3) Neither the name of Wind River Systems nor the names of its contributors |
| * may be used to endorse or promote products derived from this software without |
| * specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /* |
| * @file |
| * @brief Pipe kernel services |
| */ |
| |
| #include <micro_private.h> |
| #include <k_pipe_buffer.h> |
| #include <k_pipe_util.h> |
| #include <microkernel/pipe.h> |
| #include <misc/util.h> |
| |
| extern kpipe_t _k_pipe_ptr_start[]; |
| extern kpipe_t _k_pipe_ptr_end[]; |
| |
| /** |
| * @brief Initialize kernel pipe subsystem |
| * |
| * Performs any initialization of statically-defined pipes that wasn't done |
| * at build time. (Note: most pipe structure fields are set to zero by sysgen.) |
| * |
| * @return N/A |
| */ |
| void _k_pipe_init(void) |
| { |
| kpipe_t *pipeId; |
| struct _k_pipe_struct *pipe_ptr; |
| |
| for (pipeId = _k_pipe_ptr_start; pipeId < _k_pipe_ptr_end; pipeId++) { |
| pipe_ptr = (struct _k_pipe_struct *)(*pipeId); |
| BuffInit((unsigned char *)pipe_ptr->Buffer, |
| &(pipe_ptr->buffer_size), &pipe_ptr->desc); |
| } |
| } |
| |
| /** |
| * @brief Pipe read request |
| * |
| * This routine attempts to read data into a memory buffer area from the |
| * specified pipe. |
| * |
| * @return RC_OK, RC_INCOMPLETE, RC_FAIL, RC_TIME, or RC_ALIGNMENT |
| */ |
| int _task_pipe_get(kpipe_t Id, void *pBuffer, |
| int iNbrBytesToRead, int *piNbrBytesRead, |
| K_PIPE_OPTION Option, int32_t TimeOut) |
| { |
| struct k_args A; |
| |
| /* some users do not check the FUNCTION return value, |
| but immediately use iNbrBytesRead; make sure it always |
| has a good value, even when we return failure immediately |
| (see below) */ |
| |
| *piNbrBytesRead = 0; |
| |
| if (unlikely(iNbrBytesToRead % SIZEOFUNIT_TO_OCTET(1))) { |
| return RC_ALIGNMENT; |
| } |
| if (unlikely(0 == iNbrBytesToRead)) { |
| /* not allowed because enlisted requests with zero size |
| will hang in _k_pipe_process() */ |
| return RC_FAIL; |
| } |
| if (unlikely(_0_TO_N == Option && TICKS_NONE != TimeOut)) { |
| return RC_FAIL; |
| } |
| |
| A.priority = _k_current_task->priority; |
| A.Comm = _K_SVC_PIPE_GET_REQUEST; |
| A.Time.ticks = TimeOut; |
| |
| A.args.pipe_req.req_info.pipe.id = Id; |
| A.args.pipe_req.req_type.sync.total_size = iNbrBytesToRead; |
| A.args.pipe_req.req_type.sync.data_ptr = pBuffer; |
| |
| _k_pipe_option_set(&A.args, Option); |
| _k_pipe_request_type_set(&A.args, _SYNCREQ); |
| |
| KERNEL_ENTRY(&A); |
| |
| *piNbrBytesRead = A.args.pipe_ack.xferred_size; |
| return A.Time.rcode; |
| } |
| |
| /** |
| * @brief Pipe write request |
| * |
| * This routine attempts to write data from a memory buffer area to the |
| * specified pipe. |
| * |
| * @return RC_OK, RC_INCOMPLETE, RC_FAIL, RC_TIME, or RC_ALIGNMENT |
| */ |
| int _task_pipe_put(kpipe_t Id, void *pBuffer, |
| int iNbrBytesToWrite, int *piNbrBytesWritten, |
| K_PIPE_OPTION Option, int32_t TimeOut) |
| { |
| struct k_args A; |
| |
| /* some users do not check the FUNCTION return value, |
| but immediately use iNbrBytesWritten; make sure it always |
| has a good value, even when we return failure immediately |
| (see below) */ |
| |
| *piNbrBytesWritten = 0; |
| |
| if (unlikely(iNbrBytesToWrite % SIZEOFUNIT_TO_OCTET(1))) { |
| return RC_ALIGNMENT; |
| } |
| if (unlikely(0 == iNbrBytesToWrite)) { |
| /* not allowed because enlisted requests with zero size |
| will hang in _k_pipe_process() */ |
| return RC_FAIL; |
| } |
| if (unlikely(_0_TO_N == Option && TICKS_NONE != TimeOut)) { |
| return RC_FAIL; |
| } |
| |
| A.priority = _k_current_task->priority; |
| A.Comm = _K_SVC_PIPE_PUT_REQUEST; |
| A.Time.ticks = TimeOut; |
| |
| A.args.pipe_req.req_info.pipe.id = Id; |
| A.args.pipe_req.req_type.sync.total_size = iNbrBytesToWrite; |
| A.args.pipe_req.req_type.sync.data_ptr = pBuffer; |
| |
| _k_pipe_option_set(&A.args, Option); |
| _k_pipe_request_type_set(&A.args, _SYNCREQ); |
| |
| KERNEL_ENTRY(&A); |
| |
| *piNbrBytesWritten = A.args.pipe_ack.xferred_size; |
| return A.Time.rcode; |
| } |
| |
| /** |
| * @brief Asynchronous pipe write request |
| * |
| * This routine attempts to write data from a memory pool block to the |
| * specified pipe. (Note that partial transfers and timeouts are not |
| * supported, unlike the case for synchronous write requests.) |
| * |
| * @return RC_OK, RC_FAIL, or RC_ALIGNMENT |
| */ |
| int _task_pipe_block_put(kpipe_t Id, struct k_block Block, |
| int iReqSize2Xfer, ksem_t sema) |
| { |
| unsigned int iSize2Xfer; |
| struct k_args A; |
| |
| iSize2Xfer = min((unsigned)iReqSize2Xfer, (unsigned)(Block.req_size)); |
| |
| if (unlikely(iSize2Xfer % SIZEOFUNIT_TO_OCTET(1))) { |
| return RC_ALIGNMENT; |
| } |
| if (unlikely(0 == iSize2Xfer)) { |
| /* not allowed because enlisted requests with zero size |
| will hang in _k_pipe_process() */ |
| return RC_FAIL; |
| } |
| |
| A.priority = _k_current_task->priority; |
| A.Comm = _K_SVC_PIPE_PUT_REQUEST; |
| A.Time.ticks = TICKS_UNLIMITED; |
| /* same behavior in flow as a blocking call w/o a timeout */ |
| |
| A.args.pipe_req.req_info.pipe.id = Id; |
| A.args.pipe_req.req_type.async.block = Block; |
| A.args.pipe_req.req_type.async.total_size = iSize2Xfer; |
| A.args.pipe_req.req_type.async.sema = sema; |
| |
| _k_pipe_request_type_set(&A.args, _ASYNCREQ); |
| _k_pipe_option_set(&A.args, _ALL_N); /* force ALL_N */ |
| |
| KERNEL_ENTRY(&A); |
| return RC_OK; |
| } |