/*
 *  ======== edma3OsProtectExit ========
 *  OS critical section protect (Exit) function
 */
void edma3OsProtectExit(unsigned int edma3InstanceId, int level, 
        unsigned int intState)
{
/*      (void)edma3InstanceId;*/

    switch (level) {
        /* Enable all (global) interrupts */
        case EDMA3_OS_PROTECT_INTERRUPT :
            HWI_restore(intState);
            break;

        /* Enable scheduler */
        case EDMA3_OS_PROTECT_SCHEDULER :
            break;

        case EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION :
            TSK_enable();
            break;

        case EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR :
            TSK_enable();
            break;

        /* Enable EDMA3 TC error interrupt only */
        case EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR :
            switch (intState)
                {
                case 0:
                case 1:
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:
                case 7:
                    /* Fall through... */
                    /* Enable the corresponding interrupt */
                    TSK_enable();
                    break;

                 default:
                    break;
                }

            break;

        default:
            break;
    }
}
/**
* \brief   EDMA3 OS Protect Exit
*
*      This function undoes the protection enforced to original state
*      as is specified by the variable 'intState' passed, if the protection
*      level is EDMA3_OS_PROTECT_INTERRUPT.
*      For EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION and
*      EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR, variable 'intState' is ignored,
*      and the requested interrupt is enabled.
*      For EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR, 'intState' specifies the
*      Transfer Controller number whose interrupt needs to be enabled.
* \param   level is numeric identifier of the desired degree of protection.
* \param   intState is original state of protection at time when the
*      corresponding edma3OsProtectEntry() was called (Only
*      for EDMA3_OS_PROTECT_INTERRUPT protection level).
* \return  None
*/
void edma3OsProtectExit (int level, unsigned int intState)
{
#if 0 //wj
  switch (level)
  {
    /* Enable all (global) interrupts */
  case EDMA3_OS_PROTECT_INTERRUPT :
    HWI_restore(intState);
    break;
    
    /* Enable scheduler */
  case EDMA3_OS_PROTECT_SCHEDULER :
    TSK_enable();
    break;
    
    /* Enable EDMA3 transfer completion interrupt only */
  case EDMA3_OS_PROTECT_INTERRUPT_XFER_COMPLETION :
    ECM_enableEvent(ccXferCompInt);
    break;
    
    /* Enable EDMA3 CC error interrupt only */
  case EDMA3_OS_PROTECT_INTERRUPT_CC_ERROR :
    ECM_enableEvent(ccErrorInt);
    break;
    
    /* Enable EDMA3 TC error interrupt only */
  case EDMA3_OS_PROTECT_INTERRUPT_TC_ERROR :
    switch (intState)
    {
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
      /* Fall through... */
      /* Enable the corresponding interrupt */
      ECM_enableEvent(tcErrorInt[intState]);
      break;
      
    default:
      break;
    }
    
    break;
    
    default:
      break;
  }
#endif
}
/*
 *  ======== freeBlock ========
 */
