sdcontrol.c

来自「该BSP是基于PXA270+WINCE的BSP」· C语言 代码 · 共 1,659 行 · 第 1/5 页

C
1,659
字号
    WRITE_MMC_REGISTER_DWORD(pController, MMC_RDTO, SDH_DEFAULT_DATA_TIMEOUT_CLOCKS);

    SetCurrentState(pController, CommandSend);
        // turn on the command complete and the response error interrupts
    END_CMD_INTERRUPT_ON(pController);
    PROGRAM_RESPONSE_ERROR_INTERRUPT_ON(pController);

        // turn on the clock 
    SDClockOn(pController);

    if( fExtraDelay )
    {
        fExtraDelay = FALSE;
        Sleep(500);
    }
       
#if DEBUG
    {
        DWORD mmcStatus;

        mmcStatus = READ_MMC_REGISTER_DWORD(pController, MMC_STAT);

        if (mmcStatus & 0x0000003F) {
                // these errors should be cleared
            DbgPrintZo(SDCARD_ZONE_ERROR, 
                (TEXT("********* SDHBusRequestHandler - MMC Status did not clear : 0x%08X \n"),
                (mmcStatus & 0x0000003F)));
        }
    
    }
#endif 
    DbgPrintZo(SDH_SEND_ZONE, (TEXT("SDHBusRequestHandler - Request Sent\n")));

    return SD_API_STATUS_PENDING;
}

