bbbc7fd626ceaec66e7233e8a49043fa22df061c
[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     Swi_construct(Swi_struct(swiHandle),
89                  (Swi_FuncPtr)TransportCirc_swiFxn,
90                  &swiParams, eb);
92     /* calculate the circular buffer size one-way */
93     circBufSize = TransportCirc_msgSize * TransportCirc_numMsgs;
95     /* Init put/get buffer and index pointers. */
96     obj->putBuffer = params->writeAddr;
98     obj->putWriteIndex = (Bits32 *)((UInt32)obj->putBuffer + circBufSize);
100     obj->getBuffer = params->readAddr;
102     obj->getWriteIndex = (Bits32 *)((UInt32)obj->getBuffer + circBufSize);
104     obj->putReadIndex = (Bits32 *)((UInt32)obj->getWriteIndex + sizeof(Bits32));
106     obj->getReadIndex = (Bits32 *)((UInt32)obj->putWriteIndex + sizeof(Bits32));
108     /* init the putWrite and getRead Index to 0 */
109     obj->putWriteIndex[0] = 0;
110     obj->getReadIndex[0] = 0;
112     /* register the event with Notify */
113     status = Notify_registerEventSingle(
114                  remoteProcId,    /* remoteProcId */
115                  0,         /* lineId */
116                  TransportCirc_notifyEventId,
117                  (Notify_FnNotifyCbck)TransportCirc_notifyFxn,
118                  (UArg)swiHandle);
120     if (status < 0) {
121         Error_raise(eb, IpcMgr_E_internal, 0, 0);
122         return (1);
123     }
125     /* Register the transport with MessageQ */
126     flag = ti_sdo_ipc_MessageQ_registerTransport(
127         TransportCirc_Handle_upCast(obj), remoteProcId, params->priority);
129     if (flag == FALSE) {
130         Error_raise(eb, IpcMgr_E_internal, 0, 0);
131         return (2);
132     }
134     return (0);
137 /*
138  *  ======== TransportCirc_Instance_finalize ========
139  */
140 Void TransportCirc_Instance_finalize(TransportCirc_Object* obj, Int status)
142     Swi_Handle     swiHandle;
144     switch(status) {
145         case 0:
146             /* MessageQ_registerTransport succeeded */
147             ti_sdo_ipc_MessageQ_unregisterTransport(obj->remoteProcId,
148                 obj->priority);
150             /* OK to fall thru */
152         case 1: /* Notify_registerEventSingle failed */
154             /* OK to fall thru */
156         case 2: /* MessageQ_registerTransport failed */
157             Notify_unregisterEventSingle(
158                 obj->remoteProcId,
159                 0,
160                 TransportCirc_notifyEventId);
161             break;
162     }
164     /* Destruct the swi */
165     swiHandle = TransportCirc_Instance_State_swiObj(obj);
166     if (swiHandle != NULL) {
167         Swi_destruct(Swi_struct(swiHandle));
168     }
171 /*
172  *  ======== TransportCirc_put ========
173  *  Assuming MessageQ_put is making sure that the arguments are ok
174  */
175 Bool TransportCirc_put(TransportCirc_Object *obj, Ptr msg)
177     Int status;
178     UInt msgSize;
179     UInt hwiKey;
180     Ptr writeAddr;
181     UInt writeIndex, readIndex;
183     do {
184         /* disable interrupts */
185         hwiKey = Hwi_disable();
187         /* get the writeIndex and readIndex */
188         readIndex  = obj->putReadIndex[0];
189         writeIndex = obj->putWriteIndex[0];
191         /* if slot available 'break' out of loop */
192         if (((writeIndex + 1) & TransportCirc_maxIndex) != readIndex) {
193             break;
194         }
196         /* restore interrupts */
197         Hwi_restore(hwiKey);
199     } while (1);
201     /* interrupts are disabled at this point */
203     /* get a free buffer and copy the message into it */
204     writeAddr = (Ptr)((UInt32)obj->putBuffer +
205                 (writeIndex * TransportCirc_msgSize));
207     /* get the size of the message */
208     msgSize = MessageQ_getMsgSize(msg);
210     Assert_isTrue(msgSize <= TransportCirc_msgSize, IpcMgr_A_internal);
212     /* copy message to the write buffer */
213     memcpy(writeAddr, (Ptr)msg, msgSize);
215     /* update the writeIndex */
216     obj->putWriteIndex[0] = (writeIndex + 1) & TransportCirc_maxIndex;
218     /* restore interrupts */
219     Hwi_restore(hwiKey);
221     /* free the app's message */
222     if (((MessageQ_Msg)msg)->heapId != ti_sdo_ipc_MessageQ_STATICMSG) {
223         MessageQ_free(msg);
224     }
226     /* Notify the remote processor */
227     status = Notify_sendEvent(
228                  obj->remoteProcId,
229                  0,
230                  TransportCirc_notifyEventId,
231                  (UInt32)NULL,
232                  FALSE);
234     /* check the status of the sendEvent */
235     if (status < 0) {
236         return (FALSE);
237     }
239     return (TRUE);
242 /*
243  *  ======== TransportCirc_control ========
244  */
245 Bool TransportCirc_control(TransportCirc_Object *obj, UInt cmd,
246     UArg cmdArg)
248     return (FALSE);
251 /*
252  *  ======== TransportCirc_getStatus ========
253  */
254 Int TransportCirc_getStatus(TransportCirc_Object *obj)
256     return (0);
259 /*
260  *************************************************************************
261  *                       Module functions
262  *************************************************************************
263  */
265 /*
266  *  ======== TransportCirc_notifyFxn ========
267  */
268 Void TransportCirc_notifyFxn(UInt16 procId,
269                              UInt16 lineId,
270                              UInt32 eventId,
271                              UArg arg,
272                              UInt32 payload)
274     Swi_Handle swiHandle;
276     /* Swi_Handle was passed as arg in register */
277     swiHandle = (Swi_Handle)arg;
279     /* post the Swi */
280     Swi_post(swiHandle);
283 /*
284  *  ======== TransportCirc_swiFxn ========
285  */
286 Void TransportCirc_swiFxn(UArg arg)
288     UInt32 queueId;
289     TransportCirc_Object *obj = (TransportCirc_Object *)arg;
290     MessageQ_Msg msg = NULL;
291     MessageQ_Msg buf = NULL;
292     SizeT msgSize;
293     UInt writeIndex, readIndex;
294     UInt offset;
296     /* Make sure the TransportCirc_Object is not NULL */
297     Assert_isTrue(obj != NULL, IpcMgr_A_internal);
299     /* get the writeIndex and readIndex */
300     writeIndex = obj->getWriteIndex[0];
301     readIndex  = obj->getReadIndex[0];
303     while (writeIndex != readIndex) {
304         /* determine where the message from remote core is */
305         offset = (readIndex * TransportCirc_msgSize);
307         /* get the message */
308         msg = (MessageQ_Msg)((UInt32)obj->getBuffer + offset);
310 #ifdef xdc_target__isaCompatible_28
311         /*
312          *  The message size needs to be halved because it was
313          *  specified in bytes and the units on the c28 is 16-bit
314          *  words.
315          */
316         msgSize = MessageQ_getMsgSize(msg) >> 1;
317 #else
318         /*
319          *  The message size needs to be doubled because it was
320          *  specified in 16-bit words and the units on the m3 is
321          *  in bytes.
322          */
323         msgSize = MessageQ_getMsgSize(msg) << 1;
324 #endif
326         /* alloc a message from msg->heapId to copy the msg to */
327         buf = MessageQ_alloc(msg->heapId, msgSize);
329         /* Make sure buf is not NULL */
330         Assert_isTrue(buf != NULL, IpcMgr_A_internal);
332         /* copy the message to the buffer allocated, set the heap id */
333         memcpy((Ptr)buf, (Ptr)msg, msgSize);
335         /* overwrite the msgSize in the msg */
336         buf->msgSize = msgSize;
338         /* retrieve the detination queue id */
339         queueId = MessageQ_getDstQueue(msg);
341         /* put the message to the destination queue */
342         MessageQ_put(queueId, buf);
344         /* update the local readIndex. */
345         readIndex = ((readIndex + 1) & TransportCirc_maxIndex);
347         /* set the readIndex */
348         obj->getReadIndex[0] = readIndex;
349     }
352 /*
353  *************************************************************************
354  *                      Module functions
355  *************************************************************************
356  */
358 /*
359  *  ======== TransportCirc_close ========
360  */
361 Void TransportCirc_close(TransportCirc_Handle *handle)
363     TransportCirc_delete(handle);
366 /*
367  *  ======== TransportCirc_sharedMemReq ========
368  */
369 SizeT TransportCirc_sharedMemReq(const TransportCirc_Params *params)
371     SizeT memReq;
373     /* Ensure that params is non-NULL */
374     Assert_isTrue(params != NULL, IpcMgr_A_internal);
376     /*
377      *  Amount of shared memory:
378      *  1 putBuffer (msgSize * numMsgs) +
379      *  1 putWriteIndex ptr             +
380      *  1 putReadIndex ptr              +
381      */
382     memReq = (TransportCirc_msgSize * TransportCirc_numMsgs) +
383              (2 * sizeof(Bits32));
385     return (memReq);
388 /*
389  *  ======== TransportCirc_setErrFxn ========
390  */
391 Void TransportCirc_setErrFxn(TransportCirc_ErrFxn errFxn)
393     /* Ignore the errFxn */