static Bool freeBlock(RMM_Handle rmm, UInt32 addr, UInt32 size)
{
    RMM_Header *head;
    RMM_Header *poolHead;
    RMM_Header *curr;
    RMM_Header *next = NULL;
    RMM_Header *rhead;
    RMM_Header *headers;
    Int         nextIdx;
    Int         currIdx;
    Int         tmpIdx;
    Bool        joined = FALSE;
    Bool        retVal = TRUE;


    //DBC_assert(size > 0);
    GT_assert(ti_sdo_fc_dman3_GTMask, size > 0);

    /* Get the head of the free list */
    head = &(rmm->freeList);

    /* Array of RMM Headers */
    headers = (RMM_Header *)((UInt32)rmm + (UInt32)rmm->headers);

    /* Protect queues in case of context switch */
     TSK_disable();

    /*
     *  Search down the list of free blocks for the right place to put a
     *  header with address "addr". List is sorted by address, with lowest
     *  address first in the list.
     */
    curr = head;
    currIdx = nextIdx = curr->next;
    while ((nextIdx != -1) && (addr > headers[nextIdx].addr)) {
        curr = headers + nextIdx;
        currIdx = nextIdx;
        nextIdx = curr->next;
    }

    if (nextIdx != -1) {
        next = headers + nextIdx;
    }
    if (currIdx != -1) {
        curr = headers + currIdx;
    }

    /*
     *  The freed block should be put in between curr and next, and the
     *  it should not extend into the next block.
     *  In the case that curr and next are in the middle of the list,
     *  we should have
     *      curr->addr < addr  and (addr + size) <= next->addr
     */
    /*
     *  List is empty, or found element to insert after, or inserting at
     *  the beginning of the list
     */
    //DBC_assert((currIdx == -1) || (curr->addr < addr) ||
            //(currIdx == head->next));

    /* Got to the end of the list or found element to insert before */
    //DBC_assert((nextIdx == -1) || (addr + size <= next->addr));
    GT_assert(ti_sdo_fc_dman3_GTMask, (currIdx == -1) || (curr->addr < addr) ||
            (currIdx == head->next));
    GT_assert(ti_sdo_fc_dman3_GTMask, (nextIdx == -1) ||
            (addr + size <= next->addr));

    /* Join with upper block, if possible */
    if ((nextIdx != -1) && ((addr + size) == next->addr)) {
        next->size += size;
        next->addr = addr;
        joined = TRUE;
    }

    /* Join with the lower block, if possible */
    if ((currIdx != -1) && (currIdx != nextIdx) &&
            ((curr->addr + curr->size) == addr)) {
        if (joined) {
            //DBC_assert(next != NULL);

            /*
             *  We need to join the upper block and lower blocks, returning
             *  one of the headers back to the free pool.
             */
            curr->size += next->size;

            /* Take "next" out of the free block list */
            curr->next = next->next;

            /* Put "next" in the pool of free headers */
            poolHead = &(rmm->headerPool);
            next->next = poolHead->next;
            poolHead->next = nextIdx;
        }
        else {
            curr->size += size;
            joined = TRUE;
        }
    }

    /*
     *  If we can't join the block we're freeing to an existing free block,
     *  we need to get an RMM_Header from the free pool, initialize it, and
     *  insert it in the free list.
     */
    if (!joined) {
        poolHead = &(rmm->headerPool);

        /* If the pool of headers is empty, we're stuck */
        if (poolHead->next == -1) {
            /* List is empty */
            //DBC_assert(FALSE);
            GT_assert(ti_sdo_fc_dman3_GTMask, FALSE);
            retVal = FALSE;
        }
        else {
            /* Take the first header in the free pool. */
            tmpIdx = poolHead->next;
            rhead = headers + tmpIdx;

            poolHead->next = rhead->next;

            /*
             *  Now insert rhead into the free block list:
             *      curr --> rhead --> next
             */
            if (currIdx == nextIdx) {
                /* Insert at the beginning of the list */
                curr = head;
            }
            curr->next = tmpIdx;
            rhead->next = nextIdx;
            rhead->addr = addr;
            rhead->size = size;
        }
    }

    TSK_enable();

    return (retVal);
}
/*
 *  ======== allocBlock ========
 *  This allocation function allocates memory from the lowest addresses
 *  first.
 */
