⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xsac97ctrl.c

📁 优龙YLP270开发板 光盘自带的BIOS和实验例程源码 强烈推荐
💻 C
📖 第 1 页 / 共 5 页
字号:
* PROTOTYPE:        void XsAc97CtrlInterruptHandler (void *);
*
*******************************************************************************
* DESIGN:
*
*    Assume performed under interrupt protection
*
*    For each interrupt recorded as enabled:
*      - Determine if that interrupt trigger is active; if it is,
*        - Clear the triggering status
*        - Call the corresponding registered client interrupt handler
*           - No registered callback causes ERR_T_NO_HANDLER error in status
*
*    If there is no interrupt recorded as enabled:
*      - status is ERR_T_NO_HANDLER
*      - clear all active interrupt triggering conditions and check for
*         enabled interrupt reasons, disabling any.
*      - if there was no hardware-enabled interrupt reason, status becomes
*         ERR_T_NO_INT_REASON
*      - log an error
*
*    Special processing required:
*      - Clearing the status for Codec Ready interrupts: this can't be done.
*          Deactivate the triggered Codec Ready int (Primary or Secondary).
*          Special processing also needed in client handler, possibly
*          including unregistering of handler and notification of
*          non-interrupt level software.
*      - Calling the registered Read Status Done client interrupt handler.
*          For this interrupt, also get the value of the time-out flag for
*          the read transaction and pass that to the client handler.
*
*******************************************************************************
*/
/*
static
void XsAc97CtrlInterruptHandler (void *XsAc97CtrlContextP)
{
    ErrorT retVal = ERR_L_RSVD_FAIL;    // General failure, must prove success.
    UINT32 intIsHardwareEnabled;        // Used during general error probing.

    UINT32                   indicationStatus;
    XsAc97CtrlStatusEntryT*  currIntTypeEntryP;    // Access to interrupt table
    XsAc97CtrlIntIdT         thisInterruptType;
    XsAc97CtrlStatusIdT      statusIdForInterruptType;
    XsAc97CtrlIntIdT         unHandledInterruptType = 0;


    // Check all interrupt types.
    for (thisInterruptType = 0;
        thisInterruptType <= XS_AC97CTRL_INT_MAX;
        thisInterruptType++ )
    {
        // Map interrupt type ID onto status IDs and get pointer into table.
        statusIdForInterruptType =
            XsAc97CtrlIntToStatusTransTbl[thisInterruptType];
        currIntTypeEntryP = XsAc97CtrlStatusTable + statusIdForInterruptType;

        if (currIntTypeEntryP->intIsEnabled)
        {
            // Check and clear the status that triggers this interrupt type.
            indicationStatus = XsAc97CtrlGetStatus(statusIdForInterruptType);

            if (indicationStatus)
            {   // Something to do.  All active indications are non-zero.

                // Perform special processing before calling client handlers
                if (XS_AC97CTRL_INT_PCRDY == thisInterruptType)
                {
                    // Any special processing for Primary Codec Ready interrupt
                }
                else if (XS_AC97CTRL_INT_SCRDY == thisInterruptType)
                {
                    // Any special processing for Secondary Codec Ready int
                }
                else if (XS_AC97CTRL_INT_SDONE == thisInterruptType)
                {
                    // For CODEC status done interrupt, need to give the
                    //  time-out status.  Nonzero for timeout.
                    indicationStatus = XsAc97CtrlGetStatus
                        (XS_AC97CTRL_STAT_RCS_ERR);
                } // End of special processing for certain interrupt types

                if (currIntTypeEntryP->registeredHandlerFnP)
                {
                    retVal = ERR_NONE;

                    // Finally, call the registered client handler for this type
                    (currIntTypeEntryP->registeredHandlerFnP) (
                    currIntTypeEntryP->registeredParamP,
                        indicationStatus);
                }
                else
                {
                    retVal                  = ERR_T_NO_HANDLER;
                    unHandledInterruptType  = thisInterruptType;
                }

            } // if (indicationStatus)
        } // if (currIntTypeEntryP->intIsEnabled)
    } // Check all interrupt types


    // If neither OK nor a known missing handler, we need to clear all
    //  conditions so that we don't starve the background level.  Either
    //  identify the type that was enabled in hardware but unhandled, or
    //  decide that there was no good reason for this interrupt.

    if (ERR_L_RSVD_FAIL == retVal)
    {
        retVal = ERR_T_NO_INT_REASON;   // New default error condition

        // Check all interrupt types for active, unhandled interrupt.
        for (thisInterruptType = 0;
            thisInterruptType <= XS_AC97CTRL_INT_MAX;
            thisInterruptType++ )
        {
            // Map interrupt type ID onto status IDs and get pointer into table
            statusIdForInterruptType =
                XsAc97CtrlIntToStatusTransTbl[thisInterruptType];
            currIntTypeEntryP = XsAc97CtrlStatusTable +
                statusIdForInterruptType;

            // Check hardware enabled state.  All are single bit, active high.
            intIsHardwareEnabled = *currIntTypeEntryP->clearRegisterP
                & (1u << currIntTypeEntryP->enableBitShift);

            if (intIsHardwareEnabled)
            {
                // Interrupt type is enabled.  Now check indicator status.
                if (XsAc97CtrlGetStatus (statusIdForInterruptType))
                {
                    // Found unhandled interrupt type.  Disable and record.

                    // Known good interrupt type ID, so ignore return value.
                    (void) XsAc97CtrlDisableIntType (statusIdForInterruptType);
                    retVal                  = ERR_T_NO_HANDLER;
                    unHandledInterruptType  = thisInterruptType;
                }
            } // if (intIsHardwareEnabled)

        } // Check all interrupt types for active, unhandled interrupt type.
    } // if (ERR_L_RSVD_FAIL == retVal): end of unknown reason checking

    if (retVal)
    {
        LOGERROR (  XsAc97CtrlContext.loggedError,
            ERR_L_XSAC97CTRL,
            ERR_S_XSAC97CTRL_INT_HANDLER,
            retVal,
            unHandledInterruptType, 0, 0)

    } // status non-zero (error exists)

} // End XsAc97CtrlInterruptHandler ()
*/

