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

📄 xsac97ctrl.c

📁 优龙YLP270开发板 光盘自带的BIOS和实验例程源码 强烈推荐
💻 C
📖 第 1 页 / 共 5 页
字号:

            // 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 + -