sdcontrol.c

来自「pxa27x library for windows ce 5.0」· C语言 代码 · 共 1,690 行 · 第 1/5 页

C
1,690
字号
    if (NULL != pHardwareContext->pClkMgrRegisters) {
        MmUnmapIoSpace((PVOID)pHardwareContext->pClkMgrRegisters, sizeof(BULVERDE_CLKMGR_REG));
        pHardwareContext->pClkMgrRegisters = NULL;
    }

    if (NULL != pHardwareContext->pDMARegisters) {
        MmUnmapIoSpace((PVOID)pHardwareContext->pDMARegisters, sizeof(BULVERDE_DMA_REG));
        pHardwareContext->pDMARegisters = NULL;
    }

    UnInitializeHardware();

    DeleteCriticalSection(&pHardwareContext->ControllerCriticalSection);

    return SD_API_STATUS_SUCCESS;
}


///////////////////////////////////////////////////////////////////////////////
//  SDInitialize - Initialize the the MMC Controller
//  Input:  pHardwareContext - newly allocated hardware context
//          
//  Output: 
//  Return: SD_API_STATUS code
//  Notes:  
//          
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS SDInitialize(PSDCARD_HC_CONTEXT pHCContext)
{
    DWORD dwSDIOIrq;
    DWORD dwRegVal;                                 // intermediate value
    SD_API_STATUS status = SD_API_STATUS_SUCCESS;   // intermediate status
    DWORD         threadID;                         // thread ID
    PSDH_HARDWARE_CONTEXT pHardwareContext;       // hardware context
    PHYSICAL_ADDRESS Bulverde_GPIO_Base = {BULVERDE_BASE_REG_PA_GPIO};
    PHYSICAL_ADDRESS Bulverde_SDMMC_Base = {BULVERDE_BASE_REG_PA_MMC};
    PHYSICAL_ADDRESS Bulverde_CLKMGR_Base = {BULVERDE_BASE_REG_PA_CLKMGR};
    PHYSICAL_ADDRESS Bulverde_DMA_Base = {BULVERDE_BASE_REG_PA_DMAC};

    pHardwareContext = GetExtensionFromHCDContext(PSDH_HARDWARE_CONTEXT, pHCContext);

    InitializeCriticalSection(&pHardwareContext->ControllerCriticalSection);

    pHardwareContext->fSDIOEnabled = FALSE;
    pHardwareContext->fSDIOInterruptPending = FALSE;
    pHardwareContext->f4BitMode = FALSE;
    pHardwareContext->DevicePresent = FALSE;


    if( !InitializeHardware() )
    {
		DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("InitializeHardware:: Error initializing platform specific hardware\r\n")));
        return SD_API_STATUS_INSUFFICIENT_RESOURCES;
    }

	pHardwareContext->pGPIORegisters = (BULVERDE_GPIO_REG*)MmMapIoSpace( Bulverde_GPIO_Base, sizeof(BULVERDE_GPIO_REG), FALSE );
	if ( !pHardwareContext->pGPIORegisters )
	{
		DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("InitializeHardware:: Error allocating Bulverde GPIO registers\r\n")));
        return SD_API_STATUS_INSUFFICIENT_RESOURCES;
	}

	pHardwareContext->pSDMMCRegisters = (BULVERDE_MMC_REG*)MmMapIoSpace( Bulverde_SDMMC_Base, sizeof(BULVERDE_MMC_REG), FALSE );
	if ( !pHardwareContext->pSDMMCRegisters )
	{
		DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("InitializeHardware:: Error allocating Bulverde SD/MMC registers\r\n")));
        goto exitInit;
	}

	pHardwareContext->pClkMgrRegisters = (BULVERDE_CLKMGR_REG*)MmMapIoSpace( Bulverde_CLKMGR_Base, sizeof(BULVERDE_CLKMGR_REG), FALSE );
	if ( !pHardwareContext->pClkMgrRegisters )
	{
		DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("InitializeHardware:: Error allocating Bulverde Clock control registers\r\n")));
        goto exitInit;
	}

	pHardwareContext->pDMARegisters = (BULVERDE_DMA_REG*)MmMapIoSpace( Bulverde_DMA_Base, sizeof(BULVERDE_DMA_REG), FALSE );
	if ( !pHardwareContext->pDMARegisters )
	{
		DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("InitializeHardware:: Error allocating Bulverde DMA control registers\r\n")));
        goto exitInit;
	}

    // enable the MMC Unit Clock
    dwRegVal = pHardwareContext->pClkMgrRegisters->cken;
    dwRegVal |= (1 << 12);
    pHardwareContext->pClkMgrRegisters->cken = dwRegVal;

    //////////////////////////////////////////////////////////
    // Configure GPIO_32 as Alternate Function 2 out (MMC_CLK)

    // assume that the MMC_CLK is active-low signal driven
    dwRegVal = pHardwareContext->pGPIORegisters->GPCR1;
    dwRegVal |= 0x00000001;
    pHardwareContext->pGPIORegisters->GPCR1 = dwRegVal;
    // change the direction to OUT
    dwRegVal = pHardwareContext->pGPIORegisters->GPDR1;
    dwRegVal |= 0x00000001;
    pHardwareContext->pGPIORegisters->GPDR1 = dwRegVal;
    // change to Alternate Function 2
    dwRegVal = pHardwareContext->pGPIORegisters->GAFR1_L;
    dwRegVal = ( dwRegVal & 0xfffffffc ) | 0x00000002;
    pHardwareContext->pGPIORegisters->GAFR1_L = dwRegVal;
    
    //////////////////////////////////////////////////////////
    // Configure GPIO_112 as Alternate Function 1 (MMC_CMD)

    // assume that the MMC_CLK is active-high signal driven
    dwRegVal = pHardwareContext->pGPIORegisters->GPSR3;
    dwRegVal |= 0x00010000;
    pHardwareContext->pGPIORegisters->GPSR3 = dwRegVal;
    // change the direction to OUT
    dwRegVal = pHardwareContext->pGPIORegisters->GPDR3;
    dwRegVal |= 0x00010000;
    pHardwareContext->pGPIORegisters->GPDR3 = dwRegVal;
    // change to Alternate Function 1
    dwRegVal = pHardwareContext->pGPIORegisters->GAFR3_U;
    dwRegVal = ( dwRegVal & 0xfffffffc ) | 0x00000001;
    pHardwareContext->pGPIORegisters->GAFR3_U = dwRegVal;
    
    //////////////////////////////////////////////////////////
    // Configure GPIO_92 as Alternate Function 1 (MMC_DAT0)
    
    // assume that the MMC_CLK is active-high signal driven
    dwRegVal = pHardwareContext->pGPIORegisters->GPSR2;
    dwRegVal |= 0x10000000;
    pHardwareContext->pGPIORegisters->GPSR2 = dwRegVal;
    // change the direction to OUT
    dwRegVal = pHardwareContext->pGPIORegisters->GPDR2;
    dwRegVal |= 0x10000000;
    pHardwareContext->pGPIORegisters->GPDR2 = dwRegVal;
    // change to Alternate Function 1
    dwRegVal = pHardwareContext->pGPIORegisters->GAFR2_U;
    dwRegVal = ( dwRegVal & 0xfcffffff ) | 0x01000000;
    pHardwareContext->pGPIORegisters->GAFR2_U = dwRegVal;
    
    //////////////////////////////////////////////////////////
    // Configure GPIO_109-GPIO_111 as Alternate Function 1 (MMC_DAT1-MMC_DAT3)

    // assume that the MMC_CLK is active-high signal driven
    dwRegVal = pHardwareContext->pGPIORegisters->GPSR3;
    dwRegVal |= 0x0000e000;
    pHardwareContext->pGPIORegisters->GPSR3 = dwRegVal;
    // change the direction to OUT
    dwRegVal = pHardwareContext->pGPIORegisters->GPDR3;
    dwRegVal |= 0x0000e000;
    pHardwareContext->pGPIORegisters->GPDR3 = dwRegVal;
    // change to Alternate Function 1
    dwRegVal = pHardwareContext->pGPIORegisters->GAFR3_L;
    dwRegVal = ( dwRegVal & 0x03ffffff ) | 0x54000000;
    pHardwareContext->pGPIORegisters->GAFR3_L = dwRegVal;

#ifdef DEBUG
    DumpRegisters( pHardwareContext );
    DumpGPIORegisters( pHardwareContext );
#endif

    // allocate the interrupt event
    pHardwareContext->hControllerInterruptEvent = CreateEvent(NULL, FALSE, FALSE,NULL);
    
    if (NULL == pHardwareContext->hControllerInterruptEvent) {
        status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
        goto exitInit;
    }
        // convert the hardware SD/MMC controller interrupt IRQ into a logical SYSINTR value
    dwSDIOIrq = pHardwareContext->dwSDMMCIrq;
    if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwSDIOIrq, sizeof(DWORD), &(pHardwareContext->dwSysintrSDMMC), sizeof(DWORD), NULL))
    {
        // invalid SDIO SYSINTR value!
        DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("Error obtaining SDIO SYSINTR value!\n")));
        pHardwareContext->dwSysintrSDMMC = SYSINTR_UNDEFINED;
        goto exitInit;
    }

        // initialize the interrupt event
    if (!InterruptInitialize (pHardwareContext->dwSysintrSDMMC,
                              pHardwareContext->hControllerInterruptEvent,
                              NULL,
                              0)) {
        status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
        goto exitInit;
    }

    pHardwareContext->DriverShutdown = FALSE;
    
        // create the interrupt thread for controller interrupts
    pHardwareContext->hControllerInterruptThread = CreateThread(NULL,
                                                      0,
                                                      (LPTHREAD_START_ROUTINE)SDControllerIstThread,
                                                      pHardwareContext,
                                                      0,
                                                      &threadID);

    if (NULL == pHardwareContext->hControllerInterruptThread) {
        status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
        goto exitInit;
    }

    if (!SetupCardDetectIST(pHardwareContext))
    {
        status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
    }