/*
*******************************************************************************
*
* FUNCTION:         XsAc97CtrlClearStatus
*
* DESCRIPTION:      Clears the specified status indicator, if possible.  (Some
*                   are, by design, unclearable).  (Can't verify that the
*                   indication has cleared because the clearing mechanism
*                   is not always the same as the reporting mechanism.)
*
*                   Should not be used for status types that are currently in
*                   use as interrupt triggers.
*
* INPUT PARAMETERS: XsAc97CtrlStatusIdT statusId: ID of indicator to clear
*
* RETURNS:          Success: 0 (ERR_NONE)
*                   Failure: ERR_T_ILLPARAM - Status indicator ID out of range
*
* GLOBAL EFFECTS:   1) Because the status indicator is cleared, it will not be
*                       available to trigger an interrupt.
*                   2) If the specified status ID is invalid, an error is
*                       logged in the error log and the context structure.
*
* ASSUMPTIONS:      - Assumes that interrupt protection exists when called.
*                   - We don't have to double-check the hardware by making sure
*                     that a clearable status actually cleared.
*
* CALLS:
*
* CALLED BY:
*
* PROTOTYPE:        UINT32 XsAc97CtrlGetStatus (XsAc97CtrlStatusIdT);
*
*******************************************************************************
*/

static
ErrorT XsAc97CtrlClearStatus (XsAc97CtrlStatusIdT statusId)
{
    ErrorT retVal;
    XsAc97CtrlStatusEntryT* statusTableEntryP;


    retVal = XsAc97CtrlRangeCheckStatusId (statusId);

    if (retVal)
    {
        LOGERROR ( XsAc97CtrlContext.loggedError,
            ERR_L_XSAC97CTRL,
            ERR_S_XSAC97CTRL_CLEAR_STATUS,
            retVal, 0, 0, 0)
    }
    else
    {
        statusTableEntryP = XsAc97CtrlStatusTable + statusId;

        // Clear the indication if it can be cleared
        // NULL clear register means it can't be cleared.
        if (statusTableEntryP->clearRegisterP)
        {
            //  Write a shifted "1" to clear the status.  Don't "OR" it in.
            *statusTableEntryP->clearRegisterP =
                1u << statusTableEntryP->clearBitShift;
        }
    }  // else (rangeCheckResult)

    return (retVal);

} // XsAc97CtrlClearStatus()




