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

📄 sdiocontrollerbase.cpp

📁 S3C2440A的windows ce 5.0 bsp包
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//  CSDIOControllerBase::BusRequestHandler - bus request handler 
//  Input:  Slot - slot the request is going on
//          pRequest - the request
//          
//  Output: 
//  Return: SD_API_STATUS Code
//  Notes:  The request passed in is marked as uncancelable, this function
//          has the option of making the outstanding request cancelable    
//          
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS CSDIOControllerBase::BusRequestHandler(DWORD dwSlot, PSD_BUS_REQUEST pRequest) 
{
    DEBUGMSG (SDCARD_ZONE_FUNC,(TEXT("BusRequestHandler starts (CMD:%d)\r\n"), pRequest->CommandCode));
    SD_API_STATUS   status;

    // Reset FIFO and status registers
    vm_pSDIReg->SDIFSTA |= FIFO_RESET;
    vm_pSDIReg->SDIDSTA = 0xffff;
    vm_pSDIReg->SDIDCON = 0;
    vm_pSDIReg->SDICSTA = 0xffff;
    vm_pSDIReg->SDICCON = 0;	

   Start_SDI_Clock();

    //----- 1. Determine the type of command (data vs. no data) and send the command -----
    m_dwNumBytesToTransfer  = pRequest->BlockSize * pRequest->NumBlocks;

    //----- 2 Can we schedule a DMA operation using the caller's buffer as-is?  -----
    if( ( m_dwDMAChannel == 0xffffffff ) || m_dwNumBytesToTransfer > MAXIMUM_DMA_TRANSFER_SIZE )
    {   
        m_bUseDMAForTransfer = FALSE;
        SetupPollingXfer(pRequest);                     // Use polling I/O routines for data transfer
    }
    else
    {
    	if((IS_BUFFER_DWORD_ALIGNED(pRequest->pBlockBuffer)) && (IS_BUFFER_SIZE_A_DWORD_MULTPLE(pRequest->BlockSize)) )
    	{
	       	m_DATATransferSize = 4;							// DMA transfer size DWORD

	    	if(pRequest->BlockSize == BYTES_PER_SECTOR)
    	    	m_bUseDMABurst = TRUE;
	    	else
    	    	m_bUseDMABurst = FALSE;
		}
	    else if ((IS_BUFFER_WORD_ALIGNED(pRequest->pBlockBuffer)) && (IS_BUFFER_SIZE_A_WORD_MULTPLE(pRequest->BlockSize)) )
		{
	       	m_DATATransferSize = 2;							// DMA transfer size WORD
	    }
	    else
	    {
	       	m_DATATransferSize = 1;							// DMA transfer size BYTE
	    }

        m_bUseDMAForTransfer = TRUE;
        SetupDmaXfer(pRequest);                         // Use DMA for data transfer
    }

    if(pRequest->TransferClass == SD_COMMAND) 
    {
        // Command only
        status = SendCommand(pRequest->CommandCode, pRequest->CommandArgument, pRequest->CommandResponse.ResponseType, FALSE);

        if(!SD_API_SUCCESS(status))
        {
            DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHCDBusRequestHandler() - Error sending command:0x%02x\r\n"), pRequest->CommandCode));
            goto BUS_REQUEST_COMPLETE;      
        }

        //----- 2. Is this the first command sent to the card?  If so, delay the 74 (or 80) clock cycles per the SD spec -----
        if(m_bSendInitClocks)
        {
            m_bSendInitClocks = FALSE;
            Wait_80_SDI_Clock_Cycles();
        }
    }
    else
    {   
        // Command with data transfer
        status = SendCommand(pRequest->CommandCode, pRequest->CommandArgument, pRequest->CommandResponse.ResponseType, TRUE);

        if(!SD_API_SUCCESS(status))
        {
            DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHCDBusRequestHandler() - Error sending command:0x%02x\r\n"), pRequest->CommandCode));
            goto BUS_REQUEST_COMPLETE;      
        }
    }

    //----- 3. Signal an IST that processes response information and cache our state -----
    //         NOTE: It is critical that this API NOT complete the bus request directly (which
    //               is why another thread is used).  The bus driver expects bus requests to complete
    //               asynchronously and a stack overflow WILL eventually occur if this rule isn't honored.
    SetEvent(m_hResponseReceivedEvent);
    m_CurrentState = CommandSent;
    status = SD_API_STATUS_PENDING;

BUS_REQUEST_COMPLETE:
    DEBUGMSG (SDCARD_ZONE_FUNC,(TEXT("SDHCD:BusRequestHandler ends\r\n")));
    return status;
}


//-------------------------------------- Interrupt Service Threads---------------------------------------


///////////////////////////////////////////////////////////////////////////////
//  CSDIOControllerBase::TransferIstThread - IST thread for DMA channel dedicated to SDIO
//  Input:  pController - the controller instance
//  Output: 
//  Return: Thread exit code
//  Notes:  
///////////////////////////////////////////////////////////////////////////////
DWORD CSDIOControllerBase::TransferIstThread()
{
    PSD_BUS_REQUEST     pRequest = NULL;       // the request to complete
    SD_API_STATUS       status;

    if( m_DMAIstThreadPriority != 0xffffffff && !CeSetThreadPriority( GetCurrentThread(), m_DMAIstThreadPriority ) )
    {
        DEBUGMSG(SDCARD_ZONE_WARN,(TEXT("SDHCDriver:TransferIstThread(): warning, failed to set CEThreadPriority \r\n")));
    }
    
    for(;;)
    {
        //----- 1. Wait for the command response -----
        status = SD_API_STATUS_PENDING;
        if(WaitForSingleObject(m_hResponseReceivedEvent, INFINITE) == WAIT_FAILED)
        {
            DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCDriver:TransferIstThread(): Wait Failed!\r\n")));
            return FALSE;
        }

        if(m_bDriverShutdown) 
        {
            DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDHCD:TransferIstThread(): Thread Exiting\r\n")));
            return FALSE;
        }

        //----- 2. Get and lock the current bus request -----
        if(pRequest == NULL)
        {
            if((pRequest = SDHCDGetAndLockCurrentRequest(m_pHCContext, 0)) == NULL)
            {
                DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Unable to get/lock current request!\r\n")));
                status = SD_API_STATUS_INVALID_DEVICE_REQUEST;
                goto TRANSFER_DONE;
            }
        }

        //----- 3. Get the response information -----
        if(pRequest->CommandResponse.ResponseType == NoResponse)
        {
            goto TRANSFER_DONE;
        }else{
            status = GetCommandResponse(pRequest);

            if(!SD_API_SUCCESS(status))
            {
                DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHCDBusRequestHandler() - Error getting response for command:0x%02x\r\n"), pRequest->CommandCode));
                goto TRANSFER_DONE;     
            }
        }

        //----- 4. SPECIAL CASE: The SD_CMD_STOP_TRANSMISSION that is sent after a SD_CMD_WRITE_MULTIPLE_BLOCK command -----
        //                       requires a BUSY_CHECK
        if( ( m_fHandleBusyCheckOnCommand38 && pRequest->CommandCode == SD_CMD_ERASE ) ||
            ( ( pRequest->CommandCode == SD_CMD_STOP_TRANSMISSION ) && ( m_dwLastTypeOfTransfer == SD_WRITE ) ) )
        {
            DWORD dwWaitCount = 0;
            //----- 5. Wait until the I/O transfer is complete -----
            while(!(vm_pSDIReg->SDIDSTA & BUSY_CHECKS_FINISH))
            {
                dwWaitCount++;
                if( dwWaitCount > WAIT_TIME )
                {
                    DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - timeout waiting for BUSY_CHECKS to finish!\r\n")));
                    status = SD_API_STATUS_DATA_TIMEOUT;
                    goto TRANSFER_DONE;
                }

                if( !IsCardPresent() )
                {
                    DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Card ejected!\r\n")));
                    status = SD_API_STATUS_DEVICE_REMOVED;
                    goto TRANSFER_DONE;
                }
                if((vm_pSDIReg->SDIFSTA & FIFO_FAIL_ERROR))
                {
                    vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH;
                    vm_pSDIReg->SDIFSTA &= FIFO_FAIL_ERROR;
                    DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - FIFO Error waiting for BUSY_CHECKS to finish!\r\n")));
                    status = SD_API_STATUS_DATA_ERROR;
                    goto TRANSFER_DONE;
                }
                if((vm_pSDIReg->SDIDSTA & DATA_TRANSMIT_CRC_ERROR))
                {
                    vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH | DATA_TRANSMIT_CRC_ERROR;
                    DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Transmit CRC Error waiting for BUSY_CHECKS to finish!\r\n")));
                    status = SD_API_STATUS_DATA_ERROR;
                    goto TRANSFER_DONE;
                }
                if((vm_pSDIReg->SDIDSTA & DATA_RECEIVE_CRC_ERROR))
                {
                    vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH | DATA_RECEIVE_CRC_ERROR;
                    DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Receive CRC Error waiting for BUSY_CHECKS to finish!\r\n")));
                    status = SD_API_STATUS_DATA_ERROR;
                    goto TRANSFER_DONE;
                }
                if((vm_pSDIReg->SDIDSTA & DATA_TIME_OUT))
                {
                    vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH | DATA_TIME_OUT;
                    DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Data timeout waiting for BUSY_CHECKS to finish!\r\n")));
                    status = SD_API_STATUS_DATA_TIMEOUT;
                    goto TRANSFER_DONE;
                }
            }
            vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH;
        }


        //----- 6. If this is a data transfer, start the I/O operation; otherwise, finish the request -----
        if(pRequest->TransferClass == SD_COMMAND)
        {
            goto TRANSFER_DONE;
        }


        //----- 7. If this is a DMA transfer, we enable interrupts and wait for the DMA interrupt.  Otherwise, -----
        //         we use our polling routines to complete the I/O.
        if(m_bUseDMAForTransfer == FALSE)
        {

            //----- 8. Polling I/O, use our special routines to handle this request
            switch(pRequest->TransferClass)
            {
            case SD_READ:
                if(!PollingReceive(pRequest, m_dwNumBytesToTransfer))
                {
                    DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:BusRequestHandler() - PollingReceive() failed\r\n")));
                    goto TRANSFER_DONE;
                }
                break;

            case SD_WRITE:
                if(!PollingTransmit(pRequest, m_dwNumBytesToTransfer))
                {
                    DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:BusRequestHandler() - PollingReceive() failed\r\n")));
                    goto TRANSFER_DONE;
                }
                break;
            }

            status = SD_API_STATUS_SUCCESS;
        }else
        {


            //----- 9. For WRITE requests, be sure to copy the write data from the caller's buffer into DMA memory-----
            if(pRequest->TransferClass == SD_WRITE)
            {
                BOOL fNoException;
                DEBUGCHK(m_dwNumBytesToTransfer <= MAXIMUM_DMA_TRANSFER_SIZE);
            
                SD_SET_PROC_PERMISSIONS_FROM_REQUEST( pRequest ) {               
                    fNoException = SDPerformSafeCopy( m_pDMABuffer, pRequest->pBlockBuffer, m_dwNumBytesToTransfer );
                } SD_RESTORE_PROC_PERMISSIONS();

                if (fNoException == FALSE) {
                    status = SD_API_STATUS_ACCESS_VIOLATION;
                    goto TRANSFER_DONE;
                }
            }

            //----- 10. DMA I/O, enable the DMA channel -----
            Enable_SDIO_DMA_Channel();

            //----- 11. Wait for a DMA interrupt -----
            // first estimate the maximum DMA transfer time
            DWORD dwDelay = m_dwNumBytesToTransfer * m_dwDMATransferTimeoutFactor / ( m_dwClockRate / 2000 );
            if( Get_SDI_Bus_Width() != WIDE_BUS_ENABLE )
            {
                dwDelay *= 4;
            }
            dwDelay += m_dwDMATransferTimeoutConstant;

            // now wait for the interrupt
            if(WaitForSingleObject(m_hDMAInterruptEvent, dwDelay) != WAIT_OBJECT_0)
            {
                DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("TransferIstThread(): Wait Failed!\r\n")));
                Stop_SDIO_DMA_Channel();
                status = SD_API_STATUS_DATA_TIMEOUT;
                goto TRANSFER_DONE;
            }

            if(m_bDriverShutdown) 
            {
                DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDHCD:TransferIstThread(): Thread Exiting\r\n")));
                return FALSE;
            }

            //----- 12. ACK the DMA completion interrupt and stop the DMA channel -----
            InterruptDone(m_dwDMASysIntr);
            Stop_SDIO_DMA_Channel();

            DWORD dwWaitCount = 0;
            //----- 13. Wait until the I/O transfer is complete -----
            while(!(vm_pSDIReg->SDIDSTA & DATA_TRANSMIT_FINISHED))
            {
                dwWaitCount++;
                if( dwWaitCount > WAIT_TIME )
                {

⌨️ 快捷键说明

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