exitInit:

    if (!SD_API_SUCCESS(status)) {
            // just call the deinit handler directly to cleanup
        SDDeinitialize(pHCContext);
    }

    return status;

}

///////////////////////////////////////////////////////////////////////////////
//  SDHCancelIoHandler - io cancel handler 
//  Input:  pHostContext - host controller context
//          Slot - slot the request is going on
//          pRequest - the request to be cancelled
//          
//  Output: 
//  Return: TRUE if the request was cancelled
//  Notes:  
//          
//
///////////////////////////////////////////////////////////////////////////////
BOOLEAN SDHCancelIoHandler(PSDCARD_HC_CONTEXT pHCContext, 
                             DWORD              Slot, 
                             PSD_BUS_REQUEST    pRequest)
{
    PSDH_HARDWARE_CONTEXT    pController;

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

    return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
//  SDHBusRequestHandler - bus request handler 
//  Input:  pHostContext - host controller context
//          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 SDHBusRequestHandler(PSDCARD_HC_CONTEXT pHCContext, 
                                     DWORD              Slot, 
                                     PSD_BUS_REQUEST    pRequest) 
{
    BOOL fExtraDelay = FALSE;
    PSDH_HARDWARE_CONTEXT    pController;     // our controller
    DWORD                      cmdatRegister;   // CMDAT register

    DbgPrintZo(SDCARD_ZONE_FUNC, (TEXT("SDHBusRequestHandler - CMD: 0x%02X DATA: 0x%08X, TC: %d\n"),
                pRequest->CommandCode, pRequest->CommandArgument, pRequest->TransferClass));

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

    DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("SDHBusRequestHandler - CMD: 0x%02X DATA: 0x%08X, TC: %d\n"),
            pRequest->CommandCode, pRequest->CommandArgument, pRequest->TransferClass));

        // stop the clock
    SDClockOff(pController);

        // set the command
    WRITE_MMC_REGISTER_DWORD(pController, MMC_CMD, pRequest->CommandCode);
        // set the argument,  high part
    WRITE_MMC_REGISTER_DWORD(pController, MMC_ARGH, (pRequest->CommandArgument >> 16));
        // set the argument,  high part
    WRITE_MMC_REGISTER_DWORD(pController, MMC_ARGL, (pRequest->CommandArgument & 0x0000FFFF));


    switch (pRequest->CommandResponse.ResponseType) {

        case NoResponse:
            cmdatRegister = MMC_CMDAT_RESPONSE_NONE;
            break;
        case ResponseR1b:
                // response1 with busy signalling
            cmdatRegister = MMC_CMDAT_RESPONSE_R1 | MMC_CMDAT_EXPECT_BUSY;
            break;
        case ResponseR1:
        case ResponseR5:
        case ResponseR6:
                // on an MMC controller R5 and R6 are really just an R1 response (CRC protected)
            cmdatRegister = MMC_CMDAT_RESPONSE_R1;
            break;
        case ResponseR2:    
            cmdatRegister = MMC_CMDAT_RESPONSE_R2;
            break;
        case ResponseR3:
        case ResponseR4:    
                // R4 is really same as an R3 response on an MMC controller (non-CRC)
            cmdatRegister = MMC_CMDAT_RESPONSE_R3;
            break;

        default:
            DbgPrintZo(SDH_SDBUS_INTERACTION_ZONE, (TEXT("SDHBusRequestHandler failed (Invalid parameter)\n")));
            return SD_API_STATUS_INVALID_PARAMETER;
    }

        // check for Command Only
    if ((SD_COMMAND == pRequest->TransferClass)) {
       
            // set the length of the block
        WRITE_MMC_REGISTER_DWORD(pController, MMC_BLKLEN, 0);

            // set the number of blocks
        WRITE_MMC_REGISTER_DWORD(pController, MMC_NOB, 0);

    } else {
            // its a command with a data phase
        cmdatRegister |= MMC_CMDAT_DATA_EN;
        
            // set the buffer index to the end of the buffer
        pRequest->HCParam = 0;      

            // set the length of the block

⌨️ 快捷键说明

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