sdcontrol.c

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

C
1,659
字号
        SDClockOn( pHc );
    }
}

///////////////////////////////////////////////////////////////////////////////
//  SDDeInitialize - Deinitialize the the MMC Controller
//  Input:  pHCContext - Host controller context
//          
//  Output: 
//  Return: SD_API_STATUS code
//  Notes:  
//         
//
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS SDDeinitialize(PSDCARD_HC_CONTEXT pHCContext)
{
    PSDH_HARDWARE_CONTEXT pHardwareContext; // hardware context
    PSD_BUS_REQUEST     pRequest = NULL;       // the request to complete

    pHardwareContext = GetExtensionFromHCDContext(PSDH_HARDWARE_CONTEXT, pHCContext);

        // mark for shutdown
    pHardwareContext->DriverShutdown = TRUE;

    if( pHardwareContext->hControllerInterruptEvent )
    {
        // wake up the controller IST
        SetEvent(pHardwareContext->hControllerInterruptEvent);
    }

    if (NULL != pHardwareContext->hDMAInterruptEvent) 
    {
        // wake up the DMA IST
        SetEvent(pHardwareContext->hDMAInterruptEvent);
    }

    // clean up controller IST
    if (NULL != pHardwareContext->hControllerInterruptThread) {
            // wait for the thread to exit
        WaitForSingleObject(pHardwareContext->hControllerInterruptThread, INFINITE); 
        CloseHandle(pHardwareContext->hControllerInterruptThread);
        pHardwareContext->hControllerInterruptThread = NULL;
    }
        
    // clean up DMA IST
    if (NULL != pHardwareContext->hDmaInterruptThread) {
        // wait for the thread to exit
        WaitForSingleObject(pHardwareContext->hDmaInterruptThread, INFINITE); 
        CloseHandle(pHardwareContext->hDmaInterruptThread);
        pHardwareContext->hDmaInterruptThread = NULL;
    }
        
        // free controller interrupt event
    if (NULL != pHardwareContext->hControllerInterruptEvent) {
        CloseHandle(pHardwareContext->hControllerInterruptEvent);
        pHardwareContext->hControllerInterruptEvent = NULL;
    }

        // free the DMA interrupt event
    if( pHardwareContext->hDMAInterruptEvent )
    {
        CloseHandle(pHardwareContext->hDMAInterruptEvent);
        pHardwareContext->hDMAInterruptEvent = NULL;
    }

        // make sure all interrupt sources are disabled
    if( pHardwareContext->dwSysintrSDMMC != SYSINTR_UNDEFINED )
    {
        InterruptDisable (pHardwareContext->dwSysintrSDMMC);
        KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &pHardwareContext->dwSysintrSDMMC, sizeof(DWORD), NULL, 0, NULL);
        pHardwareContext->dwSysintrSDMMC = SYSINTR_UNDEFINED;
    }
    if( pHardwareContext->dwDmaSysIntr != SYSINTR_UNDEFINED )
    {
        InterruptDisable (pHardwareContext->dwDmaSysIntr);
        KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &pHardwareContext->dwDmaSysIntr, sizeof(DWORD), NULL, 0, NULL);
        pHardwareContext->dwDmaSysIntr = SYSINTR_UNDEFINED;
    }

        // unload the DMA ISR DLL
    if( pHardwareContext->hDMAIsrHandler )
    {
        FreeIntChainHandler(pHardwareContext->hDMAIsrHandler);
        pHardwareContext->hDMAIsrHandler = NULL;
    }

        // free the DMA buffer
    if( pHardwareContext->pDMABuffer )
    {
        HalFreeCommonBuffer( NULL, 0, pHardwareContext->pDMABufferPhys, pHardwareContext->pDMABuffer, FALSE );
        pHardwareContext->pDMABuffer = NULL;
        pHardwareContext->dwDmaBufferSize = 0;
    }

        // free the DMA descriptors buffer
    if( pHardwareContext->pDMADescriptors )
    {
        DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SHCDriver: - Unable to allocate memory for DMA descriptors!\r\n")));
        HalFreeCommonBuffer( NULL, 0, pHardwareContext->pDMADescriptorsPhys, (PVOID)pHardwareContext->pDMADescriptors, FALSE );
        pHardwareContext->pDMADescriptors = NULL;
    }

        // clean up card insertion IST and free card insertion interrupt
    CleanupCardDetectIST();

        // turn the hardware off
    SDClockOff( pHardwareContext );
    MMCPowerControl( FALSE );

        // if there is a pending request, cancel it
    if( pHardwareContext && (pRequest = SDHCDGetAndLockCurrentRequest(pHCContext, 0)) != NULL)
    {
        DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDHCD:SHCDriver() - aborting current request!\r\n")));
        SDHCDIndicateBusRequestComplete(pHCContext, pRequest, SD_API_STATUS_SHUT_DOWN);
    }


        // If a card is inserted, signal that it was ejected...
    if(pHardwareContext && pHardwareContext->DevicePresent)
    {
        // indicate the slot change 
        SDHCDIndicateSlotStateChange(pHCContext, 0, DeviceEjected); 
        pHardwareContext->DevicePresent = FALSE;
    }

        // free memory mapped resources

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

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

    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;
    }

    if(NULL != pHardwareContext->hBusAccessHandle) {
        CloseBusAccessHandle(pHardwareContext->hBusAccessHandle);
        pHardwareContext->hBusAccessHandle = 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)
{
    ULONG fInIOSpace;
    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;
    pHardwareContext->hDMAInterruptEvent = NULL;
    pHardwareContext->hDMAIsrHandler = NULL;
    pHardwareContext->DriverShutdown = FALSE;
    pHardwareContext->hDMAInterruptEvent = NULL;
    pHardwareContext->hDmaInterruptThread = NULL;
    pHardwareContext->pDMABuffer = NULL;
    pHardwareContext->pDMADescriptors = NULL;
    pHardwareContext->dwControllerIstTimeout = INFINITE;

#ifdef DEBUG
    pHardwareContext->fDMATransferInProgress = FALSE;
#endif
    
    GetSystemInfo( &pHardwareContext->systemInfo );

    if( !InitializeHardware( pHardwareContext->hBusAccessHandle ) )
    {
		DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("InitializeHardware:: Error initializing platform specific hardware\r\n")));
        goto exitInit;
    }

    if( !BusTransBusAddrToVirtual( pHardwareContext->hBusAccessHandle, Internal, 0, Bulverde_GPIO_Base, sizeof(BULVERDE_GPIO_REG), &fInIOSpace, (PPVOID)&(pHardwareContext->pGPIORegisters) ) )
	{
		DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("InitializeHardware:: Error allocating Bulverde GPIO registers\r\n")));
        goto exitInit;
	}

    if( !BusTransBusAddrToVirtual( pHardwareContext->hBusAccessHandle, Internal, 0, Bulverde_SDMMC_Base, sizeof(BULVERDE_MMC_REG), &fInIOSpace, (PPVOID)&(pHardwareContext->pSDMMCRegisters) ) )
	{
		DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("InitializeHardware:: Error allocating Bulverde SD/MMC registers\r\n")));
        goto exitInit;
	}

    if( !BusTransBusAddrToVirtual( pHardwareContext->hBusAccessHandle, Internal, 0, Bulverde_CLKMGR_Base, sizeof(BULVERDE_CLKMGR_REG), &fInIOSpace, (PPVOID)&(pHardwareContext->pClkMgrRegisters) ) )
	{
		DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("InitializeHardware:: Error allocating Bulverde Clock control registers\r\n")));
        goto exitInit;
	}

    if( !BusTransBusAddrToVirtual( pHardwareContext->hBusAccessHandle, Internal, 0, Bulverde_DMA_Base, sizeof(BULVERDE_DMA_REG), &fInIOSpace, (PPVOID)&(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;

⌨️ 快捷键说明

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