/* * ======== Notify_eventAvailable ======== */ Bool Notify_eventAvailable(UInt16 procId, UInt16 lineId, UInt32 eventId) { UInt32 strippedEventId = (eventId & 0xFFFF); UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(procId); Bool available; ti_sdo_ipc_Notify_Object *obj; Assert_isTrue(procId < ti_sdo_utils_MultiProc_numProcessors && lineId < ti_sdo_ipc_Notify_numLines, ti_sdo_ipc_Notify_A_invArgument); Assert_isTrue(strippedEventId < ti_sdo_ipc_Notify_numEvents, ti_sdo_ipc_Notify_A_invArgument); obj = (ti_sdo_ipc_Notify_Object *) Notify_module->notifyHandles[clusterId][lineId]; if (obj == NULL) { /* Driver not registered */ return (FALSE); } if (!ISRESERVED(eventId)) { /* Event is reserved and the caller isn't using Notify_SYSTEMKEY */ return (FALSE); } available = (obj->callbacks[strippedEventId].fnNotifyCbck == NULL); return (available); }
/* * ======== ti_sdo_ipc_Notify_Instance_finalize ======== */ Void ti_sdo_ipc_Notify_Instance_finalize(ti_sdo_ipc_Notify_Object *obj, Int status) { UInt i; UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(obj->remoteProcId); switch (status) { case 0: /* Unregister the notify instance from the Notify module */ Notify_module->notifyHandles[clusterId][obj->lineId] = NULL; /* Destruct the event lists */ for (i = 0; i < ti_sdo_ipc_Notify_numEvents; i++) { List_destruct(List_struct(List_Object_get(obj->eventList, i))); } /* Free memory used for the List.Objects */ Memory_free(ti_sdo_ipc_Notify_Object_heap(), obj->eventList, sizeof(List_Struct) * ti_sdo_ipc_Notify_numEvents); /* OK to fall through */ case 1: /* Free memory used for callbacks array */ Memory_free(ti_sdo_ipc_Notify_Object_heap(), obj->callbacks, sizeof(ti_sdo_ipc_Notify_EventCallback) * ti_sdo_ipc_Notify_numEvents); } }
/* * ======== Notify_disable ======== */ UInt Notify_disable(UInt16 procId, UInt16 lineId) { UInt key; UInt modKey; UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(procId); ti_sdo_ipc_Notify_Object *obj; Assert_isTrue(procId < ti_sdo_utils_MultiProc_numProcessors && lineId < ti_sdo_ipc_Notify_numLines, ti_sdo_ipc_Notify_A_invArgument); obj = (ti_sdo_ipc_Notify_Object *) Notify_module->notifyHandles[clusterId][lineId]; Assert_isTrue(obj != NULL, ti_sdo_ipc_Notify_A_notRegistered); /* Nesting value and enable state have to be in sync */ modKey = Gate_enterModule(); obj->nesting++; if (obj->nesting == 1) { /* Disable receiving all events */ if (procId != MultiProc_self()) { INotifyDriver_disable(obj->driverHandle); } } key = obj->nesting; Gate_leaveModule(modKey); return (key); }
/* * ======== Notify_restore ======== */ Void Notify_restore(UInt16 procId, UInt16 lineId, UInt key) { UInt modKey; UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(procId); ti_sdo_ipc_Notify_Object *obj; Assert_isTrue(procId < ti_sdo_utils_MultiProc_numProcessors && lineId < ti_sdo_ipc_Notify_numLines, ti_sdo_ipc_Notify_A_invArgument); obj = (ti_sdo_ipc_Notify_Object *) Notify_module->notifyHandles[clusterId][lineId]; Assert_isTrue(obj != NULL, ti_sdo_ipc_Notify_A_notRegistered); Assert_isTrue(key == obj->nesting, ti_sdo_ipc_Notify_A_outOfOrderNesting); /* Nesting value and enable state have to be in sync */ modKey = Gate_enterModule(); obj->nesting--; if (obj->nesting == 0) { /* Enable receiving events */ if (procId != MultiProc_self()) { INotifyDriver_enable(obj->driverHandle); } } Gate_leaveModule(modKey); }
/* * ======== Notify_enableEvent ======== */ Void Notify_enableEvent(UInt16 procId, UInt16 lineId, UInt32 eventId) { UInt32 strippedEventId = (eventId & 0xFFFF); UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(procId); ti_sdo_ipc_Notify_Object *obj; UInt sysKey; Assert_isTrue(procId < ti_sdo_utils_MultiProc_numProcessors && lineId < ti_sdo_ipc_Notify_numLines, ti_sdo_ipc_Notify_A_invArgument); Assert_isTrue(strippedEventId < ti_sdo_ipc_Notify_numEvents, ti_sdo_ipc_Notify_A_invArgument); Assert_isTrue(ISRESERVED(eventId), ti_sdo_ipc_Notify_A_reservedEvent); obj = (ti_sdo_ipc_Notify_Object *) Notify_module->notifyHandles[clusterId][lineId]; Assert_isTrue(obj != NULL, ti_sdo_ipc_Notify_A_notRegistered); if (procId != MultiProc_self()) { /* enable the remote event */ INotifyDriver_enableEvent(obj->driverHandle, strippedEventId); } else { /* enable the local event */ sysKey = Hwi_disable(); SET_BIT(Notify_module->localEnableMask, strippedEventId); Hwi_restore(sysKey); } }
/* * ======== ti_sdo_ipc_Notify_detach ======== * Called within Ipc module */ Int ti_sdo_ipc_Notify_detach(UInt16 remoteProcId) { ti_sdo_ipc_Notify_Object *obj; UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId); INotifyDriver_Handle driverHandle; UInt i; for (i = 0; i < ti_sdo_ipc_Notify_numLines; i++) { obj = (ti_sdo_ipc_Notify_Object *) Notify_module->notifyHandles[clusterId][i]; /* Ensure that notify is actually registered for the procId + lineId */ if (obj != NULL) { driverHandle = obj->driverHandle; /* First, unregister the driver since it was registered last */ ti_sdo_ipc_Notify_delete(&obj); /* Second, delete the driver itself */ INotifyDriver_delete(&driverHandle); } } /* Notify_detech never fails on RTOS */ return (Notify_S_SUCCESS); }
/* * ======== ti_sdo_ipc_Notify_Instance_init ======== */ Int ti_sdo_ipc_Notify_Instance_init( ti_sdo_ipc_Notify_Object *obj, INotifyDriver_Handle driverHandle, UInt16 remoteProcId, UInt16 lineId, const ti_sdo_ipc_Notify_Params *params, Error_Block *eb) { UInt i; UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId); List_Handle eventList; Assert_isTrue(remoteProcId < ti_sdo_utils_MultiProc_numProcessors && lineId < ti_sdo_ipc_Notify_numLines, ti_sdo_ipc_Notify_A_invArgument); Assert_isTrue(Notify_module->notifyHandles[clusterId][lineId] == NULL, ti_sdo_ipc_Notify_A_alreadyRegistered); obj->remoteProcId = remoteProcId; obj->lineId = lineId; obj->nesting = 0; /* Allocate and initialize (to 0 with calloc()) the callbacks array. */ obj->callbacks = Memory_calloc(ti_sdo_ipc_Notify_Object_heap(), (sizeof(ti_sdo_ipc_Notify_EventCallback) * ti_sdo_ipc_Notify_numEvents), 0, eb); if (obj->callbacks == NULL) { return (2); } obj->eventList = Memory_alloc(ti_sdo_ipc_Notify_Object_heap(), sizeof(List_Struct) * ti_sdo_ipc_Notify_numEvents, 0, eb); if (obj->eventList == NULL) { return (1); } for (i = 0; i < ti_sdo_ipc_Notify_numEvents; i++) { eventList = List_Object_get(obj->eventList, i); /* Pass in NULL for eb since construct should never fail */ List_construct(List_struct(eventList), NULL); } /* Used solely for remote driver (NULL if remoteProcId == self) */ obj->driverHandle = driverHandle; if (driverHandle != NULL) { /* Send this handle to the INotifyDriver */ INotifyDriver_setNotifyHandle(driverHandle, obj); } Notify_module->notifyHandles[clusterId][lineId] = obj; return (0); }
/* * ======== ti_sdo_ipc_Ipc_setEntry ======== */ Void ti_sdo_ipc_Ipc_setEntry(ti_sdo_ipc_Ipc_Entry *entry) { UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(entry->remoteProcId); /* Set the setupNotify flag */ Ipc_module->procEntry[clusterId].entry.setupNotify = entry->setupNotify; /* Set the setupMessageQ flag */ Ipc_module->procEntry[clusterId].entry.setupMessageQ = entry->setupMessageQ; }
/* * ======== Notify_intLineRegistered ======== */ Bool Notify_intLineRegistered(UInt16 procId, UInt16 lineId) { Bool registered; UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(procId); Assert_isTrue(procId < ti_sdo_utils_MultiProc_numProcessors && lineId < ti_sdo_ipc_Notify_numLines, ti_sdo_ipc_Notify_A_invArgument); registered = (Notify_module->notifyHandles[clusterId][lineId] != NULL); return (registered); }
/* * ======== Ipc_readConfig ======== */ Int Ipc_readConfig(UInt16 remoteProcId, UInt32 tag, Ptr cfg, SizeT size) { Int status = Ipc_E_FAIL; UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId); volatile ti_sdo_ipc_Ipc_ConfigEntry *entry; Bool cacheEnabled = SharedRegion_isCacheEnabled(0); /* Assert that the remoteProc in our cluster and isn't our own */ Assert_isTrue(clusterId < ti_sdo_utils_MultiProc_numProcsInCluster, ti_sdo_utils_MultiProc_A_invalidMultiProcId); if (cacheEnabled) { Cache_inv(Ipc_module->procEntry[clusterId].remoteConfigList, SharedRegion_getCacheLineSize(0), Cache_Type_ALL, TRUE); } entry = (ti_sdo_ipc_Ipc_ConfigEntry *) *Ipc_module->procEntry[clusterId].remoteConfigList; while ((SharedRegion_SRPtr)entry != ti_sdo_ipc_SharedRegion_INVALIDSRPTR) { entry = (ti_sdo_ipc_Ipc_ConfigEntry *) SharedRegion_getPtr((SharedRegion_SRPtr)entry); /* Traverse the list to find the tag */ if (cacheEnabled) { Cache_inv((Ptr)entry, size + sizeof(ti_sdo_ipc_Ipc_ConfigEntry), Cache_Type_ALL, TRUE); } if ((entry->remoteProcId == MultiProc_self()) && (entry->localProcId == remoteProcId) && (entry->tag == tag)) { if (size == entry->size) { memcpy(cfg, (Ptr)((UInt32)entry + sizeof(ti_sdo_ipc_Ipc_ConfigEntry)), entry->size); return (Ipc_S_SUCCESS); } else { return (Ipc_E_FAIL); } } entry = (ti_sdo_ipc_Ipc_ConfigEntry *)entry->next; } return (status); }
/* * ======== Notify_unregisterEventSingle ======== */ Int Notify_unregisterEventSingle(UInt16 procId, UInt16 lineId, UInt32 eventId) { UInt32 strippedEventId = (eventId & 0xFFFF); UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(procId); Int status; ti_sdo_ipc_Notify_Object *obj; UInt modKey; Assert_isTrue(procId < ti_sdo_utils_MultiProc_numProcessors && lineId < ti_sdo_ipc_Notify_numLines, ti_sdo_ipc_Notify_A_invArgument); Assert_isTrue(strippedEventId < ti_sdo_ipc_Notify_numEvents, ti_sdo_ipc_Notify_A_invArgument); Assert_isTrue(ISRESERVED(eventId), ti_sdo_ipc_Notify_A_reservedEvent); modKey = Gate_enterModule(); obj = (ti_sdo_ipc_Notify_Object *) Notify_module->notifyHandles[clusterId][lineId]; Assert_isTrue(obj != NULL, ti_sdo_ipc_Notify_A_notRegistered); if (obj->callbacks[strippedEventId].fnNotifyCbck) { if (procId != MultiProc_self()) { /* * First, Tell the remote notify driver that the event is now * unregistered */ INotifyDriver_unregisterEvent(obj->driverHandle, strippedEventId); } /* * No need to protect these modifications with the system gate because * we shouldn't get preempted by Notify_exec after INotifyDriver_ * unregisterEvent. */ obj->callbacks[strippedEventId].fnNotifyCbck = NULL; obj->callbacks[strippedEventId].cbckArg = NULL; status = Notify_S_SUCCESS; } else { /* No callback is registered. Fail. */ status = Notify_E_FAIL; } Gate_leaveModule(modKey); return (status); }
/* * ======== Notify_registerEventSingle ======== */ Int Notify_registerEventSingle(UInt16 procId, UInt16 lineId, UInt32 eventId, Notify_FnNotifyCbck fnNotifyCbck, UArg cbckArg) { UInt32 strippedEventId = (eventId & 0xFFFF); UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(procId); UInt modKey; Int status; ti_sdo_ipc_Notify_Object *obj; Assert_isTrue(procId < ti_sdo_utils_MultiProc_numProcessors && lineId < ti_sdo_ipc_Notify_numLines, ti_sdo_ipc_Notify_A_invArgument); Assert_isTrue(strippedEventId < ti_sdo_ipc_Notify_numEvents, ti_sdo_ipc_Notify_A_invArgument); Assert_isTrue(ISRESERVED(eventId), ti_sdo_ipc_Notify_A_reservedEvent); modKey = Gate_enterModule(); obj = (ti_sdo_ipc_Notify_Object *) Notify_module->notifyHandles[clusterId][lineId]; Assert_isTrue(obj != NULL, ti_sdo_ipc_Notify_A_notRegistered); if (obj->callbacks[strippedEventId].fnNotifyCbck) { /* A callback is already registered. Fail. */ status = Notify_E_ALREADYEXISTS; } else { /* * No callback is registered. Register it. There is no need to protect * these modifications because the event isn't registered yet. */ obj->callbacks[strippedEventId].fnNotifyCbck = (Fxn)fnNotifyCbck; obj->callbacks[strippedEventId].cbckArg = cbckArg; if (procId != MultiProc_self()) { /* Tell the remote notify driver that the event is now registered */ INotifyDriver_registerEvent(obj->driverHandle, strippedEventId); } status = Notify_S_SUCCESS; } Gate_leaveModule(modKey); return (status); }
/* * ======== ti_sdo_ipc_Ipc_getMasterAddr ======== */ Ptr ti_sdo_ipc_Ipc_getMasterAddr(UInt16 remoteProcId, Ptr sharedAddr) { Int slot; UInt16 masterId; volatile ti_sdo_ipc_Ipc_Reserved *master; SizeT reservedSize = ti_sdo_ipc_Ipc_reservedSizePerProc(); /* determine the master's procId and slot */ if (MultiProc_self() < remoteProcId) { masterId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId); slot = ti_sdo_utils_MultiProc_getClusterId(MultiProc_self()); } else { masterId = ti_sdo_utils_MultiProc_getClusterId(MultiProc_self()); slot = ti_sdo_utils_MultiProc_getClusterId(remoteProcId); } /* determine the reserve address for master between self and remote */ master = (ti_sdo_ipc_Ipc_Reserved *)((UInt32)sharedAddr + ((masterId * reservedSize) + (slot * sizeof(ti_sdo_ipc_Ipc_Reserved)))); return ((Ptr)master); }
/* * ======== ti_sdo_ipc_Ipc_getSlaveAddr ======== */ Ptr ti_sdo_ipc_Ipc_getSlaveAddr(UInt16 remoteProcId, Ptr sharedAddr) { Int slot; UInt16 slaveId; volatile ti_sdo_ipc_Ipc_Reserved *slave; SizeT reservedSize = ti_sdo_ipc_Ipc_reservedSizePerProc(); /* determine the slave's procId and slot */ if (MultiProc_self() < remoteProcId) { slaveId = ti_sdo_utils_MultiProc_getClusterId(MultiProc_self()); slot = ti_sdo_utils_MultiProc_getClusterId(remoteProcId) - 1; } else { slaveId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId); slot = ti_sdo_utils_MultiProc_getClusterId(MultiProc_self()) - 1; } /* determine the reserve address for slave between self and remote */ slave = (ti_sdo_ipc_Ipc_Reserved *)((UInt32)sharedAddr + ((slaveId * reservedSize) + (slot * sizeof(ti_sdo_ipc_Ipc_Reserved)))); return ((Ptr)slave); }
/* * ======== Ipc_isAttached ======== */ Bool Ipc_isAttached(UInt16 remoteProcId) { UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId); /* Assert remoteProcId is in our cluster */ Assert_isTrue(clusterId < ti_sdo_utils_MultiProc_numProcsInCluster, ti_sdo_utils_MultiProc_A_invalidMultiProcId); if (remoteProcId == MultiProc_self()) { return (FALSE); } else { return (Ipc_module->procEntry[clusterId].attached); } }
/* * ======== ti_sdo_ipc_Ipc_getEntry ======== */ Void ti_sdo_ipc_Ipc_getEntry(ti_sdo_ipc_Ipc_Entry *entry) { UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(entry->remoteProcId); /* Assert remoteProcId is in our cluster */ Assert_isTrue(clusterId < ti_sdo_utils_MultiProc_numProcsInCluster, ti_sdo_utils_MultiProc_A_invalidMultiProcId); /* Get the setupNotify flag */ entry->setupNotify = Ipc_module->procEntry[clusterId].entry.setupNotify; /* Get the setupMessageQ flag */ entry->setupMessageQ = Ipc_module->procEntry[clusterId].entry.setupMessageQ; }
/* * ======== Notify_sendEvent ======== */ Int Notify_sendEvent(UInt16 procId, UInt16 lineId, UInt32 eventId, UInt32 payload, Bool waitClear) { UInt32 strippedEventId = (eventId & 0xFFFF); UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(procId); Int status; ti_sdo_ipc_Notify_Object *obj; UInt sysKey; Assert_isTrue(procId < ti_sdo_utils_MultiProc_numProcessors && lineId < ti_sdo_ipc_Notify_numLines, ti_sdo_ipc_Notify_A_invArgument); Assert_isTrue(strippedEventId < ti_sdo_ipc_Notify_numEvents, ti_sdo_ipc_Notify_A_invArgument); Assert_isTrue(ISRESERVED(eventId), ti_sdo_ipc_Notify_A_reservedEvent); obj = (ti_sdo_ipc_Notify_Object *) Notify_module->notifyHandles[clusterId][lineId]; Assert_isTrue(obj != NULL, ti_sdo_ipc_Notify_A_notRegistered); if (procId != MultiProc_self()) { /* Send a remote event */ status = INotifyDriver_sendEvent(obj->driverHandle, strippedEventId, payload, waitClear); } else { /* * The check agaist non-NULL fnNotifyCbCk must be atomic with * Notify_exec so Notify_exec doesn't encounter a null callback. */ sysKey = Hwi_disable(); /* * If nesting == 0 (the driver is enabled) and the event is enabled, * send the event */ if (obj->callbacks[strippedEventId].fnNotifyCbck == NULL) { /* No callbacks are registered locally for the event. */ status = Notify_E_EVTNOTREGISTERED; } else if (obj->nesting != 0) { /* Driver is disabled */ status = Notify_E_FAIL; } else if (!TEST_BIT (Notify_module->localEnableMask, strippedEventId)) { /* Event is disabled */ status = Notify_E_EVTDISABLED; } else { /* Execute the callback function registered to the event */ ti_sdo_ipc_Notify_exec(obj, strippedEventId, payload); status = Notify_S_SUCCESS; } Hwi_restore(sysKey); } return (status); }
/* * ======== Ipc_attach ======== */ Int Ipc_attach(UInt16 remoteProcId) { Int i; Ptr sharedAddr; SizeT memReq; volatile ti_sdo_ipc_Ipc_Reserved *slave; ti_sdo_ipc_Ipc_ProcEntry *ipc; Error_Block eb; SharedRegion_Entry entry; SizeT reservedSize = ti_sdo_ipc_Ipc_reservedSizePerProc(); Bool cacheEnabled = SharedRegion_isCacheEnabled(0); UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId); Int status; UInt hwiKey; /* Assert remoteProcId is in our cluster and isn't our own */ Assert_isTrue(clusterId < ti_sdo_utils_MultiProc_numProcsInCluster, ti_sdo_utils_MultiProc_A_invalidMultiProcId); Assert_isTrue(remoteProcId != MultiProc_self(), ti_sdo_ipc_Ipc_A_invArgument); /* Check whether Ipc_start has been called. If not, fail. */ if (Ipc_module->ipcSharedAddr == NULL) { return (Ipc_E_FAIL); } /* for checking and incrementing attached below */ hwiKey = Hwi_disable(); /* Make sure its not already attached */ if (Ipc_module->procEntry[clusterId].attached) { Ipc_module->procEntry[clusterId].attached++; /* restore interrupts and return */ Hwi_restore(hwiKey); return (Ipc_S_ALREADYSETUP); } /* restore interrupts */ Hwi_restore(hwiKey); /* get region 0 information */ SharedRegion_getEntry(0, &entry); /* Make sure we've attached to owner of SR0 if we're not owner */ if ((MultiProc_self() != entry.ownerProcId) && (remoteProcId != entry.ownerProcId) && !(Ipc_module->procEntry[ti_sdo_utils_MultiProc_getClusterId( entry.ownerProcId)].attached)) { return (Ipc_E_FAIL); } /* Init error block */ Error_init(&eb); /* determine the slave's slot */ slave = Ipc_getSlaveAddr(remoteProcId, Ipc_module->ipcSharedAddr); if (cacheEnabled) { Cache_inv((Ptr)slave, reservedSize, Cache_Type_ALL, TRUE); } /* Synchronize the processors. */ status = Ipc_procSyncStart(remoteProcId, Ipc_module->ipcSharedAddr); if (status < 0) { return (status); } /* must be called before SharedRegion_attach */ status = ti_sdo_ipc_GateMP_attach(remoteProcId, Ipc_module->gateMPSharedAddr); if (status < 0) { return (status); } /* retrieves the SharedRegion Heap handles */ status = ti_sdo_ipc_SharedRegion_attach(remoteProcId); if (status < 0) { return (status); } /* get the attach parameters associated with remoteProcId */ ipc = &(Ipc_module->procEntry[clusterId]); /* attach Notify if not yet attached and specified to set internal setup */ if (!(Notify_intLineRegistered(remoteProcId, 0)) && (ipc->entry.setupNotify)) { /* call Notify_attach */ memReq = Notify_sharedMemReq(remoteProcId, Ipc_module->ipcSharedAddr); if (memReq != 0) { if (MultiProc_self() < remoteProcId) { /* * calloc required here due to race condition. Its possible * that the slave, who creates the instance, tries a sendEvent * before the master has created its instance because the * state of memory was enabled from a previous run. */ sharedAddr = Memory_calloc(SharedRegion_getHeap(0), memReq, SharedRegion_getCacheLineSize(0), &eb); /* make sure alloc did not fail */ if (sharedAddr == NULL) { return (Ipc_E_MEMORY); } /* if cache enabled, wbInv the calloc above */ if (cacheEnabled) { Cache_wbInv(sharedAddr, memReq, Cache_Type_ALL, TRUE); } /* set the notify SRPtr */ slave->notifySRPtr = SharedRegion_getSRPtr(sharedAddr, 0); } else { /* get the notify SRPtr */ sharedAddr = SharedRegion_getPtr(slave->notifySRPtr); } } else { sharedAddr = NULL; slave->notifySRPtr = 0; } /* call attach to remote processor */ status = Notify_attach(remoteProcId, sharedAddr); if (status < 0) { if (MultiProc_self() < remoteProcId && sharedAddr != NULL) { /* free the memory back to SharedRegion 0 heap */ Memory_free(SharedRegion_getHeap(0), sharedAddr, memReq); } return (Ipc_E_FAIL); } } /* Must come after GateMP_start because depends on default GateMP */ if (!(ti_sdo_utils_NameServer_isRegistered(remoteProcId)) && (ipc->entry.setupNotify)) { memReq = ti_sdo_utils_NameServer_SetupProxy_sharedMemReq( Ipc_module->ipcSharedAddr); if (memReq != 0) { if (MultiProc_self() < remoteProcId) { sharedAddr = Memory_alloc(SharedRegion_getHeap(0), memReq, SharedRegion_getCacheLineSize(0), &eb); /* make sure alloc did not fail */ if (sharedAddr == NULL) { return (Ipc_E_MEMORY); } /* set the NSRN SRPtr */ slave->nsrnSRPtr = SharedRegion_getSRPtr(sharedAddr, 0); } else { /* get the NSRN SRPtr */ sharedAddr = SharedRegion_getPtr(slave->nsrnSRPtr); } } else { sharedAddr = NULL; slave->nsrnSRPtr = 0; } /* call attach to remote processor */ status = ti_sdo_utils_NameServer_SetupProxy_attach(remoteProcId, sharedAddr); if (status < 0) { if (MultiProc_self() < remoteProcId && sharedAddr != NULL) { /* free the memory back to SharedRegion 0 heap */ Memory_free(SharedRegion_getHeap(0), sharedAddr, memReq); } return (Ipc_E_FAIL); } } /* Must come after GateMP_start because depends on default GateMP */ if (!(ti_sdo_ipc_MessageQ_SetupTransportProxy_isRegistered(remoteProcId)) && (ipc->entry.setupMessageQ)) { memReq = ti_sdo_ipc_MessageQ_SetupTransportProxy_sharedMemReq( Ipc_module->ipcSharedAddr); if (memReq != 0) { if (MultiProc_self() < remoteProcId) { sharedAddr = Memory_alloc(SharedRegion_getHeap(0), memReq, SharedRegion_getCacheLineSize(0), &eb); /* make sure alloc did not fail */ if (sharedAddr == NULL) { return (Ipc_E_MEMORY); } /* set the transport SRPtr */ slave->transportSRPtr = SharedRegion_getSRPtr(sharedAddr, 0); } else { /* get the transport SRPtr */ sharedAddr = SharedRegion_getPtr(slave->transportSRPtr); } } else { sharedAddr = NULL; slave->transportSRPtr = 0; } /* call attach to remote processor */ status = ti_sdo_ipc_MessageQ_SetupTransportProxy_attach(remoteProcId, sharedAddr); if (status < 0) { if (MultiProc_self() < remoteProcId && sharedAddr != NULL) { /* free the memory back to SharedRegion 0 heap */ Memory_free(SharedRegion_getHeap(0), sharedAddr, memReq); } return (Ipc_E_FAIL); } } /* writeback invalidate slave's shared memory if cache enabled */ if (cacheEnabled) { if (MultiProc_self() < remoteProcId) { Cache_wbInv((Ptr)slave, reservedSize, Cache_Type_ALL, TRUE); } } /* Call user attach fxns */ for (i = 0; i < ti_sdo_ipc_Ipc_numUserFxns; i++) { if (ti_sdo_ipc_Ipc_userFxns[i].userFxn.attach) { status = ti_sdo_ipc_Ipc_userFxns[i].userFxn.attach( ti_sdo_ipc_Ipc_userFxns[i].arg, remoteProcId); if (status < 0) { return (status); } } } /* Finish the processor synchronization */ status = ti_sdo_ipc_Ipc_procSyncFinish(remoteProcId, Ipc_module->ipcSharedAddr); if (status < 0) { return (status); } /* for atomically incrementing attached */ hwiKey = Hwi_disable(); /* now attached to remote processor */ Ipc_module->procEntry[clusterId].attached++; /* restore interrupts */ Hwi_restore(hwiKey); return (status); }
/* * ======== Ipc_writeConfig ======== */ Int Ipc_writeConfig(UInt16 remoteProcId, UInt32 tag, Ptr cfg, SizeT size) { Int status = Ipc_S_SUCCESS; UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId); SharedRegion_SRPtr curSRPtr, *prevSRPtr; ti_sdo_ipc_Ipc_ConfigEntry *entry; Error_Block eb; Bool cacheEnabled = SharedRegion_isCacheEnabled(0); /* Assert that the remoteProc in our cluster */ Assert_isTrue(clusterId < ti_sdo_utils_MultiProc_numProcsInCluster, ti_sdo_utils_MultiProc_A_invalidMultiProcId); Error_init(&eb); if (cfg == NULL) { status = Ipc_E_FAIL; /* get head of local config list and set prevSRPtr to it */ prevSRPtr = (Ipc_module->procEntry[clusterId].localConfigList); /* * When cfg is NULL, the last memory allocated from a previous * Ipc_writeConfig call with the same remoteProcId, tag, and size * is freed. */ curSRPtr = *prevSRPtr; /* loop through list of config entries until matching entry is found */ while (curSRPtr != ti_sdo_ipc_SharedRegion_INVALIDSRPTR) { /* convert Ptr associated with curSRPtr */ entry = (ti_sdo_ipc_Ipc_ConfigEntry *) (SharedRegion_getPtr(curSRPtr)); /* make sure entry matches remoteProcId, tag, and size */ if ((entry->remoteProcId == remoteProcId) && (entry->tag == tag) && (entry->size == size)) { /* Update the 'prev' next ptr */ *prevSRPtr = (SharedRegion_SRPtr)entry->next; /* writeback the 'prev' ptr */ if (cacheEnabled) { Cache_wb(prevSRPtr, sizeof(ti_sdo_ipc_Ipc_ConfigEntry), Cache_Type_ALL, FALSE); } /* free entry's memory back to shared heap */ Memory_free(SharedRegion_getHeap(0), entry, size + sizeof(ti_sdo_ipc_Ipc_ConfigEntry)); /* set the status to success */ status = Ipc_S_SUCCESS; break; } /* set the 'prev' to the 'cur' SRPtr */ prevSRPtr = (SharedRegion_SRPtr *)(&entry->next); /* point to next config entry */ curSRPtr = (SharedRegion_SRPtr)entry->next; } /* return that status */ return (status); } /* Allocate memory from the shared heap (System Heap) */ entry = Memory_alloc(SharedRegion_getHeap(0), size + sizeof(ti_sdo_ipc_Ipc_ConfigEntry), SharedRegion_getCacheLineSize(0), &eb); if (entry == NULL) { return (Ipc_E_FAIL); } /* set the entry */ entry->remoteProcId = remoteProcId; entry->localProcId = MultiProc_self(); entry->tag = tag; entry->size = size; memcpy((Ptr)((UInt32)entry + sizeof(ti_sdo_ipc_Ipc_ConfigEntry)), cfg, size); /* point the entry's next to the first entry in the list */ entry->next = *Ipc_module->procEntry[clusterId].localConfigList; /* first write-back the entry if cache is enabled */ if (cacheEnabled) { Cache_wb(entry, size + sizeof(ti_sdo_ipc_Ipc_ConfigEntry), Cache_Type_ALL, FALSE); } /* set the entry as the new first in the list */ *Ipc_module->procEntry[clusterId].localConfigList = SharedRegion_getSRPtr(entry, 0); /* write-back the config list */ if (cacheEnabled) { Cache_wb(Ipc_module->procEntry[clusterId].localConfigList, SharedRegion_getCacheLineSize(0), Cache_Type_ALL, FALSE); } return (status); }
/* * ======== Notify_unregisterEvent ======== */ Int Notify_unregisterEvent(UInt16 procId, UInt16 lineId, UInt32 eventId, Notify_FnNotifyCbck fnNotifyCbck, UArg cbckArg) { UInt32 strippedEventId = (eventId & 0xFFFF); UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(procId); Int status; UInt sysKey, modKey; ti_sdo_ipc_Notify_Object *obj; List_Handle eventList; ti_sdo_ipc_Notify_EventListener *listener; UInt count = 0; Assert_isTrue(procId < ti_sdo_utils_MultiProc_numProcessors && lineId < ti_sdo_ipc_Notify_numLines, ti_sdo_ipc_Notify_A_invArgument); Assert_isTrue(strippedEventId < ti_sdo_ipc_Notify_numEvents, ti_sdo_ipc_Notify_A_invArgument); Assert_isTrue(ISRESERVED(eventId), ti_sdo_ipc_Notify_A_reservedEvent); modKey = Gate_enterModule(); obj = (ti_sdo_ipc_Notify_Object *) Notify_module->notifyHandles[clusterId][lineId]; Assert_isTrue(obj != NULL, ti_sdo_ipc_Notify_A_notRegistered); eventList = List_Object_get(obj->eventList, strippedEventId); if (List_empty(eventList)) { return (Notify_E_NOTFOUND); } /* Get the first listener on the list */ listener = (ti_sdo_ipc_Notify_EventListener *)List_next(eventList, NULL); while (listener != NULL) { count++; if (listener->callback.fnNotifyCbck == (Fxn)fnNotifyCbck && listener->callback.cbckArg == cbckArg ) { break; /* found a match! */ } listener = (ti_sdo_ipc_Notify_EventListener *) List_next(eventList, (List_Elem *)listener); } if (listener == NULL) { /* Event listener not found */ status = Notify_E_NOTFOUND; } else { if (count == 1 && List_next(eventList, (List_Elem *)listener) == NULL) { /* * If only one element counted so far and the List_next returns * NULL, the list will be empty after unregistering. Therefore, * unregister the callback function. */ status = Notify_unregisterEventSingle(procId, lineId, eventId); /* unregisterEvent should always suceed */ Assert_isTrue(status == Notify_S_SUCCESS, ti_sdo_ipc_Notify_A_internal); /* No need to protect the list removal: the event's unregistered */ List_remove(eventList, (List_Elem *)listener); } else { /* * Need to atomically remove from the list using the system gate * because Notify_exec might preempt List_remove (the event is * still registered) */ sysKey = Hwi_disable(); List_remove(eventList, (List_Elem *)listener); Hwi_restore(sysKey); } /* Free the memory alloc'ed for the event listener */ Memory_free(ti_sdo_ipc_Notify_Object_heap(), listener, sizeof(ti_sdo_ipc_Notify_EventListener)); status = Notify_S_SUCCESS; } Gate_leaveModule(modKey); return (status); }
/* * ======== Ipc_detach ======== */ Int Ipc_detach(UInt16 remoteProcId) { Int i; UInt16 baseId = MultiProc_getBaseIdOfCluster(); UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId); Ptr notifySharedAddr; Ptr nsrnSharedAddr; Ptr msgqSharedAddr; volatile ti_sdo_ipc_Ipc_Reserved *slave, *master; SharedRegion_Entry entry; ti_sdo_ipc_Ipc_ProcEntry *ipc; SizeT reservedSize = ti_sdo_ipc_Ipc_reservedSizePerProc(); Bool cacheEnabled = SharedRegion_isCacheEnabled(0); Int status = Ipc_S_SUCCESS; UInt hwiKey; /* Assert remoteProcId is in our cluster and isn't our own */ Assert_isTrue(clusterId < ti_sdo_utils_MultiProc_numProcsInCluster, ti_sdo_utils_MultiProc_A_invalidMultiProcId); Assert_isTrue(remoteProcId != MultiProc_self(), ti_sdo_ipc_Ipc_A_invArgument); /* for checking and incrementing attached below */ hwiKey = Hwi_disable(); if (Ipc_module->procEntry[clusterId].attached > 1) { /* only detach if attach count reaches 1 */ Ipc_module->procEntry[clusterId].attached--; Hwi_restore(hwiKey); return (Ipc_S_BUSY); } else if (Ipc_module->procEntry[clusterId].attached == 0) { /* already detached, restore interrupts and return success */ Hwi_restore(hwiKey); return (Ipc_S_SUCCESS); } /* restore interrupts */ Hwi_restore(hwiKey); /* get region 0 information */ SharedRegion_getEntry(0, &entry); /* * Make sure we detach from all other procs in cluster before * detaching from owner of SR 0. */ if (remoteProcId == entry.ownerProcId) { for (i = 0; i < ti_sdo_utils_MultiProc_numProcsInCluster; i++, baseId++) { if ((baseId != MultiProc_self()) && (baseId != entry.ownerProcId) && (Ipc_module->procEntry[i].attached)) { return (Ipc_E_FAIL); } } } /* get the paramters associated with remoteProcId */ ipc = &(Ipc_module->procEntry[clusterId]); /* determine the slave's slot */ slave = Ipc_getSlaveAddr(remoteProcId, Ipc_module->ipcSharedAddr); /* determine the master's slot */ master = ti_sdo_ipc_Ipc_getMasterAddr(remoteProcId, Ipc_module->ipcSharedAddr); if (cacheEnabled) { Cache_inv((Ptr)slave, reservedSize, Cache_Type_ALL, TRUE); Cache_inv((Ptr)master, reservedSize, Cache_Type_ALL, TRUE); } if (MultiProc_self() < remoteProcId) { /* check to make sure master is not trying to attach */ if (master->startedKey == ti_sdo_ipc_Ipc_PROCSYNCSTART) { return (Ipc_E_NOTREADY); } } else { /* check to make sure slave is not trying to attach */ if (slave->startedKey == ti_sdo_ipc_Ipc_PROCSYNCSTART) { return (Ipc_E_NOTREADY); } } /* The slave processor waits for master to finish its detach sequence */ if (MultiProc_self() < remoteProcId) { if (master->startedKey != ti_sdo_ipc_Ipc_PROCSYNCDETACH) { return (Ipc_E_NOTREADY); } } /* Call user detach fxns */ for (i = 0; i < ti_sdo_ipc_Ipc_numUserFxns; i++) { if (ti_sdo_ipc_Ipc_userFxns[i].userFxn.detach) { status = ti_sdo_ipc_Ipc_userFxns[i].userFxn.detach( ti_sdo_ipc_Ipc_userFxns[i].arg, remoteProcId); if (status < 0) { return (status); } } } if ((ipc->entry.setupMessageQ) && (ti_sdo_ipc_MessageQ_SetupTransportProxy_isRegistered(remoteProcId))) { /* call MessageQ_detach for remote processor */ status = ti_sdo_ipc_MessageQ_SetupTransportProxy_detach(remoteProcId); if (status < 0) { return (Ipc_E_FAIL); } if (slave->transportSRPtr) { /* free the memory if slave processor */ if (MultiProc_self() < remoteProcId) { /* get the pointer to MessageQ transport instance */ msgqSharedAddr = SharedRegion_getPtr(slave->transportSRPtr); /* free the memory back to SharedRegion 0 heap */ Memory_free(SharedRegion_getHeap(0), msgqSharedAddr, ti_sdo_ipc_MessageQ_SetupTransportProxy_sharedMemReq( msgqSharedAddr)); /* set pointer for MessageQ transport instance back to NULL */ slave->transportSRPtr = NULL; } } } if ((ipc->entry.setupNotify) && (ti_sdo_utils_NameServer_isRegistered(remoteProcId))) { /* call NameServer_SetupProxy_detach for remote processor */ status = ti_sdo_utils_NameServer_SetupProxy_detach(remoteProcId); if (status < 0) { return (Ipc_E_FAIL); } if (slave->nsrnSRPtr) { /* free the memory if slave processor */ if (MultiProc_self() < remoteProcId) { /* get the pointer to NSRN instance */ nsrnSharedAddr = SharedRegion_getPtr(slave->nsrnSRPtr); /* free the memory back to SharedRegion 0 heap */ Memory_free(SharedRegion_getHeap(0), nsrnSharedAddr, ti_sdo_utils_NameServer_SetupProxy_sharedMemReq( nsrnSharedAddr)); /* set pointer for NSRN instance back to NULL */ slave->nsrnSRPtr = NULL; } } } if ((ipc->entry.setupNotify) && (Notify_intLineRegistered(remoteProcId, 0))) { /* call Notify_detach for remote processor */ status = ti_sdo_ipc_Notify_detach(remoteProcId); if (status < 0) { return (Ipc_E_FAIL); } if (slave->notifySRPtr) { /* free the memory if slave processor */ if (MultiProc_self() < remoteProcId) { /* get the pointer to Notify instance */ notifySharedAddr = SharedRegion_getPtr(slave->notifySRPtr); /* free the memory back to SharedRegion 0 heap */ Memory_free(SharedRegion_getHeap(0), notifySharedAddr, Notify_sharedMemReq(remoteProcId, notifySharedAddr)); /* set pointer for Notify instance back to NULL */ slave->notifySRPtr = NULL; } } } /* close any HeapMemMP which may have been opened */ status = ti_sdo_ipc_SharedRegion_detach(remoteProcId); if (status < 0) { return (status); } /* close any GateMP which may have been opened */ status = ti_sdo_ipc_GateMP_detach(remoteProcId); if (status < 0) { return (status); } if (MultiProc_self() < remoteProcId) { slave->configListHead = ti_sdo_ipc_SharedRegion_INVALIDSRPTR; slave->startedKey = ti_sdo_ipc_Ipc_PROCSYNCDETACH; if (cacheEnabled) { Cache_wbInv((Ptr)slave, reservedSize, Cache_Type_ALL, TRUE); } } else { master->configListHead = ti_sdo_ipc_SharedRegion_INVALIDSRPTR; master->startedKey = ti_sdo_ipc_Ipc_PROCSYNCDETACH; if (cacheEnabled) { Cache_wbInv((Ptr)master, reservedSize, Cache_Type_ALL, TRUE); } } /* attached must be decremented atomically */ hwiKey = Hwi_disable(); /* now detached from remote processor */ Ipc_module->procEntry[clusterId].attached--; /* restore interrupts */ Hwi_restore(hwiKey); return (status); }
/* * ======== ti_sdo_ipc_Ipc_procSyncStart ======== * The owner of SharedRegion 0 writes to its reserve memory address * in region 0 to let the other processors know it has started. * It then spins until the other processors start. * The other processors write their reserve memory address in * region 0 to let the owner processor know they've started. * The other processors then spin until the owner processor writes * to let them know that its finished the process of synchronization * before continuing. */ Int ti_sdo_ipc_Ipc_procSyncStart(UInt16 remoteProcId, Ptr sharedAddr) { volatile ti_sdo_ipc_Ipc_Reserved *self, *remote; ti_sdo_ipc_Ipc_ProcEntry *ipc; UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId); SizeT reservedSize = ti_sdo_ipc_Ipc_reservedSizePerProc(); Bool cacheEnabled = SharedRegion_isCacheEnabled(0); /* don't do any synchronization if procSync is NONE */ if (ti_sdo_ipc_Ipc_procSync == ti_sdo_ipc_Ipc_ProcSync_NONE) { return (Ipc_S_SUCCESS); } /* determine self and remote pointers */ if (MultiProc_self() < remoteProcId) { self = Ipc_getSlaveAddr(remoteProcId, sharedAddr); remote = ti_sdo_ipc_Ipc_getMasterAddr(remoteProcId, sharedAddr); } else { self = ti_sdo_ipc_Ipc_getMasterAddr(remoteProcId, sharedAddr); remote = Ipc_getSlaveAddr(remoteProcId, sharedAddr); } /* construct the config list */ ipc = &(Ipc_module->procEntry[clusterId]); ipc->localConfigList = (Ptr)&self->configListHead; ipc->remoteConfigList = (Ptr)&remote->configListHead; *ipc->localConfigList = ti_sdo_ipc_SharedRegion_INVALIDSRPTR; if (cacheEnabled) { Cache_wbInv(ipc->localConfigList, reservedSize, Cache_Type_ALL, TRUE); } if (MultiProc_self() < remoteProcId) { /* set my processor's reserved key to start */ self->startedKey = ti_sdo_ipc_Ipc_PROCSYNCSTART; /* write back my processor's reserve key */ if (cacheEnabled) { Cache_wbInv((Ptr)self, reservedSize, Cache_Type_ALL, TRUE); } /* wait for remote processor to start */ if (cacheEnabled) { Cache_inv((Ptr)remote, reservedSize, Cache_Type_ALL, TRUE); } if (remote->startedKey != ti_sdo_ipc_Ipc_PROCSYNCSTART) { return (Ipc_E_NOTREADY); } } else { /* wait for remote processor to start */ if (cacheEnabled) { Cache_inv((Ptr)remote, reservedSize, Cache_Type_ALL, TRUE); } if ((self->startedKey != ti_sdo_ipc_Ipc_PROCSYNCSTART) && (remote->startedKey != ti_sdo_ipc_Ipc_PROCSYNCSTART)) { return (Ipc_E_NOTREADY); } /* set my processor's reserved key to start */ self->startedKey = ti_sdo_ipc_Ipc_PROCSYNCSTART; /* write my processor's reserve key back */ if (cacheEnabled) { Cache_wbInv((Ptr)self, reservedSize, Cache_Type_ALL, TRUE); /* wait for remote processor to finish */ Cache_inv((Ptr)remote, reservedSize, Cache_Type_ALL, TRUE); } if (remote->startedKey != ti_sdo_ipc_Ipc_PROCSYNCFINISH) { return (Ipc_E_NOTREADY); } } return (Ipc_S_SUCCESS); }
/* * ======== Notify_registerEvent ======== */ Int Notify_registerEvent(UInt16 procId, UInt16 lineId, UInt32 eventId, Notify_FnNotifyCbck fnNotifyCbck, UArg cbckArg) { UInt32 strippedEventId = (eventId & 0xFFFF); UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(procId); Int status; ti_sdo_ipc_Notify_Object *obj; UInt modKey; List_Handle eventList; ti_sdo_ipc_Notify_EventListener *listener; Bool listWasEmpty; Error_Block eb; Assert_isTrue(procId < ti_sdo_utils_MultiProc_numProcessors && lineId < ti_sdo_ipc_Notify_numLines, ti_sdo_ipc_Notify_A_invArgument); Assert_isTrue(strippedEventId < ti_sdo_ipc_Notify_numEvents, ti_sdo_ipc_Notify_A_invArgument); Assert_isTrue(ISRESERVED(eventId), ti_sdo_ipc_Notify_A_reservedEvent); Error_init(&eb); modKey = Gate_enterModule(); obj = (ti_sdo_ipc_Notify_Object *) Notify_module->notifyHandles[clusterId][lineId]; Assert_isTrue(obj != NULL, ti_sdo_ipc_Notify_A_notRegistered); /* Allocate a new EventListener */ listener = Memory_alloc(ti_sdo_ipc_Notify_Object_heap(), sizeof(ti_sdo_ipc_Notify_EventListener), 0, &eb); if (listener == NULL) { /* Listener memory allocation failed. Leave module gate & return */ Gate_leaveModule(modKey); return (Notify_E_MEMORY); } listener->callback.fnNotifyCbck = (Fxn)fnNotifyCbck; listener->callback.cbckArg = cbckArg; eventList = List_Object_get(obj->eventList, strippedEventId); /* * Store whether the list was empty so we know whether to register the * callback */ listWasEmpty = List_empty(eventList); /* * Need to atomically add to the list using the system gate because * Notify_exec might preempt List_remove. List_put is atomic. */ List_put(eventList, (List_Elem *)listener); if (listWasEmpty) { /* * Registering this event for the first time. Need to register the * callback function. */ status = Notify_registerEventSingle(procId, lineId, eventId, Notify_execMany, (UArg)obj); /* Notify_registerEventSingle should always succeed */ Assert_isTrue(status == Notify_S_SUCCESS, ti_sdo_ipc_Notify_A_internal); } status = Notify_S_SUCCESS; Gate_leaveModule(modKey); return (status); }