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

📄 xsac97ctrl.c

📁 嵌入式系统关于串口传输、触摸屏、定时器、控制器、中断处理、音频控制等实验代码
💻 C
📖 第 1 页 / 共 4 页
字号:
*  4.  Perform the first (dummy) read from the processor memory location that is
*      mapped to the target Codec's target register.  Discard the resulting data
*  5.  Continuously check the AC '97 Controller's Global Status Register until
*      the SDONE bit is set.  Use software timeout logic.
*  6.  If the Read Completion Status bit is set or the software timeout has 
*      occurred, there is a timeout.
*      a)  Declare an error status 
*      b)  Skip to step 8 in this procedure.
*  7.  If there was no timeout, the read operation was successful.
*      a)  Read the CAR until it is verified that no codec I/O accesses are
*          currently in progress.  This also claims the next codec I/O
*          transaction for this operation.  It leaves an indication for the 
*          next SW read or write I/O operation.  This will prevent ambiguity.
*          (We shouldn't actually have to loop here because the SDONE bit 
*           indicator ought to be set at the same time as the CAR indicator
*           clears.  But we loop anyway, just in case.)
*      b)  Perform the second read to obtain the register contents reported by
*          the codec.
*      c)  Report the data obtained from the codec.
*  8.  Restore previous interrupt state. 
*  9.  Report success or error status.
*  
*  Note that this operation does not wait for the second read operation to
*   complete.  Any remaining wait is done in the beginning of the next access.
* 
*  Note also that there is a possible optimization in this processor for reads 
*   of a modem's GPIO bits that are reported to the controller in time slot 12.
*   It would be to skip the timeout logic and the second read cycle because the
*   local values are constantly updated from the values reported in TS 12.
*  
*  Once the link is acquired, perform the double read under interrupt 
*   protection.  This is necessary to make it an atomic operation.  Even
*   if link acquisition continued for @@@
*  
*******************************************************************************
*/

UINT32 XsAc97CtrlReadCodecReg (XsAc97CtrlCodecModemIdT  ac97DeviceId, 
                               AC97MixerRegisterIdT     targetRegister, 
                               UINT32*                  mixerRegValueP)
{
    UINT32    status ;
    INT       badParamNum  = 0; // Which param had error.  Assume no errors.
    INT       timeoutLoc   = 0; // What point had a timeout.  Assume no errors.
    BOOL      gotLink;
    VUINT32   readFinishedStatus;
    UINT32    irqIntState;
    UINT32    rcsErrTmp;
    INT       minorIterations;
    INT       retries   =   0;  
    XsAc97CtrlStatsT* codeStatsP;
    VUINT32*  mixerRegsAccessP;

    status = Ac97CheckRegId (targetRegister);

    if (status)
    {
        badParamNum = 2;
    }
    else    // register ID OK, set register access pointer to codec access base
    {
        switch (ac97DeviceId)
        {
            case XS_AC97CTRL_CM_ID_PRI_CODEC:
                mixerRegsAccessP  = &XsAc97CtrlRegsP->
                                            XsAC97CtrlMixerRegsPrimaryAud[0];
                codeStatsP = &XsAc97CtrlContext.statistics[ac97DeviceId];
                break;
            default:
                status      = ERR_T_ILLPARAM;
                badParamNum = 1;
                break;
        }
        // Point to specified register within area mapped to target codec regs
        mixerRegsAccessP += (targetRegister / XS_AC97CTRL_MIXER_REGS_PER_WORD);

    } // else (register ID OK)

    if (!status)
    {
        // Some statistics.  Only valid invocations are interesting.
        irqIntState = XsIcDisableInterruptsIrq();
        codeStatsP->readCodecNumInvocations++;     
        XsIcRestoreInterruptsIrq (irqIntState);

        do
        {
            status = ERR_NONE;      // Clear for possible retry
            // Protect entire operation for simplicity.  Very small extra
            //  execution time penalty.
            irqIntState = XsIcDisableInterruptsIrq();

            // 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
            {
                status = 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
                    status      = ERR_T_TIMEOUT;
                    timeoutLoc  = 1;                // First timeout opportunity
                }
                else  // OK to do real read
                {
                    if (!gotLink)                   // Didn't get the ACLINK
                    {
                        status = 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 && (status)); 

        // Some statistics
        irqIntState = XsIcDisableInterruptsIrq();
        codeStatsP->readCodecTotalRetries += retries -1; // Adjust for post-increment

        if (status)
        {
            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 (!status): got past initial parameter checks


    if (status)
    {

//        LOGERROR (XsAc97CtrlContext.loggedError,
  //          ERR_L_XSAC97CTRL, 
    //        ERR_S_XSAC97CTRL_CODEC_READ, 
      //      status,
        //    badParamNum, 
          //  timeoutLoc, 
            //targetRegister)
    }

    return (status);

} // 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);
*
*******************************************************************************
*/

UINT32  XsAc97CtrlColdReset (void)
{ 
    UINT32   status            = ERR_NONE; 
    INT      numCodecsReady;
    BOOL     primaryCodecReady; 
    INT      timeRemaining; 
    UINT32   irqIntState;

    // Activate cold reset line under interrupt protection
    irqIntState = XsIcDisableInterruptsIrq();   // Begin atomic zone.

    XsAc97CtrlRegsP = (XsAc97CtrlRegsT *) XS_AC97CTRL_REGISTER_BASE;

    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)
    {
        status = ERR_T_TIMEOUT;
//        LOGERROR (XsAc97CtrlContext.loggedError, ERR_L_XSAC97CTRL, 
  //          ERR_S_XSAC97CTRL_COLD_RESET, status, 0, 0, 0);
    }

    return (status);

} // XsAc97CtrlColdReset ()


/*
*******************************************************************************
*

⌨️ 快捷键说明

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