1 /*
2 * Copyright (c) 2013-2015, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 /*!
33 * @file Ipc.c
34 *
35 * @brief Starts and stops user side Ipc
36 * All setup/destroy APIs on user side will be call from this
37 * module.
38 *
39 * @ver 0002
40 *
41 */
43 /* Standard headers */
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <signal.h>
47 #include <ti/ipc/Std.h>
49 /* Common IPC headers: */
50 #include <ti/ipc/Ipc.h>
51 #include <ti/ipc/NameServer.h>
53 /* User side headers */
54 #include <ti/syslink/inc/usr/Qnx/IpcDrv.h>
56 /* IPC startup/shutdown stuff: */
57 #include <ti/ipc/MultiProc.h>
58 #include <ti/ipc/MessageQ.h>
59 #include <ti/ipc/NameServer.h>
60 #include <_MessageQ.h>
61 #include <_NameServer.h>
62 #include <_GateMP.h>
63 #include <_GateMP_usr.h>
64 #include <_TiIpcFxns.h>
65 #include <_IpcLog.h>
66 #include <ti/syslink/inc/_GateHWSpinlock.h>
67 #include <ti/syslink/inc/_MultiProc.h>
69 MultiProc_Config _MultiProc_cfg;
71 /* traces in this file are controlled via _Ipc_verbose */
72 Bool _Ipc_verbose = FALSE;
73 #define verbose _Ipc_verbose
75 static void cleanup(int arg);
77 /** ============================================================================
78 * Functions
79 * ============================================================================
80 */
81 /* Function to start Ipc */
82 Int Ipc_start (Void)
83 {
84 MessageQ_Config msgqCfg;
85 MultiProc_Config mpCfg;
86 Int32 status = Ipc_S_SUCCESS;
87 UInt16 rprocId;
89 /* Catch ctrl-C, and cleanup: */
90 (void) signal(SIGINT, cleanup);
92 if (getenv("IPC_DEBUG") != NULL) {
93 /* turn on tracing */
94 if (getenv("IPC_DEBUG")[0] == '1') {
95 /* level 1 enables typical user API tracing */
96 _Ipc_verbose = TRUE;
97 _MessageQ_verbose = TRUE;
98 _MultiProc_verbose = TRUE;
99 _NameServer_verbose = TRUE;
100 #if defined(GATEMP_SUPPORT)
101 _GateMP_verbose = TRUE;
103 _GateHWSpinlock_verbose = TRUE;
104 #endif
105 }
106 else if ((getenv("IPC_DEBUG")[0] == '2') ||
107 (getenv("IPC_DEBUG")[0] == '3')) {
108 /* levels 2 and 3 add TiIpcFxns tracing */
109 _Ipc_verbose = TRUE;
110 _MessageQ_verbose = TRUE;
111 _MultiProc_verbose = TRUE;
112 _NameServer_verbose = TRUE;
114 #if defined(GATEMP_SUPPORT)
115 _GateMP_verbose = TRUE;
117 _GateHWSpinlock_verbose = TRUE;
118 #endif
120 _TiIpcFxns_verbose = TRUE;
121 }
122 }
124 status = IpcDrv_open();
125 if (status < 0) {
126 printf("Ipc_start: IpcDrv_open() failed: %d\n", status);
127 status = Ipc_E_FAIL;
128 goto exit;
129 }
131 status = NameServer_setup();
132 if (status >= 0) {
133 MessageQ_getConfig(&msgqCfg);
134 MessageQ_setup(&msgqCfg);
136 /* Setup and get MultiProc configuration from resource manager */
137 MultiProc_getConfig(&mpCfg);
138 _MultiProc_cfg = mpCfg;
140 /* Now attach to all remote processors, assuming they are up. */
141 for (rprocId = 0;
142 (rprocId < MultiProc_getNumProcessors()) && (status >= 0);
143 rprocId++) {
144 if (0 == rprocId) {
145 /* Skip host, which should always be 0th entry. */
146 continue;
147 }
148 status = MessageQ_attach (rprocId, NULL);
149 if (status < 0) {
150 printf("Ipc_start: MessageQ_attach(%d) failed: %d\n",
151 rprocId, status);
152 status = Ipc_E_FAIL;
153 goto messageqattach_fail;
154 }
155 }
157 /*
158 * Check if MultiProc config is valid and that
159 * MultiProc_getNumProcessors() is non-zero to make sure we are not
160 * in the middle of a recovery.
161 */
162 if (rprocId == 0) {
163 PRINTVERBOSE0("Ipc_start: MultiProc not yet configured\n")
164 status = Ipc_E_FAIL;
165 goto messageqattach_fail;
166 }
167 }
168 else {
169 printf("Ipc_start: NameServer_setup() failed: %d\n", status);
170 status = Ipc_E_FAIL;
171 goto nameserversetup_fail;
172 }
174 /* Start GateMP only if it is setup in the resource manager */
175 #if defined(GATEMP_SUPPORT)
176 if (GateMP_isSetup()) {
177 /* Get GateHWSpinlock configuration from resource manager */
178 status = GateHWSpinlock_start();
179 if (status < 0) {
180 printf("Ipc_start: GateHWSpinlock_start failed: %d\n",
181 status);
182 status = Ipc_E_FAIL;
183 goto gatehwspinlockstart_fail;
184 }
185 else {
186 status = GateMP_start();
187 if (status < 0) {
188 printf("Ipc_start: GateMP_start failed: %d\n",
189 status);
190 status = Ipc_E_FAIL;
191 goto gatempstart_fail;
192 }
193 }
194 }
195 #endif
196 /* Success */
197 goto exit;
198 #if defined(GATEMP_SUPPORT)
199 gatempstart_fail:
200 GateHWSpinlock_stop();
201 gatehwspinlockstart_fail:
202 for (rprocId = rprocId - 1; (rprocId > 0) && (status >= 0); rprocId--) {
203 MessageQ_detach(rprocId);
204 }
205 #endif
206 messageqattach_fail:
207 MessageQ_destroy();
208 NameServer_destroy();
209 nameserversetup_fail:
210 IpcDrv_close();
212 exit:
213 return (status);
214 }
217 /* Function to stop Ipc */
218 Int Ipc_stop (Void)
219 {
220 Int32 status = Ipc_S_SUCCESS;
221 UInt16 rprocId;
222 #if defined(GATEMP_SUPPORT)
223 if (GateMP_isSetup()) {
224 /* Stop GateMP */
225 status = GateMP_stop();
226 if (status < 0) {
227 printf("Ipc_stop: GateMP_stop() failed: %d\n", status);
228 status = Ipc_E_FAIL;
229 goto exit;
230 }
232 /* Finalize GateHWSpinlock */
233 status = GateHWSpinlock_stop();
234 if (status < 0) {
235 printf("Ipc_stop: GateHWSpinlock_stop() failed: %d\n", status);
236 status = Ipc_E_FAIL;
237 goto exit;
238 }
239 }
240 #endif
241 /* Now detach from all remote processors, assuming they are up. */
242 for (rprocId = 0;
243 (rprocId < MultiProc_getNumProcessors()) && (status >= 0);
244 rprocId++) {
245 if (0 == rprocId) {
246 /* Skip host, which should always be 0th entry. */
247 continue;
248 }
249 status = MessageQ_detach(rprocId);
250 if (status < 0) {
251 printf("Ipc_stop: MessageQ_detach(%d) failed: %d\n",
252 rprocId, status);
253 status = Ipc_E_FAIL;
254 goto exit;
255 }
256 }
258 status = MessageQ_destroy();
259 if (status < 0) {
260 printf("Ipc_stop: MessageQ_destroy() failed: %d\n", status);
261 status = Ipc_E_FAIL;
262 goto exit;
263 }
265 status = NameServer_destroy();
266 if (status < 0) {
267 printf("Ipc_stop: NameServer_destroy() failed: %d\n", status);
268 status = Ipc_E_FAIL;
269 goto exit;
270 }
272 IpcDrv_close();
274 exit:
275 return (status);
276 }
278 static void cleanup(int arg)
279 {
280 printf("Ipc: Caught SIGINT, calling Ipc_stop...\n");
281 Ipc_stop();
282 exit(0);
283 }