c0138ae4f9bb9963d7d8c60177f4a14ffca1b3d2
[ipc/ipcdev.git] / packages / ti / sdo / ipc / family / f28m35x / TransportCirc.c
1 /*
2  * Copyright (c) 2012-2013, 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  *  ======== TransportCirc.c ========
34  */
36 #include <string.h>  /* for memcpy() */
38 #include <xdc/std.h>
39 #include <xdc/runtime/Assert.h>
40 #include <xdc/runtime/Error.h>
41 #include <xdc/runtime/Memory.h>
43 #include <ti/sysbios/hal/Hwi.h>
44 #include <ti/sysbios/knl/Swi.h>
46 #include <ti/sdo/ipc/family/f28m35x/IpcMgr.h>
48 #include "package/internal/TransportCirc.xdc.h"
50 #include <ti/sdo/utils/_MultiProc.h>
51 #include <ti/sdo/ipc/_Notify.h>
52 #include <ti/sdo/ipc/_MessageQ.h>
54 /* Need to use reserved notify events */
55 #undef TransportCirc_notifyEventId
56 #define TransportCirc_notifyEventId \
57     ti_sdo_ipc_family_f28m35x_TransportCirc_notifyEventId + \
58     (UInt32)((UInt32)Notify_SYSTEMKEY << 16)
60 /*
61  *************************************************************************
62  *                       Instance functions
63  *************************************************************************
64  */
66 /*
67  *  ======== TransportCirc_Instance_init ========
68  */
69 Int TransportCirc_Instance_init(TransportCirc_Object *obj,
70         UInt16 remoteProcId, const TransportCirc_Params *params,
71         Error_Block *eb)
72 {
73     Int        status;
74     Bool       flag;
75     Swi_Handle swiHandle;
76     Swi_Params swiParams;
77     SizeT      circBufSize;
79     swiHandle = TransportCirc_Instance_State_swiObj(obj);
81     /* init the object fields */
82     obj->priority     = params->priority;
83     obj->remoteProcId = remoteProcId;
85     /* construct the swi with lowest priority */
86     Swi_Params_init(&swiParams);
87     swiParams.arg0 = (UArg)obj;
88     swiParams.priority = params->swiPriority;
89     Swi_construct(Swi_struct(swiHandle),
90                  (Swi_FuncPtr)TransportCirc_swiFxn,
91                  &swiParams, eb);
93     /* calculate the circular buffer size one-way */
94     circBufSize = TransportCirc_msgSize * TransportCirc_numMsgs;
96     /* Init put/get buffer and index pointers. */
97     obj->putBuffer = params->writeAddr;
99     obj->putWriteIndex = (Bits32 *)((UInt32)obj->putBuffer + circBufSize);
101     obj->getBuffer = params->readAddr;
103     obj->getWriteIndex = (Bits32 *)((UInt32)obj->getBuffer + circBufSize);
105     obj->putReadIndex = (Bits32 *)((UInt32)obj->getWriteIndex + sizeof(Bits32));
107     obj->getReadIndex = (Bits32 *)((UInt32)obj->putWriteIndex + sizeof(Bits32));
109     /* init the putWrite and getRead Index to 0 */
110     obj->putWriteIndex[0] = 0;
111     obj->getReadIndex[0] = 0;
113     /* register the event with Notify */
114     status = Notify_registerEventSingle(
115                  remoteProcId,    /* remoteProcId */
116                  0,         /* lineId */
117                  TransportCirc_notifyEventId,
118                  (Notify_FnNotifyCbck)TransportCirc_notifyFxn,
119                  (UArg)swiHandle);
121     if (status < 0) {
122         Error_raise(eb, IpcMgr_E_internal, 0, 0);
123         return (1);
124     }
126     /* Register the transport with MessageQ */
127     flag = ti_sdo_ipc_MessageQ_registerTransport(
128         TransportCirc_Handle_upCast(obj), remoteProcId, params->priority);
130     if (flag == FALSE) {
131         Error_raise(eb, IpcMgr_E_internal, 0, 0);
132         return (2);
133     }
135     return (0);
138 /*
139  *  ======== TransportCirc_Instance_finalize ========
140  */
141 Void TransportCirc_Instance_finalize(TransportCirc_Object* obj, Int status)
143     Swi_Handle     swiHandle;
145     switch(status) {
146         case 0:
147             /* MessageQ_registerTransport succeeded */
148             ti_sdo_ipc_MessageQ_unregisterTransport(obj->remoteProcId,
149                 obj->priority);
151             /* OK to fall thru */
153         case 1: /* Notify_registerEventSingle failed */
155             /* OK to fall thru */
157         case 2: /* MessageQ_registerTransport failed */
158             Notify_unregisterEventSingle(
159                 obj->remoteProcId,
160                 0,
161                 TransportCirc_notifyEventId);
162             break;
163     }
165     /* Destruct the swi */
166     swiHandle = TransportCirc_Instance_State_swiObj(obj);
167     if (swiHandle != NULL) {
168         Swi_destruct(Swi_struct(swiHandle));
169     }
172 /*
173  *  ======== TransportCirc_put ========
174  *  Assuming MessageQ_put is making sure that the arguments are ok
175  */
176 Bool TransportCirc_put(TransportCirc_Object *obj, Ptr msg)
178     Int status;
179     UInt msgSize;
180     UInt hwiKey;
181     Ptr writeAddr;
182     UInt writeIndex, readIndex;
184     do {
185         /* disable interrupts */
186         hwiKey = Hwi_disable();
188         /* get the writeIndex and readIndex */
189         readIndex  = obj->putReadIndex[0];
190         writeIndex = obj->putWriteIndex[0];
192         /* if slot available 'break' out of loop */
193         if (((writeIndex + 1) & TransportCirc_maxIndex) != readIndex) {
194             break;
195         }
197         /* restore interrupts */
198         Hwi_restore(hwiKey);
200     } while (1);
202     /* interrupts are disabled at this point */
204     /* get a free buffer and copy the message into it */
205     writeAddr = (Ptr)((UInt32)obj->putBuffer +
206                 (writeIndex * TransportCirc_msgSize));
208     /* get the size of the message */
209     msgSize = MessageQ_getMsgSize(msg);
211     Assert_isTrue(msgSize <= TransportCirc_msgSize, IpcMgr_A_internal);
213     /* copy message to the write buffer */
214     memcpy(writeAddr, (Ptr)msg, msgSize);
216     /* update the writeIndex */
217     obj->putWriteIndex[0] = (writeIndex + 1) & TransportCirc_maxIndex;
219     /* restore interrupts */
220     Hwi_restore(hwiKey);
222     /* free the app's message */
223     if (((MessageQ_Msg)msg)->heapId != ti_sdo_ipc_MessageQ_STATICMSG) {
224         MessageQ_free(msg);
225     }
227     /* Notify the remote processor */
228     status = Notify_sendEvent(
229                  obj->remoteProcId,
230                  0,
231                  TransportCirc_notifyEventId,
232                  (UInt32)NULL,
233                  FALSE);
235     /* check the status of the sendEvent */
236     if (status < 0) {
237         return (FALSE);
238     }
240     return (TRUE);
243 /*
244  *  ======== TransportCirc_control ========
245  */
246 Bool TransportCirc_control(TransportCirc_Object *obj, UInt cmd,
247     UArg cmdArg)
249     return (FALSE);
252 /*
253  *  ======== TransportCirc_getStatus ========
254  */
255 Int TransportCirc_getStatus(TransportCirc_Object *obj)
257     return (0);
260 /*
261  *************************************************************************
262  *                       Module functions
263  *************************************************************************
264  */
266 /*
267  *  ======== TransportCirc_notifyFxn ========
268  */
269 Void TransportCirc_notifyFxn(UInt16 procId,
270                              UInt16 lineId,
271                              UInt32 eventId,
272                              UArg arg,
273                              UInt32 payload)
275     Swi_Handle swiHandle;
277     /* Swi_Handle was passed as arg in register */
278     swiHandle = (Swi_Handle)arg;
280     /* post the Swi */
281     Swi_post(swiHandle);
284 /*
285  *  ======== TransportCirc_swiFxn ========
286  */
287 Void TransportCirc_swiFxn(UArg arg)
289     UInt32 queueId;
290     TransportCirc_Object *obj = (TransportCirc_Object *)arg;
291     MessageQ_Msg msg = NULL;
292     MessageQ_Msg buf = NULL;
293     SizeT msgSize;
294     UInt writeIndex, readIndex;
295     UInt offset;
297     /* Make sure the TransportCirc_Object is not NULL */
298     Assert_isTrue(obj != NULL, IpcMgr_A_internal);
300     /* get the writeIndex and readIndex */
301     writeIndex = obj->getWriteIndex[0];
302     readIndex  = obj->getReadIndex[0];
304     while (writeIndex != readIndex) {
305         /* determine where the message from remote core is */
306         offset = (readIndex * TransportCirc_msgSize);
308         /* get the message */
309         msg = (MessageQ_Msg)((UInt32)obj->getBuffer + offset);
311 #ifdef xdc_target__isaCompatible_28
312         /*
313          *  The message size needs to be halved because it was
314          *  specified in bytes and the units on the c28 is 16-bit
315          *  words.
316          */
317         msgSize = MessageQ_getMsgSize(msg) >> 1;
318 #else
319         /*
320          *  The message size needs to be doubled because it was
321          *  specified in 16-bit words and the units on the m3 is
322          *  in bytes.
323          */
324         msgSize = MessageQ_getMsgSize(msg) << 1;
325 #endif
327         /* alloc a message from msg->heapId to copy the msg to */
328         buf = MessageQ_alloc(msg->heapId, msgSize);
330         /* Make sure buf is not NULL */
331         if (buf == NULL) {
332             TransportCirc_errFxn(TransportCirc_Reason_FAILEDALLOC,
333                 ti_sdo_ipc_family_f28m35x_TransportCirc_Handle_upCast(obj),
334                 NULL,
335                 (UArg)msg);
337             return;
338         }
340         /* copy the message to the buffer allocated, set the heap id */
341         memcpy((Ptr)buf, (Ptr)msg, msgSize);
343         /* overwrite the msgSize in the msg */
344         buf->msgSize = msgSize;
346         /* retrieve the detination queue id */
347         queueId = MessageQ_getDstQueue(msg);
349         /* put the message to the destination queue */
350         MessageQ_put(queueId, buf);
352         /* update the local readIndex. */
353         readIndex = ((readIndex + 1) & TransportCirc_maxIndex);
355         /* set the readIndex */
356         obj->getReadIndex[0] = readIndex;
357     }
360 /*
361  *************************************************************************
362  *                      Module functions
363  *************************************************************************
364  */
366 /*
367  *  ======== TransportCirc_close ========
368  */
369 Void TransportCirc_close(TransportCirc_Handle *handle)
371     TransportCirc_delete(handle);
374 /*
375  *  ======== TransportCirc_sharedMemReq ========
376  */
377 SizeT TransportCirc_sharedMemReq(const TransportCirc_Params *params)
379     SizeT memReq;
381     /* Ensure that params is non-NULL */
382     Assert_isTrue(params != NULL, IpcMgr_A_internal);
384     /*
385      *  Amount of shared memory:
386      *  1 putBuffer (msgSize * numMsgs) +
387      *  1 putWriteIndex ptr             +
388      *  1 putReadIndex ptr              +
389      */
390     memReq = (TransportCirc_msgSize * TransportCirc_numMsgs) +
391              (2 * sizeof(Bits32));
393     return (memReq);
396 /*
397  *  ======== TransportCirc_setErrFxn ========
398  */
399 Void TransportCirc_setErrFxn(TransportCirc_ErrFxn errFxn)
401     /* Ignore the errFxn */