///////////////////////////////////////////////////////////////////////////////
//  SDHSlotOptionHandler - handler for slot option changes
//  Input:  pHostContext - host controller context
//          SlotNumber   - the slot the change is being applied to
//          Option       - the option code
//          pData        - data associated with the option
//          OptionSize   - size of option data
//  Output: 
//  Return: SD_API_STATUS code
//  Notes:  
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS SDHSlotOptionHandler(PSDCARD_HC_CONTEXT    pHCContext,
                                     DWORD                 SlotNumber, 
                                     SD_SLOT_OPTION_CODE   Option, 
                                     PVOID                 pData,
                                     ULONG                 OptionSize)
{
    SD_API_STATUS status = SD_API_STATUS_SUCCESS;   // status
    PSDH_HARDWARE_CONTEXT    pController;         // the controller
    PSD_HOST_BLOCK_CAPABILITY  pBlockCaps;          // queried block capabilities

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

    switch (Option) {

        case SDHCDSetSlotPower:
            DbgPrintZo(SDCARD_ZONE_INIT, 
                (TEXT("SDHSlotOptionHandler - called - SetSlotPower : 0x%08X  \n"), 
                *((PDWORD)pData)));
            break;

        case SDHCDSetSlotInterface:
            DbgPrintZo(SDCARD_ZONE_INIT, 
                (TEXT("SDHSlotOptionHandler - called - SetSlotInterface : Clock Setting: %d \n"), 
                ((PSD_CARD_INTERFACE)pData)->ClockRate));
            
            if (SD_INTERFACE_SD_MMC_1BIT == 
                ((PSD_CARD_INTERFACE)pData)->InterfaceMode) {
                DbgPrintZo(SDCARD_ZONE_INIT, 
                        (TEXT("SDHSlotOptionHandler - called - SetSlotInterface : setting for 1 bit mode \n")));
                pController->f4BitMode = FALSE;
            } else {
                DbgPrintZo(SDCARD_ZONE_INIT, 
                        (TEXT("SDHSlotOptionHandler - called - SetSlotInterface : setting for 4 bit mode \n")));
                pController->f4BitMode = TRUE;
            }
                // set rate
            SDSetRate(pController, &((PSD_CARD_INTERFACE)pData)->ClockRate);
            
            break;

        case SDHCDEnableSDIOInterrupts:
            
            DbgPrintZo(SDCARD_ZONE_INIT, 
                (TEXT("SDHSlotOptionHandler - called - EnableSDIOInterrupts : on slot %d  \n"),
                SlotNumber));

            SDIO_INTERRUPT_ON(pController);
            pController->fSDIOEnabled = TRUE;

            break;

        case SDHCDAckSDIOInterrupt:

                // acquire the lock to block the SDIO interrupt thread
            ACQUIRE_LOCK(pController);

            if ( ( pController->pSDMMCRegisters->stat & 0x8000 ) &&
                 ( pController->pSDMMCRegisters->ireg & 0x0800 ) &&
                 pController->fSDIOEnabled )
            {
                DbgPrintZo(/*SDCARD_ZONE_INIT*/SDH_INTERRUPT_ZONE, (TEXT("SDIO INT (still)!\n")));
                SDHCDIndicateSlotStateChange(pController->pHCContext, 
                                                0,
                                                DeviceInterrupting);
            }
            else if( pController->fSDIOEnabled )
            {
                SDIO_INTERRUPT_ON(pController);
            }

            RELEASE_LOCK(pController);

            break;

        case SDHCDDisableSDIOInterrupts:
            DbgPrintZo(SDCARD_ZONE_INIT, 
                (TEXT("SDHSlotOptionHandler - called - DisableSDIOInterrupts : on slot %d  \n"),
                SlotNumber));

            SDIO_INTERRUPT_OFF(pController);
            pController->fSDIOEnabled = FALSE;

            break;

        case SDHCDGetWriteProtectStatus:
            
            DbgPrintZo(SDCARD_ZONE_INIT, 
                (TEXT("SDHSlotOptionHandler - called - SDHCDGetWriteProtectStatus : on slot %d  \n"),
                 SlotNumber)); 
            
            if( IsCardWriteProtected() ) {
                ((PSD_CARD_INTERFACE)pData)->WriteProtected = TRUE;
                DbgPrintZo(SDCARD_ZONE_INIT, (TEXT("SDHSlotOptionHandler - Card is write protected \n"))); 
            } else {
                ((PSD_CARD_INTERFACE)pData)->WriteProtected = FALSE;
                DbgPrintZo(SDCARD_ZONE_INIT, (TEXT("SDHSlotOptionHandler - Card is write enabled \n"))); 
            }

            break;

         case SDHCDQueryBlockCapability:
            pBlockCaps = (PSD_HOST_BLOCK_CAPABILITY)pData;

             DbgPrintZo(SDCARD_ZONE_INIT, 
             (TEXT("SDHSlotOptionHandler: Read Block Length: %d , Read Blocks: %d\n"), 
                pBlockCaps->ReadBlockSize, 
                pBlockCaps->ReadBlocks));
             DbgPrintZo(SDCARD_ZONE_INIT, 
             (TEXT("SDHSlotOptionHandler: Write Block Length: %d , Write Blocks: %d\n"), 
                pBlockCaps->WriteBlockSize, 
                pBlockCaps->WriteBlocks));

                // the PXA27x controller can only handle up to 1024 bytes
                // with a minimum of 32 bytes per transfer
            if (pBlockCaps->ReadBlockSize > SDH_MAX_BLOCK_SIZE) {
                pBlockCaps->ReadBlockSize = SDH_MAX_BLOCK_SIZE;
            }

            if (pBlockCaps->ReadBlockSize < SDH_MIN_BLOCK_SIZE ) {
                pBlockCaps->ReadBlockSize = SDH_MIN_BLOCK_SIZE;
            }

            if (pBlockCaps->WriteBlockSize > SDH_MAX_BLOCK_SIZE) {
                pBlockCaps->WriteBlockSize = SDH_MAX_BLOCK_SIZE;
            }
            
            if (pBlockCaps->WriteBlockSize < SDH_MIN_BLOCK_SIZE ) {
                pBlockCaps->WriteBlockSize = SDH_MIN_BLOCK_SIZE;
            }

                // the PXA27x controller can handle 64K blocks,
                // we leave the number of blocks alone
             
            break;

        case SDHCDGetSlotInfo:
            if( OptionSize != sizeof(SDCARD_HC_SLOT_INFO) || pData == NULL )
            {
                status = SD_API_STATUS_INVALID_PARAMETER;
            }
            else
            {
                PSDCARD_HC_SLOT_INFO pSlotInfo = (PSDCARD_HC_SLOT_INFO)pData;

                // set the slot capabilities
                SDHCDSetSlotCapabilities(pSlotInfo, SD_SLOT_SD_1BIT_CAPABLE | 
                                                    SD_SLOT_SD_4BIT_CAPABLE |
                                                    SD_SLOT_SDIO_CAPABLE);

                SDHCDSetVoltageWindowMask(pSlotInfo, (SD_VDD_WINDOW_3_2_TO_3_3 | SD_VDD_WINDOW_3_3_TO_3_4)); 

                // Set optimal voltage
                SDHCDSetDesiredSlotVoltage(pSlotInfo, SD_VDD_WINDOW_3_2_TO_3_3);

                SDHCDSetMaxClockRate(pSlotInfo, pController->dwMaximumSDClockFrequency);

                // Set power up delay. We handle this in SetVoltage().
                SDHCDSetPowerUpDelay(pSlotInfo, 300);
            }
            break;

        default:
           status = SD_API_STATUS_INVALID_PARAMETER;

    }

    return status;
}

///////////////////////////////////////////////////////////////////////////////
//  HandleProgramDone - Handle program done interrupt
//  Input:  pController - the controller that is interrupting
//  Output: 
//  Return:
//  Notes:  
///////////////////////////////////////////////////////////////////////////////
VOID HandleProgramDone(PSDH_HARDWARE_CONTEXT pController)
{
    PSD_BUS_REQUEST pRequest;       // current request

    PROGRAM_DONE_INTERRUPT_OFF(pController);

        // get the current request  
    pRequest = SDHCDGetAndLockCurrentRequest(pController->pHCContext, 0);

        // this should never happen because we mark the request as un-cancelable.
    DEBUG_ASSERT(NULL != pRequest);
    if(NULL == pRequest)
    {
        return;
    }

    SetCurrentState(pController, WriteDataDone);

        // notice there is no status to check for a programming error
        // this is up to the upper level drivers to send a card status command
    DbgPrintZo(SDH_TRANSMIT_ZONE, (TEXT("HandleProgramDone: Programming Complete \n")));

    if( !( pController->fClockAlwaysOn || ( pController->fClockOnIfInterruptsEnabled && pController->fSDIOEnabled ) ) )
    {
            // turn off the clock
        SDClockOff(pController);
            // complete the request
    }

    DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("HandleProgramDone reports Bus Request Succeeded\n")));

    SDHCDIndicateBusRequestComplete(pController->pHCContext,
                                    pRequest ,
                                    SD_API_STATUS_SUCCESS);
}

///////////////////////////////////////////////////////////////////////////////
//  EmptyReceiveFifo - Empty the receive Fifo
//  Input:  pController - the controller instance
//          pRequest - the request to get the data from
//          ByteCount - number of bytes to read
//          MaxBytes - limit of this transfer
//  Output: 
//  Return:
//  Notes:  
//      
///////////////////////////////////////////////////////////////////////////////
VOID EmptyReceiveFifo(PSDH_HARDWARE_CONTEXT pController, 
                      PSD_BUS_REQUEST         pRequest,
                      ULONG                   ByteCount,
                      ULONG                   MaxBytes)
{   
    ULONG   receiveBufferIndex = 0; // receive buffer index
    ULONG MaxBytesToRead;

    volatile UCHAR *pMMC_RX_Fifo = (volatile UCHAR *)&(pController->pSDMMCRegisters->rxfifo);
    volatile DWORD *pMMC_RX_FifoDW = (volatile DWORD *)&(pController->pSDMMCRegisters->rxfifo);

    if( !IsCardPresent() )
    {
        DbgPrintZo(SDCARD_ZONE_ERROR, (TEXT("EmptyReceiveFifo: Card ejected!\n")));     
        return;
    }

    MaxBytesToRead = MaxBytes - pRequest->HCParam;

    if( ByteCount > MaxBytesToRead )
    {
        ByteCount = MaxBytesToRead;
    }

        // we are touching the block buffer, we must set the process permissions
    SD_SET_PROC_PERMISSIONS_FROM_REQUEST(pRequest) {

            // empty the FIFO
        while (ByteCount) {
                // fill up the receive buffer
            if (receiveBufferIndex < MMC_RXFIFO_SIZE) {

                if( ByteCount >= 4 )
                {
                        // read in the dword from the FIFO
                    *(DWORD*)(&pController->RcvBuffer[receiveBufferIndex]) = *pMMC_RX_FifoDW;

                    receiveBufferIndex+=4;
                    ByteCount-=4;
                }
                else
                {
                        // read in the byte from the FIFO
                    pController->RcvBuffer[receiveBufferIndex] = *pMMC_RX_Fifo;

                    receiveBufferIndex++;
                    ByteCount--;
                }
                    // check to see if we've read enough
                if ((pRequest->HCParam + receiveBufferIndex) >= MaxBytes) {
                    break;
                }

            } else {
                    // receive buffer is full, now transfer the data safely
                PREFAST_SUPPRESS( 12008, "False positive: the buffer access index 'pRequest->HCParam + receiveBufferIndex' is guaranteed to be valid prior to this call" );
                SDPerformSafeCopy(&pRequest->pBlockBuffer[pRequest->HCParam],
                                  pController->RcvBuffer,
                                  receiveBufferIndex);
                    // bump the running count
                pRequest->HCParam += receiveBufferIndex;

⌨️ 快捷键说明

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