/* * Copyright (c) 2012-2014, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * 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. * * * Neither the name of Texas Instruments Incorporated 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 OWNER 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 Ipc.c * * @brief Starts and stops user side Ipc * All setup/destroy APIs on user side will be call from this * module. */ /* Standard headers */ #include #include #include /* Common IPC headers: */ #include #include #include #include #include /* User side headers */ #include /* IPC startup/shutdown stuff: */ #include #include #include <_GateMP.h> #include <_MultiProc.h> #include <_MessageQ.h> #include <_NameServer.h> GateHWSpinlock_Config _GateHWSpinlock_cfgParams; static LAD_ClientHandle ladHandle; static void cleanup(int arg); /** ============================================================================ * Functions * ============================================================================ */ /* Function to start Ipc */ Int Ipc_start (Void) { TransportRpmsg_Handle transport; TransportRpmsg_Params params; IMessageQTransport_Handle iMsgQTrans; MessageQ_Config msgqCfg; MultiProc_Config mpCfg; #if defined(GATEMP_SUPPORT) GateHWSpinlock_Config gateHWCfg; #endif Int attachStatus; Int32 status; LAD_Status ladStatus; UInt16 rprocId; Int32 attachedAny; /* Catch ctrl-C, and cleanup: */ (void) signal(SIGINT, cleanup); if (getenv("IPC_DEBUG") != NULL) { /* turn on tracing */ if (getenv("IPC_DEBUG")[0] == '1') { /* level 1 enables typical user API tracing */ _MessageQ_verbose = TRUE; _MultiProc_verbose = TRUE; _NameServer_verbose = TRUE; #if defined(GATEMP_SUPPORT) _GateMP_verbose = TRUE; _GateHWSpinlock_verbose = TRUE; #endif } else if ((getenv("IPC_DEBUG")[0] == '2') || (getenv("IPC_DEBUG")[0] == '3')) { /* levels 2 and 3 add socket and LAD client tracing */ _MessageQ_verbose = TRUE; _MultiProc_verbose = TRUE; _NameServer_verbose = TRUE; #if defined(GATEMP_SUPPORT) _GateMP_verbose = TRUE; _GateHWSpinlock_verbose = TRUE; #endif /* internals - should be declared in respective _*.h files */ extern Bool _SocketFxns_verbose; extern Bool _LAD_Client_verbose; _SocketFxns_verbose = TRUE; _LAD_Client_verbose = TRUE; } } ladStatus = LAD_connect(&ladHandle); if (ladStatus != LAD_SUCCESS) { printf("Ipc_start: LAD_connect() failed: %d\n", ladStatus); status = Ipc_E_FAIL; goto exit; } /* * Get MultiProc configuration from LAD and initialize local MultiProc * config structure. */ MultiProc_getConfig(&mpCfg); _MultiProc_initCfg(&mpCfg); status = NameServer_setup(); if (status >= 0) { MessageQ_getConfig(&msgqCfg); MessageQ_setup(&msgqCfg); /* * Attach to all remote processors. We need to attach to * at least one, so tolerate MessageQ_E_RESOURCE failures for * now. */ status = Ipc_S_SUCCESS; attachedAny = FALSE; for (rprocId = 0; rprocId < MultiProc_getNumProcessors(); rprocId++) { if (0 == rprocId) { /* Skip host, which should always be 0th entry. */ continue; } params.rprocId = rprocId; transport = TransportRpmsg_create(¶ms, &attachStatus); if (transport) { iMsgQTrans = TransportRpmsg_upCast(transport); MessageQ_registerTransport(iMsgQTrans, rprocId, 0); attachedAny = TRUE; } else { if (attachStatus == MessageQ_E_RESOURCE) { continue; } printf("Ipc_start: failed to attach to %d: %d\n", rprocId, attachStatus); status = Ipc_E_FAIL; break; } } if (!attachedAny) { status = Ipc_E_FAIL; } } else { printf("Ipc_start: NameServer_setup() failed: %d\n", status); status = Ipc_E_FAIL; } /* Start GateMP only if device has support */ #if defined(GATEMP_SUPPORT) if (GateMP_isSetup()) { /* * Get HWSpinlock base address and size from LAD and * initialize the local config structure. */ GateHWSpinlock_getConfig(&gateHWCfg); _GateHWSpinlock_cfgParams = gateHWCfg; status = GateHWSpinlock_start(); if (status < 0) { printf("Ipc_start: GateHWSpinlock_start failed: %d\n", status); status = Ipc_E_FAIL; goto gatehwspinlockstart_fail; } else { status = GateMP_start(); if (status < 0) { printf("Ipc_start: GateMP_start failed: %d\n", status); status = Ipc_E_FAIL; goto gatempstart_fail; } } } #endif /* Success */ goto exit; #if defined(GATEMP_SUPPORT) gatempstart_fail: GateHWSpinlock_stop(); gatehwspinlockstart_fail: #if 0 for (rprocId = rprocId - 1; (rprocId > 0) && (status >= 0); rprocId--) { MessageQ_detach(rprocId); } #endif #endif exit: return (status); } /* Function to stop Ipc */ Int Ipc_stop (Void) { Int32 status = Ipc_S_SUCCESS; LAD_Status ladStatus; UInt16 rprocId; /* Now detach from all remote processors, assuming they are up. */ for (rprocId = 0; (rprocId < MultiProc_getNumProcessors()) && (status >= 0); rprocId++) { if (0 == rprocId) { /* Skip host, which should always be 0th entry. */ continue; } #if 0 status = MessageQ_detach(rprocId); if (status < 0) { printf("Ipc_stop: MessageQ_detach(%d) failed: %d\n", rprocId, status); status = Ipc_E_FAIL; goto exit; } #endif } status = MessageQ_destroy(); if (status < 0) { printf("Ipc_stop: MessageQ_destroy() failed: %d\n", status); status = Ipc_E_FAIL; goto exit; } status = NameServer_destroy(); if (status < 0) { printf("Ipc_stop: NameServer_destroy() failed: %d\n", status); status = Ipc_E_FAIL; goto exit; } ladStatus = LAD_disconnect(ladHandle); if (ladStatus != LAD_SUCCESS) { printf("LAD_disconnect() failed: %d\n", ladStatus); status = Ipc_E_FAIL; goto exit; } exit: return (status); } static void cleanup(int arg) { printf("Ipc: Caught SIGINT, calling Ipc_stop...\n"); Ipc_stop(); exit(0); }