📄 xsac97ctrl.c
字号:
* 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 + -