/*
*******************************************************************************
*
* FUNCTION:         XsAc97CtrlRangeCheckIntTypeId
*
* DESCRIPTION:      Report whether the interrupt type ID is valid.
*
* INPUT PARAMETERS: XsAc97CtrlIntIdT   intTypeId  - AC '97 interrupt type ID
*                                                   to range-check
*
* RETURNS:          Success: 0 (ERR_NONE)
*                   Failure: ERR_T_ILLPARAM  - Interrupt type ID out of range
*                            ERR_T_NOT_AVAIL - Interrupt type ID unsupported
*
* GLOBAL EFFECTS:   None
*
* ASSUMPTIONS:      None
*
* CALLS:
*
* CALLED BY:
*
* PROTOTYPE:        UINT32 XsAc97CtrlRangeCheckIntTypeId (XsAc97CtrlIntIdT);
*
*******************************************************************************
*/
ErrorT XsAc97CtrlRangeCheckIntTypeId (XsAc97CtrlIntIdT interruptTypeId)
{
    ErrorT retVal = ERR_NONE;
    BOOL isSupported;

    if ((interruptTypeId < 0 )|| (interruptTypeId > XS_AC97CTRL_INT_MAX))
    {
        retVal = ERR_T_ILLPARAM;
    }
    else
    {
        // Map interrupt type ID onto status IDs and get supported status
        isSupported = XsAc97CtrlStatusTable
            [ XsAc97CtrlIntToStatusTransTbl [ interruptTypeId ]]
            .intIsSupported;
        if (FALSE == isSupported)
        {
            retVal = ERR_T_NOT_AVAIL;
        }
    }
    return(retVal);

} // XsAc97CtrlRangeCheckIntTypeId ()

/*
*******************************************************************************
*
* FUNCTION:         XsAc97CtrlRangeCheckStatusId
*
* DESCRIPTION:      Report whether the status indicator ID is valid.
*
* INPUT PARAMETERS: XsAc97CtrlStatusIdT   statusIndicatorId
*                                   - AC '97 status indicator ID to range-check
*
* RETURNS:          Success: 0 (ERR_NONE)
*                   Failure: ERR_T_ILLPARAM - Status indicator ID out of range
*
* GLOBAL EFFECTS:   None
*
* ASSUMPTIONS:      None
*
* CALLS:
*
* CALLED BY:
*
* PROTOTYPE:        UINT32 XsAc97CtrlRangeCheckStatusId (XsAc97CtrlStatusIdT);
*
*******************************************************************************
*/
static
ErrorT XsAc97CtrlRangeCheckStatusId (XsAc97CtrlStatusIdT statusIndicatorId)
{
    ErrorT retVal = ERR_NONE;
    
    if ((statusIndicatorId < 0 )|| (statusIndicatorId > XS_AC97CTRL_STAT_MAX))
    {
        retVal = ERR_T_ILLPARAM;
    }
    return(retVal);

} // XsAc97CtrlRangeCheckStatusId ()


/*
*******************************************************************************
*
* FUNCTION:         XsAc97CtrlSetStatusEntry
*
* DESCRIPTION:      Initialize one entry in the XsAc97CtrlStatusTable.
*                   Force to disabled, with no registered handler or param.
*                   All other entry values come from parameters.
*
* INPUT PARAMETERS: None
*
* RETURNS:          None
*
* GLOBAL EFFECTS:   None
*
* ASSUMPTIONS:
*
* CALLS:
*
* CALLED BY:        Only XsAc97CtrlSWInit
*
* PROTOTYPE:        void XsAc97CtrlSetStatusEntry ( XsAc97CtrlStatusEntryT*,
*                                                   INT,
*                                

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -