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

📄 sdcontrol.cpp

📁 freescale i.mx31 BSP CE5.0全部源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    if (BspSdhcIsSdmaSupported(pHardwareContext->ControllerIndex) == TRUE)
    {
        // Release DMA Resources 
        DeInitDMA(pHardwareContext); 
    }

    // free the virtual space allocated for SDHC memory map
    if (pHardwareContext->pSDMMCRegisters != NULL)
    {
        MmUnmapIoSpace(pHardwareContext->pSDMMCRegisters, sizeof(CSP_SDHC_REG));
        pHardwareContext->pSDMMCRegisters = NULL;
    }
    DeleteCriticalSection(&pHardwareContext->ControllerCriticalSection);
    DEBUGMSG(ZONE_FUNCTION, (TEXT("-SDDeinitialize: \r\n")));
    return SD_API_STATUS_SUCCESS;
}
//------------------------------------------------------------------------------
//
// Function: SDHCancelIoHandler
//
// io cancel handler
//
// Parameters:
//      pHostContext[in] - host controller context
//		Slot[in]		 - slot the request is going on
//		pRequest[in]	 - the request to be cancelled
//
// Returns:
//      TRUE if the request was cancelled
//
//------------------------------------------------------------------------------
BOOLEAN SDHCancelIoHandler(PSDCARD_HC_CONTEXT pHCContext, 
                           DWORD              Slot, 
                           PSD_BUS_REQUEST    pRequest)
{
    PSDH_HARDWARE_CONTEXT    pController;
    DEBUGMSG(ZONE_FUNCTION, (TEXT("+SDHCancelIoHandler \n"))) ; 

    // for now, we should never get here because all requests are non-cancelable
    // the hardware supports timeouts so it is impossible for the controller to get stuck
    DEBUG_ASSERT(FALSE);

    // get our extension 
    pController = GetExtensionFromHCDContext(PSDH_HARDWARE_CONTEXT, pHCContext);

    // --- Stop hardware, cancel the request!

    // release the lock before we complete the request
    SDHCDReleaseHCLock(pHCContext);

    // complete the request with a cancelled status
    SDHCDIndicateBusRequestComplete(pHCContext,pRequest, SD_API_STATUS_CANCELED);
    DEBUGMSG(ZONE_FUNCTION, (TEXT("-SDHCancelIoHandler \n"))) ; 
    return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: SDHBusRequestHandler
//
// bus request handler. The request passed in is marked as uncancelable, this function
// has the option of making the outstanding request cancelable 
//
// Parameters:
//      pHostContext[in] - host controller context
//		Slot[in]		 - slot the request is going on
//		pRequest[in]	 - the request to be cancelled
//
// Returns:
//      SD_API_STATUS Code
//
//------------------------------------------------------------------------------
SD_API_STATUS SDHBusRequestHandler(PSDCARD_HC_CONTEXT pHCContext, 
                                   DWORD              Slot, 
                                   PSD_BUS_REQUEST    pRequest) 
{
    PSDH_HARDWARE_CONTEXT    pController;     // our controller
    DWORD                      cmdatRegister=0;   // CMDAT register

    // get our extension 
    pController = GetExtensionFromHCDContext(PSDH_HARDWARE_CONTEXT, pHCContext);

    DWORD  dwNumBytesToTransfer = pRequest->NumBlocks * pRequest->BlockSize;

    // DMA is not used for comands
    // DMA is not used for small data transfers (DmaMinTransfer)
    // DMA is not used for transfer sizes that are not 32-bit aligned
    if ((SD_COMMAND == pRequest->TransferClass) || 
        (dwNumBytesToTransfer < (pController->DmaMinTransfer)) ||
        (dwNumBytesToTransfer & 0x3))
    {
        pController->fDMATransfer = FALSE;
    }
    // Allow platform code to specify if DMA is supported
    else
    {
        pController->fDMATransfer = BspSdhcIsSdmaSupported(pController->ControllerIndex);
    }

    // Handle for ACMD 42/23. Our SDHC expects no reponse but spec say R1.
    //This is used during MX21 SDIO workaround. It might not be used during ARM11 hardware debugging 
    if ( (pRequest->CommandCode == SD_CMD_LOCK_UNLOCK && pController->fAppCommandSent == TRUE) ||
         (pRequest->CommandCode == SD_ACMD_SET_WR_BLOCK_ERASE_COUNT && pController->fAppCommandSent == TRUE))
    {
        pRequest->CommandResponse.ResponseType = NoResponse;
    }

    //Set the response type
    switch (pRequest->CommandResponse.ResponseType)
    {
    case NoResponse:
        CSP_BITFINS(cmdatRegister, SDHC_CDC_FORMAT, 0);
        break;      
        //ARM11 spec does not have busy bit register set. 
        //Need to check busy bit Hw implementation and handling.This affects commands with 
        //response R1b and for SDIOAbort transfers.
    case ResponseR1b:
    case ResponseR1:
    case ResponseR5:
    case ResponseR6:
        CSP_BITFINS(cmdatRegister, SDHC_CDC_FORMAT, 1);
        break;  
    case ResponseR2:    
        CSP_BITFINS(cmdatRegister, SDHC_CDC_FORMAT, 2);
        break;
    case ResponseR3:
    case ResponseR4:    
        // R4 is really same as an R3 response on an MMC controller (non-CRC)
        // Note: sdbus send for R4 although specs say R3
        CSP_BITFINS(cmdatRegister, SDHC_CDC_FORMAT, 3);
        break;
    default:
        ERRORMSG(ZONE_ERROR, (TEXT("SDHBusRequestHandler failed (Invalid parameter)\n")));
        return SD_API_STATUS_INVALID_PARAMETER;
    }

    // check for Command Only
    if ((SD_COMMAND != pRequest->TransferClass))
    {
        // its a command with a data phase
        CSP_BITFINS(cmdatRegister, SDHC_CDC_DE, 1);
    }
        
    // check for write
    if (SD_WRITE == pRequest->TransferClass)
    {
        //Indicate that it is write process
        CSP_BITFINS(cmdatRegister, SDHC_CDC_WR, 1);
		
#ifdef SD_R1B_BUSYWAIT_WORKAROUND 
	pController->CurrTransferReq = SD_WRITE;
#endif

        // If transfer can be supported by DMA
        if (pController->fDMATransfer == TRUE)
        {
            if (pController->CurrentDmaReq != pController->DmaReqTx)
            {
                //Update shared channel to TX 
                DDKSdmaUpdateSharedChan(pController->ChanSDHC, pController->DmaReqTx);
                pController->CurrentDmaReq = pController->DmaReqTx ; 

                // Set flag to update the DMA channel context
                pController->fDmaUpdateContext = TRUE;
            }
        }
    } 
    else if (SD_READ == pRequest->TransferClass)
    {
    		
#ifdef SD_R1B_BUSYWAIT_WORKAROUND 
	pController->CurrTransferReq = SD_READ;
#endif

        // If transfer can be supported by DMA
        if (pController->fDMATransfer == TRUE)
        {
            
            if (pController->CurrentDmaReq != pController->DmaReqRx)
            {
                //Update shared channel to RX 
                DDKSdmaUpdateSharedChan(pController->ChanSDHC, pController->DmaReqRx);
                pController->CurrentDmaReq = pController->DmaReqRx ; 

                // Set flag to update the DMA channel context
                pController->fDmaUpdateContext = TRUE;
            }
        }
    }

    // Build up scatter-gather list for transfers supported by DMA
    if (pController->fDMATransfer == TRUE)
    {
        // Update DMA channel context if needed
        if (pController->fDmaUpdateContext == TRUE)
        {
            DDKSdmaInitChain(pController->ChanSDHC, pController->Bytes_in_fifo);
            pController->fDmaUpdateContext = FALSE;
        }

        // Map address and check for security violation
        LPBYTE pBuffer = (LPBYTE) MapPtrToProcess((LPVOID)pRequest->pBlockBuffer, (HANDLE) GetCurrentProcessId());
        if (pBuffer == NULL) 
        {
            // Security violation
            ERRORMSG(ZONE_ERROR, (TEXT("SDHBusRequestHandler:  MapCaller pointer failed for block buffer\r\n")));
            return SD_API_STATUS_ACCESS_VIOLATION;
        }

        // Use CEDDK macro to calculate the number of physical pages spanned by the mapped buffer in virtual memory
        DWORD dwNumPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(pBuffer, dwNumBytesToTransfer);

        // Check if we have enough buffer desciptors
        if (dwNumPages > SDHC_DMA_BUF_DESC)
        {
            RETAILMSG(TRUE, (_T("WARNING: SDHBusRequestHandler:   Buffer descriptors exhausted.  Falling back to CPU transfers.\r\n")));
            pController->fDMATransfer = FALSE;
        }
        else
        {

            // Use LockPages to translate the mapped buffer in virtual memory into an array of physical pages.  These
            // physical pages will be used to build up a scatter-gather list for the DMA
            DWORD physPages[SDHC_DMA_BUF_DESC];
            int fOptions = ((SD_WRITE == pRequest->TransferClass) ? LOCKFLAG_READ : LOCKFLAG_WRITE);
            if (!LockPages(pBuffer, dwNumBytesToTransfer, physPages,  fOptions))
            {
                // Security violation
                ERRORMSG(ZONE_ERROR, (TEXT("SDHBusRequestHandler:  LockPages failed for block buffer\r\n")));
                return SD_API_STATUS_ACCESS_VIOLATION;
            }        
            
            // Assume no bytes will be left stranded in the FIFO
            pController->DmaStrandedBytes = 0;
                
            DWORD dwTempPtr = (DWORD) pBuffer;
            DWORD dwTempLen = dwNumBytesToTransfer;
            DWORD currentDesc = 0;

            // Traverse the physical pages returned by LockPages and build up a scatter-gather list for the DMA
            for(DWORD i = 0; (i < dwNumPages) && (dwTempLen > 0) && pController->fDMATransfer; i++)
            {                                   
                // Check for invaild physical pages
                DEBUGCHK(physPages[i] != 0);

                // Physical addresses returned from LockPages must be shifted to get start address of page
                DWORD dwPhys = physPages[i] << UserKInfo[KINX_PFN_SHIFT];

                // Offset into physical page is determined using lower bits of virtual address
                DWORD dwOffset = dwTempPtr & (UserKInfo[KINX_PAGESIZE] - 1); 

                // Size for scatter-gather list item will be minimum of:
                //      - length of physical page minus buffer offset
                //      - remaining length of buffer
                DWORD dwSize = UserKInfo[KINX_PAGESIZE] - dwOffset;            
                if(dwSize > dwTempLen)
                {
                    dwSize = dwTempLen;
                }

                // Calculate physical address for scatter-gather list item
                dwPhys += dwOffset;                
                
                // Track progress of traversal through virtual buffer 
                dwTempLen -= dwSize;
                dwTempPtr += dwSize;

                DWORD dwFlags;
                
                // If we are done creating the scatter-gather list,  
                if(dwTempLen == 0)
                {
                    // To avoid leaving data stranded in the SDHC FIFO, we must 
                    // make the last buffer descriptor a multiple of the FIFO 
                    // watermark (16 bytes for 1-bit, 64 bytes for 4-bit).  
                    // We keep track of the number of bytes that would
                    // be stranded by the DMA and read them out
                    // with the CPU
                    pController->DmaStrandedBytes = dwSize & (pController->Bytes_in_fifo - 1);
                    dwSize -= pController->DmaStrandedBytes;
                    dwFlags = DDK_DMA_FLAGS_INTR | DDK_DMA_FLAGS_WRAP;
                }
                
                else if (dwTempLen < pController->Bytes_in_fifo)
                {
                    pController->DmaStrandedBytes = dwTempLen;
                    dwTempLen = 0;
                    dwFlags = DDK_DMA_FLAGS_INTR | DDK_DMA_FLAGS_WRAP;
                }

                // Else we need more scatter-gather list entries, set the
                // buffer descriptor continue flag
                else
                {
                    dwFlags = DDK_DMA_FLAGS_CONT;
                }

                // DMA cannot handle unaligned sizes and data pointers
                if ((dwSize & 0x3) || (dwPhys & 0x3))
                {
                    pController->fDMATransfer = FALSE;
                    continue;
                }

#ifdef SDHC_SDMA_VERBOSE
                if (SD_WRITE == pRequest->TransferClass)
                    RETAILMSG(TRUE, (_T("SD_WRITE:  DDKSdmaSetBufDesc-SG (BD[%d], flags = 0x%x, addr = 0x%x, size = %d\r\n"), currentDesc, dwFlags, dwPhys, dwSize));
                else
                    RETAILMSG(TRUE, (_T("SD_READ:  DDKSdmaSetBufDesc-SG (BD[%d], flags = 0x%x, addr = 0x%x, size = %d\r\n"), currentDesc, dwFlags, dwPhys, dwSize));
#endif

                // Add new buffer descriptor to DMA chain
                DDKSdmaSetBufDesc(pController->ChanSDHC, 
                                  currentDesc, 
                                  dwFlags, 
                                  dwPhys,
                                  0, 
                                  DDK_DMA_ACCESS_32BIT, 
                                  (UINT16) dwSize);

                ++currentDesc;
                                                                    
            }
            

⌨️ 快捷键说明

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