static Bool allocBlock(RMM_Handle rmm, UInt32 size, UInt32 *addr)
{
    RMM_Header *head;
    RMM_Header *poolHead;
    RMM_Header *prev;
    RMM_Header *curr;
    RMM_Header *headers;
    Int         nextIdx;
    Int         currIdx;
    UInt32      blockSize;
    Bool        retVal = FALSE;

    /* Initialize head pointer to point to beginning of free list */
    head = &(rmm->freeList);

    /* prev pointer should point to the previous entry, start by pointing
       to the head of free list */ 
    prev = head;

    /* Array of RMM Headers */
    headers = (RMM_Header *)((UInt32)rmm + (UInt32)rmm->headers);

    /* Protect queues in case of context switch */
    TSK_disable();

    /* Loop through free list till you reach the end (-1) */ 
    while ((currIdx = prev->next) != -1) {

        /* curr pointer should point to the current freeList entry */  
        curr = headers + prev->next;

        /* nextIdx should point to the next entry in the linked list */ 
        nextIdx = curr->next;

        /* size of the current free block */
        blockSize = curr->size;        

        if (blockSize >= size) {       /* big enough */

            /* If the block is a perfect match */
            if (blockSize == size) {

                /*
                 *  Remove current header from the list of free blocks
                 *  and put it back in the pool of "allocated" headers, at the
                 *  beginning of the list.
                 */

                /* To remove entry from freeList, adjust the next pointer of
                   the prev entry */ 
                prev->next = nextIdx;

                /* poolHead points to headerPool which is list of allocated
                   blocks  */
                poolHead = &(rmm->headerPool);

                /* Adjust next pointer of curr */ 
                curr->next = poolHead->next;

                /* current entry will become the new beginning of headerPool */ 
                poolHead->next = currIdx;
            }
            
            /* This is the allocated address, return it */ 
            *addr = curr->addr;

            /* Adjust current entries size and addr to account for allocated 
               memory */
            curr->size -= size;
            curr->addr += size;

            retVal = TRUE;
            break;
        }
        prev = curr;
    }

    TSK_enable();

    return (retVal);
}
Exemple #5
0
/*
 * DEV_createDevice creates device(DEV_Device) entry in the OBJ table
 * if device by that name do not exist in the system.
 * This API is not reentrant
 */
Int DEV_createDevice (String name, Void *fxns,   Fxn initFxn,
        DEV_Attrs *attrs)
{
    DEV_TableElem *objDevHead = (DEV_TableElem*) &DEV_table;
    DEV_TableElem *objDev, *objEntry;
    DEV_Device *dptr, *entry;
    IOM_Fxns *iomfxns;
    Int status;
    Uns key;

    /*
     * Crate a device entry, if not successful return
     * SYS_EALLOC. 
     */

    objEntry = MEM_calloc(0, sizeof(DEV_TableElem), 0);

    if (objEntry == NULL) {
        return(SYS_EALLOC);
    }

    TSK_disable();


    /*
     * Check if device already exists in the Device table, if yes return
     * SYS_EINVAL
     */
    DEV_find(name, &entry);

    if (entry != NULL) {
        TSK_enable();
        MEM_free(0, objEntry, sizeof(DEV_TableElem));
        SYS_error("DEV", SYS_EINVAL);
        return(SYS_EINVAL);
    }

    /*
     * Initialize new device entry(DEV_Device) in the OBJ table with
     * the parameters passed to API
     */
    entry = &objEntry->device;
    entry->name = name;
    entry->fxns = fxns;

    if (attrs == NULL) {
        attrs = &DEV_ATTRS;
    }
    entry->devid  = attrs->devid;
    entry->params = attrs->params;
    entry->type   = attrs->type;
    entry->devp   = attrs->devp;

    /*
     * Call the Device init function if its not NULL, with interrupts
     * disabled.
     */
    if (initFxn != NULL) {
        key = HWI_disable();
        (*initFxn)();
        HWI_restore(key);
    }

    /*
     * If device created is of type IOM then call mini driver function
     * mdBindDev with interrupts disabled.
     */
    if (entry->type == DEV_IOMTYPE) {
        iomfxns = (IOM_Fxns *) entry->fxns;

        key = HWI_disable();
        status = iomfxns->mdBindDev(&entry->devp, entry->devid,
                                     entry->params);
        HWI_restore(key);

        if (status != IOM_COMPLETED) {
            
            TSK_enable();

            /* Delete the just created device entry in device table */
            MEM_free(0, objEntry, sizeof(DEV_TableElem));

            SYS_error("DEV", SYS_EBADIO);

            return(status);
        }

    }

    /*
     * Device is ready for addition into OBJ_Table. Check new device
     * name length against existing device name lengths. If length of
     * new device is greater than one in OBJ_table, mark the location
     * and insert device ahead of device whose name length is shorter
     * else add it to the end.
     *
     * This will keep all the devices sorted in descending order, which is
     * required to pass additional parameters along with device name in 
     * DEV_open()
     */

    objDev = (DEV_TableElem *)QUE_next((Ptr)objDevHead);
    while (objDev != objDevHead) {
        dptr = &objDev->device;
        if (strlen(name) > strlen(dptr->name)) {
            break;
        }
        objDev = (DEV_TableElem *)QUE_next((Ptr)objDev);
    }

    /* Insert objEntry ahead of objDev */
    QUE_insert(objDev, objEntry);

    TSK_enable();

    return(SYS_OK);
}
Exemple #6
0
/*
 *  ======== DPI_issue ========
 */
Static Int DPI_issue(DEV_Handle dev)
{
    PipeObj         *pipe = (PipeObj *)dev->object;
    SPipeObj        *sPipe = pipe->sPipe;
    DEV_Handle      otherdev = sPipe->device[dev->mode ^ 0x1];
    SEM_Handle      otherReady = sPipe->readySem[dev->mode ^ 0x1];
    DEV_Frame       *otherframe;
    DEV_Frame       *frame;
#ifdef COPYBUFS
    DEV_Frame       *srcframe;
    DEV_Frame       *dstframe;
#endif
    
    /*
     * Atomically check that each side has a frame so we can do an
     * exchange.  We can't be sure that a frame is on the
     * dev->todevice queue (just put there by SIO) since a task
     * switch to the task on the other side might intervene and
     * take the frame from this side.
     */
    TSK_disable();
    if (otherdev != NULL &&
        !QUE_empty(dev->todevice) && !QUE_empty(otherdev->todevice)) {

        otherframe = QUE_get(otherdev->todevice);
        frame = QUE_get(dev->todevice);

        /* done with atomic stuff */
        TSK_enable();

/*
 * #define COPYBUFS to cause buffers to be copied through the pipe
 * instead of being exchanged.  Doing so retains the semantics of
 * the ISSUERECLAIM model, but is slow.  If COPYBUFS is *not* defined,
 * then one side reclaims buffers issued by the other side, thereby
 * not strictly retaining buffer ordering.
 */
#ifdef COPYBUFS
        if (dev->mode == DEV_INPUT) {
            dstframe = frame;
            srcframe = otherframe;
        }
        else {
            dstframe = otherframe;
            srcframe = frame;
        }
        memcpy(dstframe->addr, srcframe->addr, srcframe->size);
        dstframe->size = srcframe->size;
        dstframe->arg = srcframe->arg;

        QUE_put(dev->fromdevice, frame);
        QUE_put(otherdev->fromdevice, otherframe);

        /*
         * frames reclaimed from an output device must have size 0.
         */
        if (dev->mode != DEV_INPUT) {
            frame->size = 0;
        }
        else {
            otherframe->size = 0;
        }
#else
        QUE_put(dev->fromdevice, otherframe);
        QUE_put(otherdev->fromdevice, frame);

        /*
         * frames reclaimed from an output device must have size 0.
         */
        if (dev->mode != DEV_INPUT) {
            otherframe->size = 0;
        }
        else {
            frame->size = 0;
        }
#endif
    }
    else {
        /* done with atomic stuff */
        TSK_enable();
    }

    SEM_post(pipe->toSem);

    if (otherReady != NULL) {
        SEM_post(otherReady);
    }

    return SYS_OK;
}