📄 xsac97ctrl.c
字号:
// Lock the ACLINK
minorIterations = 0;
do
{
gotLink = XsAc97CtrlLockAcLink();
if (!gotLink) // 1 usec is a long time. Skip delay if possible.
{
DM_WaitUs(1);
}
}
// Wait while time remaining and ACLINK not available
while ( (minorIterations++ < XS_AC97CTRL_CAIP_TIMEOUT_1USECS)
&& !gotLink );
if (!gotLink) // Didn't get the ACLINK
{
retVal = ERR_T_NOT_AVAIL;
}
else // We got the link. Perform the read operations.
{
// First, clear old read status indications.
(void) XsAc97CtrlClearStatus (XS_AC97CTRL_STAT_SDONE);
(void) XsAc97CtrlClearStatus (XS_AC97CTRL_STAT_RCS_ERR);
*mixerRegValueP = *mixerRegsAccessP; // This is THE DUMMY READ.
// Wait for read I/O with codec to complete before doing real read.
minorIterations = 0;
do
{
DM_WaitUs(1);
readFinishedStatus =
XsAc97CtrlGetStatus (XS_AC97CTRL_STAT_SDONE);
}
// Wait while time remaining and read I/O still incomplete
// SDONE bit is high when done.
while ( (minorIterations++ < XS_AC97CTRL_READ_TIMEOUT_1USECS)
&& !readFinishedStatus);
// Another way to detect a timeout is to check the Read
// Completion Status bit in the GSR. It is set for a timeout.
rcsErrTmp = XsAc97CtrlGetStatus (XS_AC97CTRL_STAT_RCS_ERR);
if ( rcsErrTmp ||
!readFinishedStatus)
{
// Timed out on read
retVal = ERR_T_TIMEOUT;
timeoutLoc = 1; // First timeout opportunity
}
else // OK to do real read
{
if (!gotLink) // Didn't get the ACLINK
{
retVal = ERR_T_TIMEOUT;
timeoutLoc = 2; // Second timeout opportunity
}
else // No problems. Perform the read operation.
{
*mixerRegValueP = *mixerRegsAccessP; // THE REAL READ.
}
} // else (OK to do real read)
} // else (We got the link. Perform the read operations.)
XsIcRestoreInterruptsIrq (irqIntState); // End atomic zone.
} // do: try communication until retries run out or success.
while (retries++ < XS_AC97CTRL_CODEC_READ_RETRIES && (retVal));
// Some statistics
irqIntState = XsIcDisableInterruptsIrq();
codeStatsP->readCodecTotalRetries += retries -1; // Adjust for post-increment
if (retVal)
{
codeStatsP->readCodecNumFailures++;
}
else
{
// Clean up after real read. Why must we do it here instead
// of speculatively at the beginning of the read process?
// Need to investigate proper procedure.
minorIterations = 0;
do
{
DM_WaitUs(1);
readFinishedStatus =
XsAc97CtrlGetStatus (XS_AC97CTRL_STAT_SDONE);
}
// Wait while time remaining and read I/O still incomplete
// SDONE bit is high when done.
while ( (minorIterations++ < XS_AC97CTRL_READ_TIMEOUT_1USECS)
&& !readFinishedStatus);
}
XsIcRestoreInterruptsIrq (irqIntState);
} // if (!retVal): got past initial parameter checks
if (retVal)
{
LOGERROR (XsAc97CtrlContext.loggedError,
ERR_L_XSAC97CTRL,
ERR_S_XSAC97CTRL_CODEC_READ,
retVal,
badParamNum,
timeoutLoc,
targetRegister)
}
return (retVal);
} // XsAc97CtrlCodecRead ()
/*
*******************************************************************************
Non-standard, test-oriented API of main processor on-board
AC'97 controller driver. Lower level access provided.
*******************************************************************************
*/
/*
*******************************************************************************
*
* FUNCTION: XsAc97CtrlColdReset
*
* DESCRIPTION: Perform a cold reset of the processor's AC'97 Controller,
* the AC Link and all AC'97 codecs and modems attached to
* the controller's AC'97 cold reset pin.
*
* INPUT PARAMETERS: None
*
* RETURNS:
* Success: 0 (ERR_NONE); All codecs reported ready within time limit.
* Failure: ERR_T_TIMEOUT: A timeout occurred on one of the codecs.
* In systems with multiple codecs, the calling function
* could determine which device(s) is/are not ready by
* performing XsAc97CtrlGetStatus() on
* XS_AC97CTRL_STAT_PCRDY and XS_AC97CTRL_STAT_SCRDY.
*
* GLOBAL EFFECTS: All codecs initialized to default settings. Controller
* set to default state and is operational.
*
* ASSUMPTIONS: Not used in an interrupt service routine.
*
* CALLS:
*
* CALLED BY:
*
* PROTOTYPE: UINT32 XsAc97CtrlColdReset (void);
*
*******************************************************************************
*/
ErrorT XsAc97CtrlColdReset (void)
{
INT numCodecsReady;
BOOL primaryCodecReady;
INT timeRemaining;
UINT32 irqIntState;
XsAc97CtrlContext.loggedError = ERR_NONE;
// Activate cold reset line under interrupt protection
irqIntState = XsIcDisableInterruptsIrq(); // Begin atomic zone.
XsAc97CtrlRegsP->GCR &= ~(XS_AC97CTRL_GCR_COLD_RESET_MSK); // Activate
XsIcRestoreInterruptsIrq (irqIntState); // End atomic zone.
// Hold reset active for a minimum time
for (timeRemaining = 0 ;
timeRemaining < XS_AC97CTRL_COLD_HOLD_50USECS;
timeRemaining++ )
{
DM_WaitUs(50);
}
// Deactivate cold reset line
irqIntState = XsIcDisableInterruptsIrq(); // Begin atomic zone.
XsAc97CtrlRegsP->GCR |= XS_AC97CTRL_GCR_COLD_RESET_MSK; // Deactivate
XsIcRestoreInterruptsIrq (irqIntState); // End atomic zone.
// And wait with timeout for all codecs to respond.
numCodecsReady = 0; // Codecs plus modems.
primaryCodecReady = FALSE;
timeRemaining = XS_AC97CTRL_COLD_TIMEOUT_50USECS;
do
{
DM_WaitUs(50);
if ((!primaryCodecReady) && (XsAc97CtrlRegsP->GSR & XS_AC97CTRL_GSR_PCRDY_MSK))
{
// Note: Don't bother trying to clear the interrupt trigger for the
// primary codec ready status indicator. This is not an
// interrupt-based function.
primaryCodecReady = TRUE;
numCodecsReady ++;
}
// Note: Other codecs or modems would be checked here, if supported by
// the platform.
} // exit loop if timeout or all devices ready
while (timeRemaining-- && (numCodecsReady < XS_AC97CTRL_NUM_CODECS));
// Timeout status if some of the devices weren't ready.
if (numCodecsReady < XS_AC97CTRL_NUM_CODECS)
{
LOGERROR (XsAc97CtrlContext.loggedError, ERR_L_XSAC97CTRL,
ERR_S_XSAC97CTRL_COLD_RESET, ERR_T_TIMEOUT, 0, 0, 0);
}
return (XsAc97CtrlContext.loggedError);
} // XsAc97CtrlColdReset ()
/*
*******************************************************************************
*
* FUNCTION: XsAc97CtrlLockAcLink
*
* DESCRIPTION: Try to lock the AC Link for command/status accesses to a
* codec.
*
* INPUT PARAMETERS: None
*
* RETURNS: TRUE if the attempt was successful; FALSE if not.
*
* GLOBAL EFFECTS: If TRUE, the hardware indicator will show that the AC Link
* is locked until either a codec command or status I/O
* operation has completed, or XsAc97CtrlReleaseAcLink
* is called.
*
* ASSUMPTIONS:
*
* CALLS:
*
* CALLED BY:
*
* PROTOTYPE: BOOL XsAc97CtrlLockAcLink (void);
*
*******************************************************************************
*/
BOOL XsAc97CtrlLockAcLink (void)
{
BOOL status = TRUE;
VUINT32 carTmp;
carTmp = XsAc97CtrlRegsP->CAR;
if (carTmp & XS_AC97CTRL_CAIP_MSK) // "1" in CAIP bit means lock failed.
{
status = FALSE;
}
return (status);
} // XsAc97CtrlLockAcLink ()
/*
*******************************************************************************
*
* FUNCTION: XsAc97CtrlReleaseAcLink
*
* DESCRIPTION: Forced release of AC Link lock set by XsAc97CtrlLockAcLink
*
* INPUT PARAMETERS: None
*
* RETURNS: None
*
* GLOBAL EFFECTS:
*
* ASSUMPTIONS: Only used if the link has been locked but SW does not
* initiate a command or status query I/O on the link.
*
* CALLS:
*
* CALLED BY: Probably never used.
*
* PROTOTYPE: void XsAc97CtrlReleaseAcLink (void);
*
*******************************************************************************
*/
void XsAc97CtrlReleaseAcLink (void)
{
XsAc97CtrlRegsP->CAR = XS_AC97CTRL_CAIP_MSK;
}
/*
*******************************************************************************
Private functions for main processor on-board AC'97 controller driver
*******************************************************************************
*/
/*
*******************************************************************************
*
* FUNCTION: XsAc97CtrlInterruptHandler
*
* DESCRIPTION: For each enabled interrupt with a pending interrupt reason,
* clear the interrupt and dispatch any corresponding
* registered interrupt handling subroutines. Perform special
* processing as needed (see special processing list below).
*
* INPUT PARAMETERS: None
*
* RETURNS: None
*
* GLOBAL EFFECTS: Two serious error conditions are detected. In either case,
* the error is logged.
* ERR_T_NO_HANDLER: No handler registered for
* an activated AC '97 interrupt type. This is an
* AC'97 Controller module internal error. The ID of
* the unhandled type is recorded in the error log
*
* ERR_T_NO_INT_REASON: No interrupt type that was enabled
* in the hardware was found, so this AC'97 Controller
* interrupt should not have happened.
*
* ASSUMPTIONS: DM "owns" the AC '97 interrupts: No debug monitor
* considerations apply
*
* CALLS:
*
* CALLED BY:
*
* NOTES: Special handling is needed if the following interrupts are
* supported.
* XS_AC97CTRL_INT_PCRDY // Primary CODEC Ready (PCR)
* XS_AC97CTRL_INT_SCRDY // Secondary CODEC Ready (SCR)
* XS_AC97CTRL_INT_SDONE // Status Done (SDONE)
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -