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

📄 ac97.c

📁 pxa270触摸屏驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:

// Ac97StartFifo actually touches the hardware.  It assumes (verifies) 
//  that Ac97OpenFifo has been performed.
// All Fifo-related interrupts are assumed to be inactive when this routine
//  is called.  That is a responsibility of Ac97StopFifo().

// @@@ Note: May need to zero all buffers before (re)use.

UINT32 Ac97StartFifo (Ac97FifoProcessingInfoT* fifoInfoP)
{
    UINT32 status = ERR_NONE;
    UINT32 errLoc = 0;          // Assume no errors
                                

    DM_CwDbgPrintf(DM_CW_AC97_CODEC, 
                "Ac97StartFifo: Fifo, ID = %d; Addr = %08X; Name = %s \n",
                 fifoInfoP->fifoId, (UINT32) fifoInfoP, fifoInfoP->fifoNameStrP);
    DM_CwDbgPrintf(DM_CW_AC97_CODEC, 
                "Fifo status word: %X\n",fifoInfoP->fifoStatus);

    // First, check various error conditions
    if (!(fifoInfoP->fifoStatus & AC97_FIFO_ST_OPEN))
    {
        status = ERR_T_WRONG_STATE; 
        errLoc = 1;
    }
    else if (fifoInfoP->fifoStatus & AC97_FIFO_ST_ACTIVE)
    {
        status = ERR_T_ALREADY_IN_USE;
        errLoc = 2;
    }

    /*
    ***************************************************************************
        Now, perform various software-only operations
    ***************************************************************************
    */

    if (!status)
    {
        // Fresh start.  No errors.  Init for new operations.
        // We have a DMA channel and maybe a descriptor-buffer chain.

///@@@ // Obtain needed descriptors and descriptor-buffer chains from DMA and 
    //  memalloc module.  Configure descriptor chains to our needs (closed 
    //  loop, bidirectional).
// getting DMA buffers?

        // First, make sure that this FIFO has the descriptor/buffer chain it needs
//@@@   //  for standard model
//        if (!(fifoInfoP->fifoStatus & AC97_FIFO_ST_DMA_LP_MODE))
//        {
//            Ac97SetUpDescriptors (fifoInfoP);
//        }


        // Then, set up descriptor chains for DMA loop mode if appropriate
// For first pass, just set up for DMA loop
        if (fifoInfoP->fifoStatus & AC97_FIFO_ST_DMA_LP_ABLE)
        {
            status = Ac97SetUpDmaLoopDescriptors (fifoInfoP);
        }
// Early development.  The "else" will go away.
        else
        {
            // Need to work out details of normal mode buffering.
            //  Do we need new/current link counts to look for changes?
            //  If so, how do we handle changes in the link count?
            //  Maybe two versions of "normal" to test just double buffering
            //  versus longer, glitch-protected chains.
            status = ERR_T_NOT_IMPLEMENTED;
            errLoc = 3;
            DM_CwDbgPrintf(DM_CW_AC97_CODEC, 
                "Error: %s FIFO not DMA Loopable, FifoStatus = %X\n",
                            fifoInfoP->fifoNameStrP ,fifoInfoP->fifoStatus);
        }
        // Now set up the descriptor chain to use
        if (!status)
        {
            if (fifoInfoP->fifoStatus & AC97_FIFO_ST_DMA_LP_MODE)
            {
                // Make DMA loop chain current.
                fifoInfoP->activeDescriptorRootP = 
                                            fifoInfoP->dmaLoopDescriptorRootP;
                DM_CwDbgPrintf(DM_CW_AC97_CODEC, 
                "Installing %08X as active descriptor\n",
                                            fifoInfoP->dmaLoopDescriptorRootP);
            }
            else
            {
                // Make normal chain current.  First make sure that we have
                //  one.  (To be done earlier in this function)
// @@@          fifoInfoP->activeDescriptorRootP = 
//                                      fifoInfoP->standardModeDescriptorRootP;
            }
        }
    }


    /*
    ***************************************************************************
        More software-only operations
    ***************************************************************************
    */

    if (!status)
    {
        // Register appropriate ISRs
        // Activate interrupts for registered types.

        Ac97ClearFifoStatus (fifoInfoP);

// Next four lines might be superflous, probably handled in fifo_close.
        fifoInfoP->clientBufP                   = 0;
        fifoInfoP->dmaDescriptorHwPaddrNextTmp  = 0;
        fifoInfoP->samplesProcessed             = 0;
        

        // Install FIFO error ISR if desired and needed.
        if ( (fifoInfoP->fifoStatus & 
                  (AC97_FIFO_ST_FIFO_ISR_MODE | AC97_FIFO_ST_FIFO_ISR_REG))
             == (AC97_FIFO_ST_FIFO_ISR_MODE ))
        {

            DM_CwDbgPrintf(DM_CW_AC97_CODEC, 
                        "Registering ISR with AC97 Controller\n");
            status = XsAc97CtrlRegisterHandler (fifoInfoP->fifoInterruptId,
                                                Ac97FifoInterruptHandler,
                                                (void *) fifoInfoP);
            if (status)
            {
                // Bad interrupt type ID or handler already registered.
                //  Log the bug and don't cover it up.  Get it fixed.
                //  However, make sure that we clean up.
                errLoc = 4;
                // Already caught the error.
                (void) XsAc97CtrlUnRegisterHandler (fifoInfoP->fifoInterruptId);

                Ac97WriteFifoStatus (fifoInfoP, 
                                     AC97_FIFO_ST_FIFO_ISR_REG,
                                     AC97_CLEAR);
            }
            else
            {
                Ac97WriteFifoStatus (fifoInfoP, 
                                     AC97_FIFO_ST_FIFO_ISR_REG,
                                     AC97_SET);
            }
        } // if (installing FIFO error ISR)
     } // if (!status): preliminary error checks passed

     if (!status)
     {
        // Now, make sure that we have the specified buffer and DMA 
        //  configuration in place.  (buffers already allocated). 
        //  This includes having an appropriate
        //  set of interrupt handlers registered.

        // Register DMA status ISR if desired and needed.
        // Then activate it.  Assume that DMA is stopped; that's a condition
        //  for calling this function.
        //  For now, just use default that reports events in FIFO structure

        if (   !status 
            && (fifoInfoP->fifoStatus & AC97_FIFO_ST_DMA_ISR_MODE)
            && !(fifoInfoP->fifoStatus & AC97_FIFO_ST_DMA_ISR_REG))
        {
            status = XsDmaRegisterHandler (fifoInfoP->dmaChannel, 
                                         Ac97DefaultDmaInterruptHandler, 
                                         fifoInfoP);
            if (status)
            {
                errLoc = 5;
            }
            else
            {
                Ac97WriteFifoStatus (fifoInfoP, 
                                     AC97_FIFO_ST_DMA_ISR_REG,
                                     AC97_SET);
            }
        }
                
        /*
        ***********************************************************************
            Finally, begin the actual DMA operation
        ***********************************************************************
        */
        if (!status)
        {
            // Now, enable the DMA interrupts and wait for the
            //  "stopped" interrupt to occur.

            fifoInfoP->ac97DcsrStopIntrs = 0;  // Set up for ready-wait

            // (void): Just passed all error checks immediately above.
            (void) XsDmaIntReasonEnable(fifoInfoP->dmaChannel,
                                        (DCSR_BUSERRINTR |
                                         DCSR_STARTINTR  |
                                         DCSR_ENDINTR    |
                                         DCSR_STOPINTR    ));

            (void) XsDmaLoadFirstDescriptorAddr(fifoInfoP->dmaChannel, 
                                            fifoInfoP->activeDescriptorRootP);

            (void) XsDmaStart (fifoInfoP->dmaChannel);


            status = Ac97WaitForDmaStart (fifoInfoP);

            if (status)
            {
                errLoc = 6;
            }
            else
            {
                Ac97WriteFifoStatus (fifoInfoP, 
                                     AC97_FIFO_ST_DMA_RUNNING,
                                     AC97_SET);
            } // else (:successfully registered handler for DMA interrupt)

        } // if (need to install DMA status ISR)

    } // if (!status): succeeded in installing FIFO error ISR

    if (status)
    {
        LOGERROR (fifoInfoP->parentAc97ctxP->loggedError, 
                  ERR_L_AC97,
                  ERR_S_AC97_START_FIFO,
                  status,
                  fifoInfoP->fifoId,
                  errLoc,
                  0)
        DM_CwDbgPrintf(DM_CW_AC97_CODEC, 
                "Error Code: %X\n", fifoInfoP->parentAc97ctxP->loggedError);
        DM_CwDbgPrintf(DM_CW_AC97_CODEC, 
                "Error loc: %X\n", errLoc);
    }
    else
    {
        // Don't declare active until all operations performed successfully.
        Ac97WriteFifoStatus (fifoInfoP, 
                             AC97_FIFO_ST_ACTIVE,
                             AC97_SET);
        DM_CwDbgPrintf(DM_CW_AC97_CODEC, 
                "Success activating FIFO\n");
    }

    DM_CwDbgPrintf(DM_CW_AC97_CODEC, 
                "End of Ac97StartFifo: FifoName = %s, Status word: %X \n",
                 fifoInfoP->fifoNameStrP, fifoInfoP->fifoStatus);

    return(status);

} // Ac97StartFifo ()


// Graceful termination of DDMA, not instantaneous.  Operates by setting the 
// Stop bits in the nextPhysicalAddr fields of all descriptors in current
// chain.  Minimum delay is 1 buffer time; maximum is 2 buffer times.

UINT32 Ac97StopFifo (Ac97FifoProcessingInfoT* fifoInfoP)
{
    UINT32 status = ERR_NONE;

    DM_CwDbgPrintf(DM_CW_AC97_CODEC, 
                "Begin Ac97StopFifo(). Fifo status word: %X, Active mask: %X",
                                      fifoInfoP->fifoStatus,AC97_FIFO_ST_ACTIVE);
    DM_CwDbgPrintf(DM_CW_AC97_CODEC, 
                "Fifo IDs: %d, %s,",
                     fifoInfoP->fifoId,
                     fifoInfoP->fifoNameStrP);

    // No-op gracefuly if inactive.
    if (fifoInfoP->fifoStatus & AC97_FIFO_ST_ACTIVE)
    {
        // Prepare Stop bit to become active after next descriptor load.
        (void) XsDmaOperateOnChain (fifoInfoP->dmaLoopDescriptorRootP, 
                                    XsDmaDescrSetStopBit);

        XsDmaDumpDescriptor (fifoInfoP->dmaLoopDescriptorRootP,
            DM_ControlWordsDebugPrintGetBit(DM_CW_AC97_CODEC));
        XsDmaDumpDescriptor(fifoInfoP->dmaLoopDescriptorRootP->nextVirtualAddr,
            DM_ControlWordsDebugPrintGetBit(DM_CW_AC97_CODEC));

//        @@@
        // Wait with standard 100 ms timeout for channel to stop.
        // This assumes knowledge of the timeout and that two buffer
        //   times is less than 
        status = XsDmaWaitUntilStopped (fifoInfoP->dmaChannel);

        // Don't declare inactive until everything has stopped.
        Ac97WriteFifoStatus (fifoInfoP, 
                             (AC97_FIFO_ST_ACTIVE      |
                              AC97_FIFO_ST_DMA_RUNNING),
                             AC97_CLEAR);
    }
    DM_CwDbgPrintf(DM_CW_AC97_CODEC, 
                "End Ac97StopFifo(). Fifo status word: %X, Active mask: %X",
                                      fifoInfoP->fifoStatus,AC97_FIFO_ST_ACTIVE);

    return (status);
    
} // Ac97StopFifo ()


// Slightly faster, still graceful DMA termination.  Write a dummy descriptor 
//  with 0 length and the stop bit set to the DDADR.
// Minimum delay is almost immediate; maximum is 1 buffer time.

UINT32 Ac97StopFifoQuick (Ac97FifoProcessingInfoT* fifoInfoP)
{
    UINT32 status = ERR_NONE;

    // No-op gracefuly if inactive.
    if (fifoInfoP->fifoStatus & AC97_FIFO_ST_ACTIVE)
    {

        (void) XsDmaLoadFirstDescriptorAddr(fifoInfoP->dmaChannel, 
                                            fifoInfoP->stopDescriptorRootP);

        // Wait with standard timeout for channel to stop.
        status = XsDmaWaitUntilStopped (fifoInfoP->dmaChannel);

        // Don't declare inactive until everything has stopped.
        Ac97WriteFifoStatus (fifoInfoP, 
                             (AC97_FIFO_ST_ACTIVE      |
                              AC97_FIFO_ST_DMA_RUNNING),
                             AC97_CLEAR);
    DM_CwDbgPrintf(DM_CW_AC97_CODEC, 
                "End Ac97StopFifoQuick(). Fifo status word: %X, Active mask: %X",
                                      fifoInfoP->fifoStatus,AC97_FIFO_ST_ACTIVE);
    }

    return (status);
    
} // Ac97StopFifoQuick ()



UINT32 Ac97OpenFifo (Ac97ContextT*             ctxP, 
                     Ac97FifoProcessingInfoT** fifoInfoAddrP,
                     XsAc97CtrlFifoIdT         fifoId)
{
    UINT32 status = ERR_NONE;
    UINT32 errLoc = 0;          // Assume no errors
    Ac97FifoProcessingInfoT* fifoInfoP = 
                                &ctxP->fifoProcessingInfoRecords[fifoId];

    DM_CwDbgPrintf(DM_CW_AC97_CODEC, 
                "Ac97OpenFifo: Fifo, ID = %d; Addr = %08X; Name = %s \n",
                 fifoId, (UINT32) fifoInfoP, fifoInfoP->fifoNameStrP);
    DM_CwDbgPrintf(DM_CW_AC97_CODEC, 
                "Fifo status word: %X\n",fifoInfoP->fifoStatus);


    // First, check various error conditions
    if (!fifoInfoP->isSupported)
    {
        status = ERR_T_NOT_IMPLEMENTED; 
        errLoc = 1;
    }
    else if (fifoInfoP->fifoStatus & AC97_FIFO_ST_OPEN)
    {
        status = ERR_T_ALREADY_IN_USE;
        errLoc = 2;

⌨️ 快捷键说明

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