]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - packages/ti/sdo/ipc/notifyDrivers/NotifyDriverShm.c
465638e5846e747b5336a6c10356c6756dd7d2b9
[ipc/ipcdev.git] / packages / ti / sdo / ipc / notifyDrivers / NotifyDriverShm.c
1 /*
2  * Copyright (c) 2012-2019, 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  *  ======== NotifyDriverShm.c ========
34  */
36 #include <xdc/std.h>
38 #include <xdc/runtime/Assert.h>
39 #include <xdc/runtime/Error.h>
40 #include <xdc/runtime/Memory.h>
41 #include <xdc/runtime/Startup.h>
43 #include <ti/sysbios/hal/Cache.h>
44 #include <ti/sysbios/hal/Hwi.h>
46 #include <ti/sdo/utils/List.h>
48 #include <ti/sdo/ipc/interfaces/INotifyDriver.h>
50 #include "package/internal/NotifyDriverShm.xdc.h"
52 #include <ti/sdo/ipc/_Ipc.h>
53 #include <ti/sdo/ipc/_Notify.h>
54 #include <ti/sdo/ipc/_SharedRegion.h>
55 #include <ti/sdo/utils/_MultiProc.h>
57 /* Bit mask operations */
58 #define SET_BIT(num,pos)            ((num) |= (1u << (pos)))
59 #define CLEAR_BIT(num,pos)          ((num) &= ~(1u << (pos)))
60 #define TEST_BIT(num,pos)           ((num) & (1u << (pos)))
62 #define EVENTENTRY(eventChart, entrySize, eventId) \
63             ((NotifyDriverShm_EventEntry *) \
64              ((UInt32)(eventChart) + ((entrySize) * (eventId))));
66 /*
67  **************************************************************
68  *                       Instance functions
69  **************************************************************
70  */
72 /*
73  *  ======== NotifyDriverShm_Instance_init ========
74  */
75 Int NotifyDriverShm_Instance_init(NotifyDriverShm_Object *obj,
76                                   const NotifyDriverShm_Params *params,
77                                   Error_Block *eb)
78 {
79     UInt16 regionId;
80     SizeT regionCacheSize, minAlign, procCtrlSize;
82    /*
83     * Check whether remote proc ID has been set and isn't the same as the
84     * local proc ID
85     */
86     Assert_isTrue ((params->remoteProcId != MultiProc_INVALIDID) &&
87                    (params->remoteProcId != MultiProc_self()),
88                    ti_sdo_ipc_Ipc_A_invParam);
90     /*
91      *  Determine obj->cacheEnabled using params->cacheEnabled and SharedRegion
92      *  cache flag setting, if applicable.
93      */
94     obj->cacheEnabled = params->cacheEnabled;
95     minAlign = params->cacheLineSize;
96     if (minAlign == 0) {
97         /* Fix alignment of zero */
98         minAlign = sizeof(Ptr);
99     }
100     regionId = SharedRegion_getId(params->sharedAddr);
101     if (regionId != SharedRegion_INVALIDREGIONID) {
102         /*
103          *  Override the user cacheEnabled setting if the region
104          *  cacheEnabled is FALSE.
105          */
106         if (!SharedRegion_isCacheEnabled(regionId)) {
107             obj->cacheEnabled = FALSE;
108         }
110         regionCacheSize = SharedRegion_getCacheLineSize(regionId);
112         /*
113          *  Override the user cache line size setting if the region
114          *  cache line size is smaller.
115          */
116         if (regionCacheSize < minAlign) {
117             minAlign = regionCacheSize;
118         }
119     }
121     /* Check if shared memory base addr is aligned to cache line boundary.*/
122     Assert_isTrue ((UInt32)params->sharedAddr % minAlign == 0,
123         ti_sdo_ipc_Ipc_A_addrNotCacheAligned);
125     obj->remoteProcId           = params->remoteProcId;
127     /*
128      *  Store all interrupt information so it may be used (if neccessary) by
129      *  the IInterrupt delegates
130      */
131     obj->intInfo.remoteIntId    = params->remoteIntId;
132     obj->intInfo.localIntId     = params->localIntId;
133     obj->intInfo.intVectorId    = params->intVectorId;
135     obj->nesting            = 0;
137     if (params->remoteProcId > MultiProc_self()) {
138         obj->selfId  = 0;
139         obj->otherId = 1;
140     }
141     else {
142         obj->selfId  = 1;
143         obj->otherId = 0;
144     }
146     /* Initialize pointers to shared memory regions */
147     procCtrlSize = _Ipc_roundup(sizeof(NotifyDriverShm_ProcCtrl), minAlign);
149     /*
150      *  Save the eventEntrySize in obj since we will need it at runtime to
151      *  index the event charts
152      */
153     obj->eventEntrySize = _Ipc_roundup(sizeof(NotifyDriverShm_EventEntry),
154         minAlign);
156     obj->selfProcCtrl = (NotifyDriverShm_ProcCtrl *)
157         ((UInt32)params->sharedAddr + (obj->selfId * procCtrlSize));
158     obj->otherProcCtrl = (NotifyDriverShm_ProcCtrl *)
159         ((UInt32)params->sharedAddr + (obj->otherId * procCtrlSize));
160     obj->selfEventChart  = (NotifyDriverShm_EventEntry *)
161         ((UInt32)params->sharedAddr
162          + (2 * procCtrlSize)
163          + (obj->eventEntrySize * ti_sdo_ipc_Notify_numEvents * obj->selfId));
164     obj->otherEventChart  = (NotifyDriverShm_EventEntry *)
165          ((UInt32)params->sharedAddr
166          + (2 * procCtrlSize)
167          + (obj->eventEntrySize * ti_sdo_ipc_Notify_numEvents * obj->otherId));
169     /* Allocate memory for regChart and init to (UInt32)-1 (unregistered) */
170     obj->regChart = Memory_valloc(
171             NotifyDriverShm_Object_heap(),
172             (sizeof(UInt32) * ti_sdo_ipc_Notify_numEvents),
173             0,
174             ~0,
175             eb);
176     if (obj->regChart == NULL) {
177         return (1);
178     }
180     /* Enable all events initially.*/
181     obj->selfProcCtrl->eventEnableMask = 0xFFFFFFFF;
183     /* Write back our own ProcCtrl */
184     if (obj->cacheEnabled) {
185         Cache_wbInv(obj->selfProcCtrl, sizeof(NotifyDriverShm_ProcCtrl),
186             Cache_Type_ALL, TRUE);
187     }
189     /* Register the incoming interrupt */
190     NotifyDriverShm_InterruptProxy_intRegister(obj->remoteProcId,
191         &(obj->intInfo), (Fxn)NotifyDriverShm_isr, (UArg)obj);
193     return (0);
196 /*
197  *  ======== NotifyDriverShm_Instance_finalize ========
198  */
199 Void NotifyDriverShm_Instance_finalize(NotifyDriverShm_Object *obj, int status)
201     if (status == 0) {
202         /* Indicate that driver is no longer ready to send/receive events */
203         obj->selfProcCtrl->recvInitStatus = 0;
204         obj->selfProcCtrl->sendInitStatus = 0;
206         Cache_wbInv(obj->selfProcCtrl, sizeof(NotifyDriverShm_ProcCtrl),
207             Cache_Type_ALL, TRUE);
209         /* Unregister interrupt */
210         NotifyDriverShm_InterruptProxy_intUnregister(obj->remoteProcId,
211             &(obj->intInfo));
213         /* Free memory alloc'ed for regChart */
214         Memory_free(NotifyDriverShm_Object_heap(), obj->regChart,
215             sizeof(UInt32) * ti_sdo_ipc_Notify_numEvents);
216     }
219 /*
220  *  ======== NotifyDriverShm_registerEvent ========
221  */
222 Void NotifyDriverShm_registerEvent(NotifyDriverShm_Object *obj,
223                                    UInt32 eventId)
225     NotifyDriverShm_EventEntry *eventEntry;
226     Int i, j;
228     /*
229      *  Disable interrupt line to ensure that NotifyDriverShm_isr doesn't
230      *  preempt registerEvent and encounter corrupt state
231      */
232     NotifyDriverShm_disable(obj);
234     /*
235      *  Add an entry for the registered event into the Event Registration
236      *  Chart, in ascending order of event numbers (and decreasing
237      *  priorities).
238      */
239     for (i = 0; i < (Int)ti_sdo_ipc_Notify_numEvents; i++) {
240         /* Find the correct slot in the registration array.*/
241         if (obj->regChart[i] == (UInt32)-1) {
242             for (j = i - 1; j >= 0; j--) {
243                 if (eventId < obj->regChart[j]) {
244                     obj->regChart[j + 1] = obj->regChart[j];
245                     i = j;
246                 }
247                 else {
248                     /* End the loop, slot found.*/
249                     j = -1;
250                 }
251             }
252             obj->regChart[i] = eventId;
253             break;
254         }
255     }
257     /*
258      *  Clear any pending unserviced event as there are no listeners
259      *  for the pending event
260      */
261     eventEntry = EVENTENTRY(obj->selfEventChart, obj->eventEntrySize, eventId)
262     eventEntry->flag = NotifyDriverShm_DOWN;
263     if (obj->cacheEnabled) {
264         Cache_wbInv(eventEntry, sizeof(NotifyDriverShm_EventEntry),
265                     Cache_Type_ALL, TRUE);
266     }
268     /* Set the 'registered' bit in shared memory and write back */
269     SET_BIT(obj->selfProcCtrl->eventRegMask, eventId);
270     if (obj->cacheEnabled) {
271         Cache_wbInv(obj->selfProcCtrl, sizeof(NotifyDriverShm_ProcCtrl),
272                     Cache_Type_ALL, TRUE);
273     }
275     /* Restore the interrupt line */
276     NotifyDriverShm_enable(obj);
279 /*
280  *  ======== NotifyDriverShm_unregisterEvent ========
281  */
282 Void NotifyDriverShm_unregisterEvent(NotifyDriverShm_Object *obj,
283                                      UInt32 eventId)
285     NotifyDriverShm_EventEntry *eventEntry;
286     UInt i, j;
288     /*
289      *  Disable interrupt line to ensure that NotifyDriverShm_isr doesn't
290      *  preempt registerEvent and encounter corrupt state
291      */
292     NotifyDriverShm_disable(obj);
294     /*
295      *  First unset the registered bit in shared memory so no notifications
296      *  arrive after this point
297      */
298     CLEAR_BIT(obj->selfProcCtrl->eventRegMask, eventId);
299     if (obj->cacheEnabled) {
300         Cache_wbInv(obj->selfProcCtrl, sizeof(NotifyDriverShm_ProcCtrl),
301                     Cache_Type_ALL, TRUE);
302     }
304     /*
305      *  Clear any pending unserviced event as there are no listeners
306      *  for the pending event.  This should be done only after the event
307      *  is unregistered from shared memory so the other processor doesn't
308      *  successfully send an event our way immediately after unflagging this
309      *  event.
310      */
311     eventEntry = EVENTENTRY(obj->selfEventChart, obj->eventEntrySize, eventId);
312     eventEntry->flag = NotifyDriverShm_DOWN;
314     /* Write back both the flag and the reg mask */
315     if (obj->cacheEnabled) {
316         Cache_wbInv(eventEntry, sizeof(NotifyDriverShm_EventEntry),
317                     Cache_Type_ALL, TRUE);
318     }
320     /*
321      *  Re-arrange eventIds in the Event Registration Chart so there is
322      *  no gap caused by the removal of this eventId
323      *
324      *  There is no need to make this atomic since Notify_exec cannot preempt:
325      *  the event has already been disabled in shared memory (see above)
326      */
327     for (i = 0; i < ti_sdo_ipc_Notify_numEvents; i++) {
328         if (eventId == obj->regChart[i]) {
329             obj->regChart[i] = (UInt32)-1;
330             for (j = i + 1; (j != ti_sdo_ipc_Notify_numEvents) &&
331                     (obj->regChart[j] != (UInt32)-1); j++) {
332                 obj->regChart[j - 1] = obj->regChart[j];
333                 obj->regChart[j] = (UInt32)-1;
334             }
335             break;
336         }
337     }
339     /* Restore the interrupt line */
340     NotifyDriverShm_enable(obj);
343 /*
344  *  ======== NotifyDriverShm_sendEvent ========
345  */
346 Int NotifyDriverShm_sendEvent(NotifyDriverShm_Object *obj,
347                               UInt32                 eventId,
348                               UInt32                 payload,
349                               Bool                   waitClear)
351     NotifyDriverShm_EventEntry *eventEntry;
352     UInt32 i;
353     UInt sysKey;
355     eventEntry = EVENTENTRY(obj->otherEventChart, obj->eventEntrySize, eventId);
357     /* Check whether driver on other processor is initialized */
358     if (obj->cacheEnabled) {
359         Cache_inv(obj->otherProcCtrl, sizeof(NotifyDriverShm_ProcCtrl),
360                   Cache_Type_ALL, TRUE);
361     }
363     if (obj->otherProcCtrl->recvInitStatus != NotifyDriverShm_INIT_STAMP) {
364         /*
365          * This may be used for polling till the other driver is ready, so
366          * do not assert or error
367          */
368         return (Notify_E_NOTINITIALIZED);
369     }
371     /* Check to see if the remote event is enabled */
372     if (!TEST_BIT(obj->otherProcCtrl->eventEnableMask, eventId)) {
373         return (Notify_E_EVTDISABLED);
374     }
376     /* Check to see if the remote event is registered */
377     if (!TEST_BIT(obj->otherProcCtrl->eventRegMask, eventId)) {
378         return (Notify_E_EVTNOTREGISTERED);
379     }
382     if (waitClear) {
383         i = 0;
385         if (obj->cacheEnabled) {
386             Cache_inv(eventEntry, sizeof(NotifyDriverShm_EventEntry),
387                 Cache_Type_ALL, TRUE);
388         }
390         /*
391          *  The system gate is needed to ensure that checking eventEntry->flag
392          *  is atomic with the eventEntry modifications (flag/payload).
393          */
394         sysKey = Hwi_disable();
396         /* Wait for completion of previous event from other side. */
397         while ((eventEntry->flag != NotifyDriverShm_DOWN)) {
398             /*
399              * Leave critical section protection. Create a window
400              * of opportunity for other interrupts to be handled.
401              */
402             Hwi_restore(sysKey);
403             i++;
404             if ((i != (UInt32)-1) &&
405                 (i == ti_sdo_ipc_Notify_sendEventPollCount)) {
406                 return (Notify_E_TIMEOUT);
407             }
409             if (obj->cacheEnabled) {
410                 Cache_inv(eventEntry, sizeof(NotifyDriverShm_EventEntry),
411                     Cache_Type_ALL, TRUE);
412             }
414             /* Re-enter the system gate */
415             sysKey = Hwi_disable();
416         }
417     }
418     else {
419         /*
420          *  The system gate is needed to ensure that checking eventEntry->flag
421          *  is atomic with the eventEntry modifications (flag/payload).
422          */
423         sysKey = Hwi_disable();
424     }
426     /* Set the event bit field and payload.*/
427     eventEntry->payload = payload;
428     eventEntry->flag    = NotifyDriverShm_UP;
429     if (obj->cacheEnabled) {
430         Cache_wbInv(eventEntry, sizeof(NotifyDriverShm_EventEntry),
431             Cache_Type_ALL, TRUE);
432     }
434     /* Send an interrupt to the Remote Processor */
435     NotifyDriverShm_InterruptProxy_intSend(obj->remoteProcId, &(obj->intInfo),
436                                            eventId);
438     /* must not restore interrupts before sending the interrupt */
439     Hwi_restore(sysKey);
441     return (Notify_S_SUCCESS);
444 /*
445  *  ======== NotifyDriverShm_disable ========
446  */
447 Void NotifyDriverShm_disable(NotifyDriverShm_Object *obj)
449     /* Disable the incoming interrupt line */
450     NotifyDriverShm_InterruptProxy_intDisable(obj->remoteProcId,
451                                               &(obj->intInfo));
454 /*
455  *  ======== NotifyDriverShm_enable ========
456  */
457 Void NotifyDriverShm_enable(NotifyDriverShm_Object *obj)
459     /* Enable the incoming interrupt line */
460     NotifyDriverShm_InterruptProxy_intEnable(obj->remoteProcId,
461                                              &(obj->intInfo));
464 /*
465  *  ======== NotifyDriverShm_disableEvent ========
466  */
467 Void NotifyDriverShm_disableEvent(NotifyDriverShm_Object *obj, UInt32 eventId)
469     UInt sysKey;
470     NotifyDriverShm_EventEntry *eventEntry;
472     Assert_isTrue(eventId < ti_sdo_ipc_Notify_numEvents,
473             ti_sdo_ipc_Ipc_A_invArgument);
475     /*
476      *  Atomically unset the corresponding bit in the processor's
477      *  eventEnableMask
478      */
479     sysKey = Hwi_disable();
480     CLEAR_BIT(obj->selfProcCtrl->eventEnableMask, eventId);
481     Hwi_restore(sysKey);
482     if (obj->cacheEnabled) {
483         Cache_wbInv(obj->selfProcCtrl, sizeof(NotifyDriverShm_ProcCtrl),
484             Cache_Type_ALL, TRUE);
485     }
487     eventEntry = EVENTENTRY(obj->selfEventChart, obj->eventEntrySize,
488             eventId);
489     if (obj->cacheEnabled) {
490         Cache_inv(eventEntry,
491                   sizeof(NotifyDriverShm_EventEntry),
492                   Cache_Type_ALL, TRUE);
493     }
495     /*
496      *  Disable incoming Notify interrupts.  This is done to ensure that the
497      *  eventEntry->flag is read atomically with any write back to shared
498      *  memory
499      */
500     NotifyDriverShm_disable(obj);
502     /*
503      *  Is the local NotifyDriverShm_disableEvent happening between the
504      *  following two NotifyDriverShm_sendEvent operations on the remote
505      *  processor?
506      *  1. Writing NotifyDriverShm_UP to shared memory
507      *  2. Sending the interrupt across
508      *  If so, we should handle this event so the other core isn't left spinning
509      *  until the event is re-enabled and the next NotifyDriverShm_isr executes
510      *  This race condition is very rare but we need to account for it:
511      */
512     if (eventEntry->flag == NotifyDriverShm_UP) {
513         /*
514          *  Acknowledge the event. No need to store the payload. The other side
515          *  will not send this event again even though flag is down, because the
516          *  event is now disabled. So the payload within the eventChart will not
517          *  get overwritten.
518          */
519         eventEntry->flag = NotifyDriverShm_DOWN;
521         /* Write back acknowledgement */
522         if (obj->cacheEnabled) {
523             Cache_wbInv(eventEntry, sizeof(NotifyDriverShm_EventEntry),
524                 Cache_Type_ALL, TRUE);
525         }
527         /*
528          *  Execute the callback function. This will execute in a Task
529          *  or Swi context (not Hwi!)
530          */
531         ti_sdo_ipc_Notify_exec(obj->notifyHandle, eventId, eventEntry->payload);
532     }
534     /* Re-enable incoming Notify interrupts */
535     NotifyDriverShm_enable(obj);
538 /*
539  *  ======== NotifyDriverShm_enableEvent ========
540  */
541 Void NotifyDriverShm_enableEvent(NotifyDriverShm_Object *obj, UInt32 eventId)
543     UInt sysKey;
545     Assert_isTrue(eventId < ti_sdo_ipc_Notify_numEvents,
546             ti_sdo_ipc_Ipc_A_invArgument);
548     /*
549      * Atomically set the corresponding bit in the processor's
550      * eventEnableMask
551      */
552     sysKey = Hwi_disable();
553     SET_BIT(obj->selfProcCtrl->eventEnableMask, eventId);
554     Hwi_restore(sysKey);
556     if (obj->cacheEnabled) {
557         Cache_wbInv(obj->selfProcCtrl, sizeof(NotifyDriverShm_ProcCtrl),
558             Cache_Type_ALL, TRUE);
559     }
562 /*
563  *************************************************************************
564  *                       Module functions
565  *************************************************************************
566  */
568 /*
569  *  ======== NotifyDriverShm_sharedMemReq ========
570  */
571 SizeT NotifyDriverShm_sharedMemReq(const NotifyDriverShm_Params *params)
573     UInt16 regionId;
574     SizeT regionCacheSize;
575     SizeT minAlign, memReq;
577     /* Ensure that params is non-NULL */
578     Assert_isTrue(params != NULL, ti_sdo_ipc_Ipc_A_internal);
580     /*
581      *  Determine obj->cacheEnabled using params->cacheEnabled and SharedRegion
582      *  cache flag setting, if applicable.
583      */
584     minAlign = params->cacheLineSize;
585     if (minAlign == 0) {
586         /* Fix alignment of zero */
587         minAlign = sizeof(Ptr);
588     }
589     regionId = SharedRegion_getId(params->sharedAddr);
590     if (regionId != SharedRegion_INVALIDREGIONID) {
591         regionCacheSize = SharedRegion_getCacheLineSize(regionId);
592         /* Override minAlign if the region cache line size is smaller */
593         if (regionCacheSize < minAlign) {
594             minAlign = regionCacheSize;
595         }
596     }
598     /* Determine obj->align which will be used to _Ipc_roundup addresses */
599     memReq = ((_Ipc_roundup(sizeof(NotifyDriverShm_ProcCtrl), minAlign)) * 2)
600            + ((_Ipc_roundup(sizeof(NotifyDriverShm_EventEntry), minAlign) * 2
601               * ti_sdo_ipc_Notify_numEvents));
603     return (memReq);
606 /*
607  *************************************************************************
608  *                       Internal functions
609  *************************************************************************
610  */
612 /*
613  *  ======== NotifyDriverShm_isr ========
614  */
615 Void NotifyDriverShm_isr(UArg arg)
617     UInt                            i;
618     NotifyDriverShm_EventEntry      *eventEntry;
619     NotifyDriverShm_Object          *obj;
620     UInt32                          eventId;
621     UInt32                          payload;
623     obj = (NotifyDriverShm_Object *)arg;
625     /* Make sure the NotifyDriverShm_Object is not NULL */
626     Assert_isTrue(obj != NULL, ti_sdo_ipc_Ipc_A_internal);
628     /* Clear the remote interrupt */
629     NotifyDriverShm_InterruptProxy_intClear(obj->remoteProcId,
630                                             &(obj->intInfo));
632     /*
633      * Iterate till no asserted event is found for one complete loop
634      * through all registered events.
635      */
636     i = 0;
637     do {
638         eventId = obj->regChart[i];
640         /* Check if the entry is a valid registered event. */
641         if (eventId != (UInt32)-1) {
642             /*
643              *  Check whether the event is disabled. If so, avoid the
644              *  unnecessary Cache invalidate. NOTE: selfProcCtrl does not have
645              *  to be cache-invalidated because:
646              *  1) Whenever self is written to by the local processor its memory
647              *     is also invalidated
648              *  2) 'selfProcCtrl' is never written to by the remote processor
649              */
650             if (!TEST_BIT(obj->selfProcCtrl->eventEnableMask,
651                 (UInt32)eventId)) {
652                 i++;
653                 continue;
654             }
656             eventEntry = EVENTENTRY(obj->selfEventChart, obj->eventEntrySize,
657                 eventId);
659             if (obj->cacheEnabled) {
660                 Cache_inv(eventEntry,
661                           sizeof(NotifyDriverShm_EventEntry),
662                           Cache_Type_ALL, TRUE);
663             }
665             /* Check if the event is set */
666             if (eventEntry->flag == NotifyDriverShm_UP) {
667                 /*
668                  *  Save the payload since it may be overwritten before
669                  *  Notify_exec is called
670                  */
671                 payload = eventEntry->payload;
673                 /* Acknowledge the event. */
674                 eventEntry->flag = NotifyDriverShm_DOWN;
676                 /* Write back acknowledgement */
677                 if (obj->cacheEnabled) {
678                     Cache_wbInv(eventEntry, sizeof(NotifyDriverShm_EventEntry),
679                         Cache_Type_ALL, TRUE);
680                 }
682                 /* Execute the callback function */
683                 ti_sdo_ipc_Notify_exec(obj->notifyHandle, eventId, payload);
685                 /* reinitialize the event check counter. */
686                 i = 0;
687             }
688             else {
689                 /* check for next event. */
690                 i++;
691             }
692         }
693     }
694     while ((eventId != (UInt32)-1) && (i < ti_sdo_ipc_Notify_numEvents));
697 /*
698  *  ======== NotifyDriverShm_setNotifyHandle ========
699  */
700 Void NotifyDriverShm_setNotifyHandle(NotifyDriverShm_Object *obj,
701                                      Ptr notifyHandle)
703     /* Internally used, so no Assert needed */
704     obj->notifyHandle = (ti_sdo_ipc_Notify_Handle)notifyHandle;
706     /* Indicate that the driver is initialized for this processor */
707     obj->selfProcCtrl->recvInitStatus = NotifyDriverShm_INIT_STAMP;
708     obj->selfProcCtrl->sendInitStatus = NotifyDriverShm_INIT_STAMP;
710     /* Write back our own ProcCtrl */
711     if (obj->cacheEnabled) {
712         Cache_wbInv(obj->selfProcCtrl, sizeof(NotifyDriverShm_ProcCtrl),
713             Cache_Type_ALL, TRUE);
714     }