/* * ======== NTFY_Notify ======== * Purpose: * Execute notify function (signal event) for every * element in the notification list that is to be notified about the * event specified in uEventMask. */ void NTFY_Notify(struct NTFY_OBJECT *hNtfy, u32 uEventMask) { struct NOTIFICATION *pNotify; DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE)); /* * Go through notifyList and notify all clients registered for * uEventMask events. */ (void) SYNC_EnterCS(hNtfy->hSync); pNotify = (struct NOTIFICATION *)LST_First(hNtfy->notifyList); while (pNotify != NULL) { if (pNotify->uEventMask & uEventMask) { /* Notify */ if (pNotify->uNotifyType == DSP_SIGNALEVENT) (void)SYNC_SetEvent(pNotify->hSync); } pNotify = (struct NOTIFICATION *)LST_Next(hNtfy->notifyList, (struct list_head *)pNotify); } (void) SYNC_LeaveCS(hNtfy->hSync); }
/* * ======== RMM_free ======== */ bool RMM_free(struct RMM_TargetObj *target, u32 segid, u32 addr, u32 size, bool reserved) { struct RMM_OvlySect *sect; bool retVal = true; DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE)); DBC_Require(reserved || segid < target->numSegs); DBC_Require(reserved || (addr >= target->segTab[segid].base && (addr + size) <= (target->segTab[segid].base + target->segTab[segid].length))); GT_5trace(RMM_debugMask, GT_ENTER, "RMM_free(0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx)\n", target, segid, addr, size, reserved); /* * Free or unreserve memory. */ if (!reserved) { retVal = freeBlock(target, segid, addr, size); if (retVal) target->segTab[segid].number--; } else { /* Unreserve memory */ sect = (struct RMM_OvlySect *)LST_First(target->ovlyList); while (sect != NULL) { if (addr == sect->addr) { DBC_Assert(size == sect->size); /* Remove from list */ LST_RemoveElem(target->ovlyList, (struct LST_ELEM *)sect); MEM_Free(sect); break; } sect = (struct RMM_OvlySect *)LST_Next(target->ovlyList, (struct LST_ELEM *)sect); } if (sect == NULL) retVal = false; } return retVal; }
/* * ======== RMM_alloc ======== */ DSP_STATUS RMM_alloc(struct RMM_TargetObj *target, u32 segid, u32 size, u32 align, u32 *dspAddr, bool reserve) { struct RMM_OvlySect *sect; struct RMM_OvlySect *prevSect = NULL; struct RMM_OvlySect *newSect; u32 addr; DSP_STATUS status = DSP_SOK; DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE)); DBC_Require(dspAddr != NULL); DBC_Require(size > 0); DBC_Require(reserve || (target->numSegs > 0)); DBC_Require(cRefs > 0); GT_6trace(RMM_debugMask, GT_ENTER, "RMM_alloc(0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx, 0x%lx)\n", target, segid, size, align, dspAddr, reserve); if (!reserve) { if (!allocBlock(target, segid, size, align, dspAddr)) { status = DSP_EMEMORY; } else { /* Increment the number of allocated blocks in this * segment */ target->segTab[segid].number++; } goto func_end; } /* An overlay section - See if block is already in use. If not, * insert into the list in ascending address size. */ addr = *dspAddr; sect = (struct RMM_OvlySect *)LST_First(target->ovlyList); /* Find place to insert new list element. List is sorted from * smallest to largest address. */ while (sect != NULL) { if (addr <= sect->addr) { /* Check for overlap with sect */ if ((addr + size > sect->addr) || (prevSect && (prevSect->addr + prevSect->size > addr))) { status = DSP_EOVERLAYMEMORY; } break; } prevSect = sect; sect = (struct RMM_OvlySect *)LST_Next(target->ovlyList, (struct LST_ELEM *)sect); } if (DSP_SUCCEEDED(status)) { /* No overlap - allocate list element for new section. */ newSect = MEM_Calloc(sizeof(struct RMM_OvlySect), MEM_PAGED); if (newSect == NULL) { status = DSP_EMEMORY; } else { LST_InitElem((struct LST_ELEM *)newSect); newSect->addr = addr; newSect->size = size; newSect->page = segid; if (sect == NULL) { /* Put new section at the end of the list */ LST_PutTail(target->ovlyList, (struct LST_ELEM *)newSect); } else { /* Put new section just before sect */ LST_InsertBefore(target->ovlyList, (struct LST_ELEM *)newSect, (struct LST_ELEM *)sect); } } } func_end: return status; }
/* * ======== NTFY_Register ======== * Purpose: * Add a notification element to the list. If the notification is already * registered, and uEventMask != 0, the notification will get posted for * events specified in the new event mask. If the notification is already * registered and uEventMask == 0, the notification will be unregistered. */ DSP_STATUS NTFY_Register(struct NTFY_OBJECT *hNtfy, struct DSP_NOTIFICATION *hNotification, u32 uEventMask, u32 uNotifyType) { struct NOTIFICATION *pNotify; struct SYNC_ATTRS syncAttrs; DSP_STATUS status = DSP_SOK; DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE)); if (hNotification == NULL) status = DSP_EHANDLE; /* Return DSP_ENOTIMPL if uNotifyType is not supported */ if (DSP_SUCCEEDED(status)) { if (!IsValidNotifyMask(uNotifyType)) status = DSP_ENOTIMPL; } if (DSP_FAILED(status)) return status; (void)SYNC_EnterCS(hNtfy->hSync); pNotify = (struct NOTIFICATION *)LST_First(hNtfy->notifyList); while (pNotify != NULL) { /* If there is more than one notification type, each * type may require its own handler code. */ if (hNotification->handle == pNotify->hSync) { /* found */ break; } pNotify = (struct NOTIFICATION *)LST_Next(hNtfy->notifyList, (struct list_head *)pNotify); } if (pNotify == NULL) { /* Not registered */ if (uEventMask == 0) { status = DSP_EVALUE; } else { /* Allocate NOTIFICATION object, add to list */ pNotify = MEM_Calloc(sizeof(struct NOTIFICATION), MEM_PAGED); if (pNotify == NULL) status = DSP_EMEMORY; } if (DSP_SUCCEEDED(status)) { LST_InitElem((struct list_head *)pNotify); /* If there is more than one notification type, each * type may require its own handler code. */ status = SYNC_OpenEvent(&pNotify->hSync, &syncAttrs); hNotification->handle = pNotify->hSync; if (DSP_SUCCEEDED(status)) { pNotify->uEventMask = uEventMask; pNotify->uNotifyType = uNotifyType; LST_PutTail(hNtfy->notifyList, (struct list_head *)pNotify); } else { DeleteNotify(pNotify); } } } else { /* Found in list */ if (uEventMask == 0) { /* Remove from list and free */ LST_RemoveElem(hNtfy->notifyList, (struct list_head *)pNotify); DeleteNotify(pNotify); } else { /* Update notification mask (type shouldn't change) */ pNotify->uEventMask = uEventMask; } } (void)SYNC_LeaveCS(hNtfy->hSync); return status; }