Add defaultErrFxn and an err fxn to module state
[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>
45 #include <ti/sdo/ipc/interfaces/IMessageQTransport.h>
47 #include <ti/sdo/ipc/family/f28m35x/IpcMgr.h>
49 #include "package/internal/TransportCirc.xdc.h"
51 #include <ti/sdo/utils/_MultiProc.h>
52 #include <ti/sdo/ipc/_Notify.h>
53 #include <ti/sdo/ipc/_MessageQ.h>
55 /* Need to use reserved notify events */
56 #undef TransportCirc_notifyEventId
57 #define TransportCirc_notifyEventId \
58     ti_sdo_ipc_family_f28m35x_TransportCirc_notifyEventId + \
59     (UInt32)((UInt32)Notify_SYSTEMKEY << 16)
61 /*
62  *************************************************************************
63  *                       Instance functions
64  *************************************************************************
65  */
67 /*
68  *  ======== TransportCirc_Instance_init ========
69  */
70 Int TransportCirc_Instance_init(TransportCirc_Object *obj,
71         UInt16 remoteProcId, const TransportCirc_Params *params,
72         Error_Block *eb)
73 {
74     Int        status;
75     Bool       flag;
76     Swi_Handle swiHandle;
77     Swi_Params swiParams;
78     SizeT      circBufSize;
80     swiHandle = TransportCirc_Instance_State_swiObj(obj);
82     /* init the object fields */
83     obj->priority     = params->priority;
84     obj->remoteProcId = remoteProcId;
86     /* construct the swi with lowest priority */
87     Swi_Params_init(&swiParams);
88     swiParams.arg0 = (UArg)obj;
89     swiParams.priority = params->swiPriority;
90     Swi_construct(Swi_struct(swiHandle),
91                  (Swi_FuncPtr)TransportCirc_swiFxn,
92                  &swiParams, eb);
94     /* calculate the circular buffer size one-way */
95     circBufSize = TransportCirc_msgSize * TransportCirc_numMsgs;
97     /* Init put/get buffer and index pointers. */
98     obj->putBuffer = params->writeAddr;
100     obj->putWriteIndex = (Bits32 *)((UInt32)obj->putBuffer + circBufSize);
102     obj->getBuffer = params->readAddr;
104     obj->getWriteIndex = (Bits32 *)((UInt32)obj->getBuffer + circBufSize);
106     obj->putReadIndex = (Bits32 *)((UInt32)obj->getWriteIndex + sizeof(Bits32));
108     obj->getReadIndex = (Bits32 *)((UInt32)obj->putWriteIndex + sizeof(Bits32));
110     /* init the putWrite and getRead Index to 0 */
111     obj->putWriteIndex[0] = 0;
112     obj->getReadIndex[0] = 0;
114     /* register the event with Notify */
115     status = Notify_registerEventSingle(
116                  remoteProcId,    /* remoteProcId */
117                  0,         /* lineId */
118                  TransportCirc_notifyEventId,
119                  (Notify_FnNotifyCbck)TransportCirc_notifyFxn,
120                  (UArg)swiHandle);
122     if (status < 0) {
123         Error_raise(eb, IpcMgr_E_internal, 0, 0);
124         return (1);
125     }
127     /* Register the transport with MessageQ */
128     flag = ti_sdo_ipc_MessageQ_registerTransport(
129         TransportCirc_Handle_upCast(obj), remoteProcId, params->priority);
131     if (flag == FALSE) {
132         Error_raise(eb, IpcMgr_E_internal, 0, 0);
133         return (2);
134     }
136     return (0);
139 /*
140  *  ======== TransportCirc_Instance_finalize ========
141  */
142 Void TransportCirc_Instance_finalize(TransportCirc_Object* obj, Int status)
144     Swi_Handle     swiHandle;
146     switch(status) {
147         case 0:
148             /* MessageQ_registerTransport succeeded */
149             ti_sdo_ipc_MessageQ_unregisterTransport(obj->remoteProcId,
150                 obj->priority);
152             /* OK to fall thru */
154         case 1: /* Notify_registerEventSingle failed */
156             /* OK to fall thru */
158         case 2: /* MessageQ_registerTransport failed */
159             Notify_unregisterEventSingle(
160                 obj->remoteProcId,
161                 0,
162                 TransportCirc_notifyEventId);
163             break;
164     }
166     /* Destruct the swi */
167     swiHandle = TransportCirc_Instance_State_swiObj(obj);
168     if (swiHandle != NULL) {
169         Swi_destruct(Swi_struct(swiHandle));
170     }
173 /*
174  *  ======== TransportCirc_put ========
175  *  Assuming MessageQ_put is making sure that the arguments are ok
176  */
177 Bool TransportCirc_put(TransportCirc_Object *obj, Ptr msg)
179     Int status;
180     UInt msgSize;
181     UInt hwiKey;
182     Ptr writeAddr;
183     UInt writeIndex, readIndex;
185     do {
186         /* disable interrupts */
187         hwiKey = Hwi_disable();
189         /* get the writeIndex and readIndex */
190         readIndex  = obj->putReadIndex[0];
191         writeIndex = obj->putWriteIndex[0];
193         /* if slot available 'break' out of loop */
194         if (((writeIndex + 1) & TransportCirc_maxIndex) != readIndex) {
195             break;
196         }
198         /* restore interrupts */
199         Hwi_restore(hwiKey);
201     } while (1);
203     /* interrupts are disabled at this point */
205     /* get a free buffer and copy the message into it */
206     writeAddr = (Ptr)((UInt32)obj->putBuffer +
207                 (writeIndex * TransportCirc_msgSize));
209     /* get the size of the message */
210     msgSize = MessageQ_getMsgSize(msg);
212     Assert_isTrue(msgSize <= TransportCirc_msgSize, IpcMgr_A_internal);
214     /* copy message to the write buffer */
215     memcpy(writeAddr, (Ptr)msg, msgSize);
217     /* update the writeIndex */
218     obj->putWriteIndex[0] = (writeIndex + 1) & TransportCirc_maxIndex;
220     /* restore interrupts */
221     Hwi_restore(hwiKey);
223     /* free the app's message */
224     if (((MessageQ_Msg)msg)->heapId != ti_sdo_ipc_MessageQ_STATICMSG) {
225         MessageQ_free(msg);
226     }
228     /* Notify the remote processor */
229     status = Notify_sendEvent(
230                  obj->remoteProcId,
231                  0,
232                  TransportCirc_notifyEventId,
233                  (UInt32)NULL,
234                  FALSE);
236     /* check the status of the sendEvent */
237     if (status < 0) {
238         return (FALSE);
239     }
241     return (TRUE);
244 /*
245  *  ======== TransportCirc_control ========
246  */
247 Bool TransportCirc_control(TransportCirc_Object *obj, UInt cmd,
248     UArg cmdArg)
250     return (FALSE);
253 /*
254  *  ======== TransportCirc_getStatus ========
255  */
256 Int TransportCirc_getStatus(TransportCirc_Object *obj)
258     return (0);
261 /*
262  *************************************************************************
263  *                       Module functions
264  *************************************************************************
265  */
267 /*
268  *  ======== TransportCirc_notifyFxn ========
269  */
270 Void TransportCirc_notifyFxn(UInt16 procId,
271                              UInt16 lineId,
272                              UInt32 eventId,
273                              UArg arg,
274                              UInt32 payload)
276     Swi_Handle swiHandle;
278     /* Swi_Handle was passed as arg in register */
279     swiHandle = (Swi_Handle)arg;
281     /* post the Swi */
282     Swi_post(swiHandle);
285 /*
286  *  ======== TransportCirc_swiFxn ========
287  */
288 Void TransportCirc_swiFxn(UArg arg)
290     UInt32 queueId;
291     TransportCirc_Object *obj = (TransportCirc_Object *)arg;
292     MessageQ_Msg msg = NULL;
293     MessageQ_Msg buf = NULL;
294     SizeT msgSize;
295     UInt writeIndex, readIndex;
296     UInt offset;
298     /* Make sure the TransportCirc_Object is not NULL */
299     Assert_isTrue(obj != NULL, IpcMgr_A_internal);
301     /* get the writeIndex and readIndex */
302     writeIndex = obj->getWriteIndex[0];
303     readIndex  = obj->getReadIndex[0];
305     while (writeIndex != readIndex) {
306         /* determine where the message from remote core is */
307         offset = (readIndex * TransportCirc_msgSize);
309         /* get the message */
310         msg = (MessageQ_Msg)((UInt32)obj->getBuffer + offset);
312 #ifdef xdc_target__isaCompatible_28
313         /*
314          *  The message size needs to be halved because it was
315          *  specified in bytes and the units on the c28 is 16-bit
316          *  words.
317          */
318         msgSize = MessageQ_getMsgSize(msg) >> 1;
319 #else
320         /*
321          *  The message size needs to be doubled because it was
322          *  specified in 16-bit words and the units on the m3 is
323          *  in bytes.
324          */
325         msgSize = MessageQ_getMsgSize(msg) << 1;
326 #endif
328         /* alloc a message from msg->heapId to copy the msg to */
329         buf = MessageQ_alloc(msg->heapId, msgSize);
331         /* Make sure buf is not NULL */
332         if (buf == NULL) {
333             TransportCirc_module->errFxn(TransportCirc_Reason_FAILEDALLOC,
334                 ti_sdo_ipc_family_f28m35x_TransportCirc_Handle_upCast(obj),
335                 NULL,
336                 (UArg)msg);
338             return;
339         }
341         /* copy the message to the buffer allocated, set the heap id */
342         memcpy((Ptr)buf, (Ptr)msg, msgSize);
344         /* overwrite the msgSize in the msg */
345         buf->msgSize = msgSize;
347         /* retrieve the detination queue id */
348         queueId = MessageQ_getDstQueue(msg);
350         /* put the message to the destination queue */
351         MessageQ_put(queueId, buf);
353         /* update the local readIndex. */
354         readIndex = ((readIndex + 1) & TransportCirc_maxIndex);
356         /* set the readIndex */
357         obj->getReadIndex[0] = readIndex;
358     }
361 /*
362  *************************************************************************
363  *                      Module functions
364  *************************************************************************
365  */
367 /*
368  *  ======== TransportCirc_close ========
369  */
370 Void TransportCirc_close(TransportCirc_Handle *handle)
372     TransportCirc_delete(handle);
375 /*
376  *  ======== TransportCirc_sharedMemReq ========
377  */
378 SizeT TransportCirc_sharedMemReq(const TransportCirc_Params *params)
380     SizeT memReq;
382     /* Ensure that params is non-NULL */
383     Assert_isTrue(params != NULL, IpcMgr_A_internal);
385     /*
386      *  Amount of shared memory:
387      *  1 putBuffer (msgSize * numMsgs) +
388      *  1 putWriteIndex ptr             +
389      *  1 putReadIndex ptr              +
390      */
391     memReq = (TransportCirc_msgSize * TransportCirc_numMsgs) +
392              (2 * sizeof(Bits32));
394     return (memReq);
397 /*
398  *  ======== TransportCirc_defaultErrFxn ========
399  */
400 Void TransportCirc_defaultErrFxn(IMessageQTransport_Reason reason,
401                                  IMessageQTransport_Handle handle,
402                                  Ptr ptr,
403                                  UArg arg)
407 /*
408  *  ======== TransportCirc_setErrFxn ========
409  */
410 Void TransportCirc_setErrFxn(TransportCirc_ErrFxn errFxn)
412     TransportCirc_module->errFxn = errFxn;