/*  ============================================================================
 *  Copyright (c) Texas Instruments Inc 2002, 2003, 2004, 2005
 *
 *  Use of this software is controlled by the terms and conditions found in the
 *  license agreement under which this software has been supplied.
 *  ===========================================================================
 */

/** @file csl_dmaxOpen.c
 *
 *  @brief  File for functional layer of CSL API @a CSL_dmaxOpen()
 *
 *  Description
 *    - The @a CSL_dmaxOpen() function definition & it's associated functions
 *
 *  Modification 1
 *    - Created on: 10/March/2005
 *
 *  @author asr.
 */

#include <csl_dmax.h>

extern CSL_DmaxResourceAlloc CslDmaxAlloc;
/** ===========================================================================
 *   @n@b CSL_dmaxOpen
 *
 *   @b Description
 *   @n This function populates the peripheral data object for the instance
 *      and returns a handle to the instance. The open call sets up the data 
 *      structures for the particular instance of DMAX device. The device can 
 *      be re-opened anytime after it has been normally closed if so required.
 *      The handle returned by this call is input as an essential argument for 
 *      rest of the APIs described for this module. 
 * 
 *   @b Arguments
 *   @verbatim
 *
 *      pDmaxObj     Pointer to the DMAX instance object
 *      dmaxNum      Instance of the DMAX to be opened. 
 *      pDmaxParam   Pointer to module specific parameters
 *      pStatus      Pointer for returning status of the function call
 *       
 *   @endverbatim
 *
 *   <b> Return Value </b> CSL_DmaxHandle
 *
 *       - Valid Dmax instance handle will be returned if status value is
 *        equal to CSL_SOK else CSL_DMAX_BADHANDLE
 *
 *   <b> Pre Condition </b>
 *   @n  CSL_dmaxInit() has to be called
 *
 *   <b> Post Condition </b>
 *   @n  1.	The status is returned in the status variable. If status returned is
 *   @li            CSL_OK		       - Open call is successful
 *   @li            CSL_ESYS_INVPARAMS - If invalid parameter passed
 *   @li            CSL_ESYS_FAIL      - If invalid instance number
 *       2.	DMAX object structure is populated
 *
 *   @b Modifies
 *   @n@li  	The status variable
 *     @li  	DMAX object structure 
 *
 *   @b Example
 *   @verbatim
 *        CSL_status        status;
 *        CSL_DmaxObj       dmaxObj;
 *        CSL_DmaxHandle    hDmax;
 *
 *        hDmax = CSL_dmaxOpen (&dmaxObj,
 *                              CSL_DMAX_0,
 *                              NULL,
 *                              &status
 *                             );
     @endverbatim
 * ===========================================================================
 */

#pragma CODE_SECTION (CSL_dmaxOpen, ".text:csl_section:dmax");

CSL_DmaxHandle CSL_dmaxOpen (
    CSL_DmaxObj 	*pDmaxObj,
    CSL_InstNum 	dmaxNum,
    CSL_DmaxParam 	*pDmaxParam,
    CSL_Status 		*pStatus
)
{
    CSL_Status               status;
    CSL_DmaxHandle           hDmax;
    CSL_DmaxBaseAddress      baseAddress;

    CSL_DmaxAlloc	*allocPtr = (CSL_DmaxAlloc *) & CslDmaxAlloc;
    Uint32			ndx = (((pDmaxObj->eventUid) >> 28) & 0xFFFF) - 1;
    Uint32			flag = (pDmaxObj->eventUid & 0xFFFF);
    Uint32			mask = 1 << flag;
    Uint32			paramNdx =
        			(((pDmaxObj->paramUid) >> 28) & 0xFFFFu) - 1;
    Uint32          paramId = pDmaxObj->paramUid & 0xFFFF;

    hDmax = (CSL_DmaxHandle) CSL_DMAX_BADHANDLE;

    if (pStatus == NULL) {
        return hDmax;
    }

    if ((pDmaxObj == NULL) || (dmaxNum < CSL_DMAX)) {
        *pStatus = CSL_ESYS_INVPARAMS;
        return hDmax;
    }

    status = CSL_dmaxGetBaseAddress (dmaxNum, pDmaxParam, &baseAddress);

    if (status == CSL_SOK) {
        pDmaxObj->regs = baseAddress.regs;
        pDmaxObj->perNum = (CSL_InstNum) dmaxNum;
        if ((allocPtr[ndx].allocMap & mask) == 0) {
            allocPtr[ndx].allocMap = allocPtr[ndx].allocMap | mask;
            if (paramNdx != 0xFFFFFFFF) {
                if (paramId == 0xFFFF) {
                    paramId =
                        CSL_dmaxGetNextFreeParamEntry (pDmaxObj->paramUid,
                        &status);
                    pDmaxObj->paramUid &= (0xF0000000 | paramId);
                }
                if (paramId == (Uint32) CSL_ESYS_OVFL) {
                    *pStatus = CSL_EDMAX_PARAM_ENTRY_FULL_ERROR;
                    return (CSL_DmaxHandle) CSL_ESYS_BADHANDLE;
                }
                allocPtr[paramNdx].allocMap =
                    allocPtr[paramNdx].allocMap | (1u << paramId);
                pDmaxObj->paramPtr = CSL_DMAX_GET_PARAM_ENTRY_OFFSET (paramId);
            }
            pDmaxObj->hiTableEventEntryPtr =
                (Uint32 *) & (((Uint32 *) & (pDmaxObj->regs->
                        HiPriorityEventTable))[flag]);
            pDmaxObj->loTableEventEntryPtr =
                (Uint32 *) & (((Uint32 *) & (pDmaxObj->regs->
                        LoPriorityEventTable))[flag]);

            hDmax = (CSL_DmaxHandle) pDmaxObj;
            /* To remove compiler warning/remark. */
            *pDmaxParam = *pDmaxParam;
        }
		else {
			*pStatus = CSL_ESYS_OVFL;
			hDmax = (CSL_DmaxHandle) CSL_DMAX_BADHANDLE;
			return hDmax;
		}
    }
    else {
        pDmaxObj->regs = (CSL_DmaxRegsOvly) NULL;
        pDmaxObj->perNum = (CSL_InstNum) - 1;
    }

    *pStatus = status;
    return hDmax;
}
