📄 xsac97ctrl.c
字号:
* when a specified AC'97 interrupt type occurs. Also
* register a pointer that will be passed to that handler.
*
* Critical section is performed under interrupt protection.
*
* INPUT PARAMETERS:
* XsAc97CtrlIdT interruptTypeId - int type to register handler for
* XsAc97CtrlHandlerFnPT clientHandlerFnP - Handler to be called for int.
* void * paramP - Pointer to be passed to reg. handler
*
* RETURNS:
* Success: 0 (ERR_NONE)
* Failure: ERR_T_ILLPARAM - Interrupt type ID out of range
* ERR_T_NOT_AVAIL - Interrupt type ID unsupported
* ERR_T_REG_HANDLER - pin already has a registered handler
*
* GLOBAL EFFECTS:
* - Required for XsAc97CtrlEnableIntType().
* - Records last detected failure condition
*
* ASSUMPTIONS:
*
* CALLS:
*
* CALLED BY:
*
* Notes:
* - Does not enable the interrupt: use XsAc97CtrlEnableIntType() afterwards.
*
* PROTOTYPE: UINT32 XsAc97CtrlRegisterHandler (XsAc97CtrlIdT,
* XsAc97CtrlHandlerFnPT,
* void *)
*
*******************************************************************************
*/
ErrorT XsAc97CtrlRegisterHandler ( XsAc97CtrlIntIdT interruptTypeId,
XsAc97CtrlHandlerFnPT clientHandlerFnP,
void * paramP)
{
ErrorT retVal;
UINT32 irqIntState;
XsAc97CtrlStatusEntryT* currIntTypeCfgP;
retVal = XsAc97CtrlRangeCheckIntTypeId (interruptTypeId);
irqIntState = XsIcDisableInterruptsIrq(); // Begin atomic zone.
if (!retVal)
{ // Interrupt type ID is safe. Check other conditions.
// Map interrupt type ID onto retVal IDs and get pointer into table.
currIntTypeCfgP = XsAc97CtrlStatusTable +
XsAc97CtrlIntToStatusTransTbl[interruptTypeId];
if (currIntTypeCfgP->registeredHandlerFnP)
{
retVal = ERR_T_REG_HANDLER; // Can't overwrite existing hndlr
}
}
if (retVal)
{
LOGERROR (XsAc97CtrlContext.loggedError, ERR_L_XSAC97CTRL,
ERR_S_XSAC97CTRL_REG_HANDLER, retVal, 0, 0, 0)
}
else // No problems, register the handler.
{
currIntTypeCfgP->registeredHandlerFnP = clientHandlerFnP;
currIntTypeCfgP->registeredParamP = paramP;
}
XsIcRestoreInterruptsIrq (irqIntState); // End atomic zone.
return (retVal);
} // XsAc97CtrlRegisterHandler ()
/*
*******************************************************************************
*
* FUNCTION: XsAc97CtrlUnRegisterHandler
*
* DESCRIPTION: Disable any interrupt of the specified AC '97 Controller
* interrupt type and unregister any registered handler for it.
* The only error is out-of-range interrupt type ID;
*
* INPUT PARAMETERS: XsAc97CtrlIdT interruptTypeId - AC'97 interrupt type
* to unregister handler for
*
* 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 XsAc97CtrlUnRegisterHandler (XsAc97CtrlIdT);
*
*******************************************************************************
*/
ErrorT XsAc97CtrlUnRegisterHandler (XsAc97CtrlIntIdT interruptTypeId)
{
ErrorT retVal ;
UINT32 irqIntState ;
XsAc97CtrlStatusEntryT* currIntTypeCfgP ;
irqIntState = XsIcDisableInterruptsIrq(); // Begin atomic zone.
// Also checks interruptTypeId
retVal = XsAc97CtrlDisableIntType (interruptTypeId);
if (retVal)
{
LOGERROR (XsAc97CtrlContext.loggedError, ERR_L_XSAC97CTRL,
ERR_S_XSAC97CTRL_UNR_HANDLER, retVal, 0, 0, 0)
}
else // Interrupt disabled for interrupt type. Unregister.
{
// Map interrupt type ID onto retVal IDs and get pointer into table.
currIntTypeCfgP = XsAc97CtrlStatusTable +
XsAc97CtrlIntToStatusTransTbl[interruptTypeId];
currIntTypeCfgP->registeredHandlerFnP = NULL;
currIntTypeCfgP->registeredParamP = NULL;
}
XsIcRestoreInterruptsIrq (irqIntState); // End atomic zone.
return(retVal);
} // XsAc97CtrlUnRegisterHandler ()
/*
*******************************************************************************
*
* FUNCTION: XsAc97CtrlEnableIntType
*
* DESCRIPTION: Enable interrupts for the specified AC '97 Controller
* interrupt type. An interrupt handling subroutine must
* already be registered. Performed under interrupt protection.
* Clears any existing interrupt triggering indication on
* specified interrupt type before enabling.
*
* Gracefully does nothing if already enabled.
*
* INPUT PARAMETERS: XsAc97CtrlIntIdT interruptTypeId - ID for AC '97 interrupt
* type to enable
*
* RETURNS:
* Success: 0 (ERR_NONE)
* Failure: ERR_T_ILLPARAM - Interrupt type ID out of range
* ERR_T_NOT_AVAIL - Interrupt type ID unsupported
* ERR_T_NO_HANDLER - interrupt type lacks a registered handler
*
* GLOBAL EFFECTS: None
*
* ASSUMPTIONS:
*
* CALLS: XsAc97CtrlCheckStatus
* XsAc97CtrlRangeCheckIntTypeId
*
* CALLED BY:
*
* PROTOTYPE: UINT32 XsAc97CtrlEnableIntType (XsAc97CtrlIdT);
*
*******************************************************************************
*/
ErrorT XsAc97CtrlEnableIntType (XsAc97CtrlIntIdT interruptTypeId)
{
ErrorT retVal ;
UINT32 irqIntState ;
XsAc97CtrlStatusEntryT* currIntTypeCfgP;
// Look for out of range IDs and non-supported IDs
retVal = XsAc97CtrlRangeCheckIntTypeId (interruptTypeId);
if (!retVal)
{ // Valid ID, type is supported.
// Map interrupt type ID onto retVal IDs and get pointer into table.
currIntTypeCfgP = XsAc97CtrlStatusTable +
XsAc97CtrlIntToStatusTransTbl[interruptTypeId];
// Only enable interrupts that have registered handlers.
if (NULL == currIntTypeCfgP->registeredHandlerFnP)
{
retVal = ERR_T_NO_HANDLER;
}
} // Finished if !retVal: all error states checked.
if (retVal)
{
LOGERROR (XsAc97CtrlContext.loggedError, ERR_L_XSAC97CTRL,
ERR_S_XSAC97CTRL_ENAB_INT, retVal, 0, 0, 0)
}
// Act only if currently disabled.
else if (FALSE == currIntTypeCfgP->intIsEnabled)
{
irqIntState = XsIcDisableInterruptsIrq(); // Begin atomic zone.
// Clear old indications that might trigger spurious interrupt.
// - Use side effect of status check subroutine.
(void) XsAc97CtrlGetStatus (
XsAc97CtrlIntToStatusTransTbl[interruptTypeId]);
// Enable int type: All AC '97 Controller interrupt type enables
// are active high and controlled by a single bit.
*currIntTypeCfgP->enableRegisterP |=
(1u << currIntTypeCfgP->enableBitShift);
currIntTypeCfgP->intIsEnabled = TRUE; // Record new state
XsIcRestoreInterruptsIrq (irqIntState); // End atomic zone.
} // Done else (retVal): range checked and supported, and if (not enabled).
return(retVal);
} // XsAc97CtrlEnableIntType ()
/*
*******************************************************************************
*
* FUNCTION: XsAc97CtrlDisableIntType
*
* DESCRIPTION: Disable, if currently enabled, interrupts for the specified
* AC '97 Controller interrupt type. Performed under
* interrupt protection.
*
* No-ops gracefully if not enabled.
*
* INPUT PARAMETERS: XsAc97CtrlIntIdT interruptTypeId - ID for AC '97 interrupt
* type to disable
*
* 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:
* CALLS:
*
* CALLED BY:
*
* PROTOTYPE: UINT32 XsAc97CtrlDisableIntType (XsAc97CtrlIntIdT);
*
*******************************************************************************
*/
ErrorT XsAc97CtrlDisableIntType (XsAc97CtrlIntIdT interruptTypeId)
{
ErrorT retVal ;
UINT32 irqIntState;
XsAc97CtrlStatusEntryT* currIntTypeCfgP;
retVal = XsAc97CtrlRangeCheckIntTypeId (interruptTypeId);
if (retVal)
{
LOGERROR (XsAc97CtrlContext.loggedError, ERR_L_XSAC97CTRL,
ERR_S_XSAC97CTRL_DISAB_INT, retVal, 0, 0, 0)
}
else
{
// Map interrupt type ID onto retVal IDs and get pointer into table.
currIntTypeCfgP = XsAc97CtrlStatusTable +
XsAc97CtrlIntToStatusTransTbl[interruptTypeId];
irqIntState = XsIcDisableInterruptsIrq(); // Begin atomic zone.
if (TRUE == currIntTypeCfgP->intIsEnabled)
{
// All AC '97 Controller interrupt type enables are active high
// and controlled by a single bit.
*currIntTypeCfgP->enableRegisterP &=
~(1u << currIntTypeCfgP->enableBitShift);
currIntTypeCfgP->intIsEnabled = FALSE; // Record new state
} // Was enabled, so disabled it.
XsIcRestoreInterruptsIrq (irqIntState); // End atomic zone.
} // Finished else (retVal): parameter range checked
return(retVal);
} // XsAc97CtrlDisablePinInt ()
/*
*******************************************************************************
*
* FUNCTION: XsAc97CtrlGetStatus
*
* DESCRIPTION: Reports the value of the specified status indicator, as
* obtained from the ACUNIT's GSR register. Clears the
* status indicator, if possible, after reading it.
*
* Should not be used for status types that are currently in
* use as interrupt triggers.
*
* INPUT PARAMETERS: XsAc97CtrlStatusIdT statusId: ID of status indicator to get
*
* RETURNS: Status indicator masked and normalized to bit 0.
* Invalid ID: 0 (There is no direct reporting of invalid ID error).
*
* 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: 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);
*
*******************************************************************************
*/
ErrorT XsAc97CtrlGetStatus (XsAc97CtrlStatusIdT statusId)
{
UINT32 statusIndication = 0; // Assume bad ID
UINT32 rangeCheckResult;
XsAc97CtrlStatusEntryT* statusTableEntryP;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -