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

📄 sdhc_core.cpp

📁 NXP LPC3000系列 wince BSP包
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//*********************************************************************
//* Software that is described herein is for illustrative purposes only  
//* which provides customers with programming information regarding the  
//* products. This software is supplied "AS IS" without any warranties.  
//* NXP Semiconductors assumes no responsibility or liability for the 
//* use of the software, conveys no license or title under any patent, 
//* copyright, or mask work right to the product. NXP Semiconductors 
//* reserves the right to make changes in the software without 
//* notification. NXP Semiconductors also make no representation or 
//* warranty that such application will be suitable for the specified 
//* use without further testing or modification. 
//*
//* Copyright NXP Semiconductors
//*********************************************************************
//
// sdhc_core.cpp
//
// SDHC controller driver implementation
//

#include <SDCardDDK.h>
#include "SDHC.h"
#include <nkintr.h>
#include "bsp.h"
#include "intr.h"

#define IndicateBusRequestComplete(pRequest, status) \
    SDHCDIndicateBusRequestComplete(m_pHCContext, \
    (pRequest), (status))

// Instance counter
int sdCardController::instance = 0;

//------------------------------------------------------------------------------
//
// StartDetectThread
//
// Start the detect thread with the passed class
//
static void StartDetectThread(class sdCardController *pSdCardClass)
{
	pSdCardClass->sdCDThread();
}

//------------------------------------------------------------------------------
//
// StartSD0Thread
//
// Start the command thread with the passed class
//
static void StartSD0Thread(class sdCardController *pSdCardClass)
{
	pSdCardClass->sdSD0Thread();
}

//------------------------------------------------------------------------------
//
// SDHCInitialize
//
// SDHC callback function
//
SD_API_STATUS SDHCInitialize(PSDCARD_HC_CONTEXT pHCContext)
{
    class sdCardController *pController = GET_PCONTROLLER_FROM_HCD(pHCContext);
    return pController->SDHCInitializeImpl();
}

//------------------------------------------------------------------------------
//
// SDHCDeinitialize
//
// SDHC callback function
//
SD_API_STATUS SDHCDeinitialize(PSDCARD_HC_CONTEXT pHCContext)
{
    class sdCardController *pController = GET_PCONTROLLER_FROM_HCD(pHCContext);
    return pController->SDHCDeinitializeImpl();
}

//------------------------------------------------------------------------------
//
// SDHCCancelIoHandler
//
// SDHC callback function
//
BOOLEAN SDHCCancelIoHandler(PSDCARD_HC_CONTEXT pHCContext,
							DWORD Slot,
							PSD_BUS_REQUEST pRequest)
{
    class sdCardController *pController = GET_PCONTROLLER_FROM_HCD(pHCContext);
    return pController->SDHCCancelIoHandlerImpl((UCHAR)Slot, pRequest);
}

//------------------------------------------------------------------------------
//
// SDHCSlotOptionHandler
//
// SDHC callback function
//
SD_API_STATUS SDHCSlotOptionHandler(PSDCARD_HC_CONTEXT pHCContext,
						            DWORD SlotNumber,
									SD_SLOT_OPTION_CODE Option,
									PVOID pData,
									ULONG OptionSize)
{
    class sdCardController *pController = GET_PCONTROLLER_FROM_HCD(pHCContext);
    return pController->SDHCSlotOptionHandlerImpl((UCHAR)SlotNumber,
		Option, pData, OptionSize );
}

//------------------------------------------------------------------------------
//
// SDHCBusRequestHandler
//
// SDHC callback function
//
SD_API_STATUS SDHCBusRequestHandler(PSDCARD_HC_CONTEXT pHCContext,
							        DWORD Slot,
									PSD_BUS_REQUEST pRequest)
{
    class sdCardController *pController = GET_PCONTROLLER_FROM_HCD(pHCContext);
    return pController->SDHCBusRequestHandlerImpl(pRequest);
}

//********************************************************************
// Class constructor and destructor functions
//********************************************************************

//------------------------------------------------------------------------------
//
// sdCardController
//
// Constructor
//
sdCardController::sdCardController(void)
{
	// Multilpe instances of this class aren't really allowed
	instance++;
	if (instance == 1)
	{
		// Set initial class values here
		sdCardSetInitialValues();
	}
}

//------------------------------------------------------------------------------
//
// ~sdCardController
//
// Destructor
//
sdCardController::~sdCardController()
{
	instance--;
}

//------------------------------------------------------------------------------
//
// sdCardSetInitialValues
//
// Setup initial driver values - this function is called when the
// driver is first instantiated or when the driver is destroyed, it
// will setup initial values for all class objects
//
void sdCardController::sdCardSetInitialValues(void)
{
	// Access to registers
	m_pGPIORegs = NULL;
	m_pSDCardRegs = NULL;
	m_pSDCardRegs = NULL;
	m_pClkPwrRegs = NULL;

	// SD host context and handle data
    m_hParentBus = NULL;
    m_pHCContext = NULL;
	m_registeredWithBusDriver = FALSE;
	m_PowerState = D4;

	// Card detect IRQ, sysIntr, events, threads, etc.
	m_dwSDCDIrq = MAPPED_INTROAL_VAL;
	m_dwSysintrCD = SYSINTR_UNDEFINED;
	m_hCardInsertInterruptEvent = INVALID_HANDLE_VALUE;
	m_DetectThreadKill = FALSE;
	m_detectThreadDone = FALSE;
	m_cardInserted = FALSE;

	// Comnmand IRQ, sysIntr, event, thread, etc.
	m_dwIrq0 = OAL_INTR_IRQ_SD0;
	m_dwSysIntr0 = SYSINTR_UNDEFINED;
	m_eventSD0 = INVALID_HANDLE_VALUE;
	m_SD0ThreadKill = FALSE;
	m_SD0ThreadDone = FALSE;

	// DMA driver handle
	m_dmaTXCtl = m_dmaRXCtl = 0;

	m_hardwareInitialized = FALSE;
}

//********************************************************************
// SDHC initialization and de-init functions. Sets up hardware and
// functions that are used whether a card is installed or not.
//********************************************************************

//------------------------------------------------------------------------------
//
// sdCardGetRegistrySettings
//
// Read the registry settings
//
BOOL sdCardController::sdCardGetRegistrySettings(LPCTSTR pszActiveKey)
{
	CReg regDevice;
    HKEY hKeyDevice = NULL;
    BOOL fRet = FALSE;

	DEBUGMSG(SDHC_INIT_ZONE,
		(TEXT("sdCardController: INFO: SDHC Active RegPath: %s\r\n"),
		pszActiveKey));

    hKeyDevice = OpenDeviceKey(pszActiveKey);
    if ((hKeyDevice == NULL) || (!regDevice.Open(hKeyDevice, NULL)))
	{
        DEBUGMSG(SDHC_ERROR_ZONE,
			(TEXT("sdCardController: ERROR: Failed to open device key\r\n")));
        goto error;
    }

	// Thread priorities
	m_dwCardDetectIstThreadPriority =
		regDevice.ValueDW(SHC_DETECT_THREAD_PRIORITY_KEY, SHC_DETECT_THREAD_PRIORITY_DEF);
	m_dwSD0IstThreadPriority =
		regDevice.ValueDW(SHC_SD0_THREAD_PRIORITY_KEY, SHC_SD0_THREAD_PRIORITY_DEF);

	DEBUGMSG(SDHC_INIT_ZONE,
		(TEXT("REGISTRY: m_dwCardDetectIstThreadPriority: %x\r\n"),
		m_dwCardDetectIstThreadPriority));
	DEBUGMSG(SDHC_INIT_ZONE,
		(TEXT("REGISTRY: m_dwSD0IstThreadPriority: %x\r\n"),
		m_dwSD0IstThreadPriority));

	// Additional data timeout clocks
	m_dataTimeout = regDevice.ValueDW(SHC_DATA_TIMEOUT_KEY, SHC_DATA_TIMEOUT_DEF);
	DEBUGMSG(SDHC_INIT_ZONE,
		(TEXT("REGISTRY: m_dataTimeout: %x\r\n"),
		m_dataTimeout));

    // Maximum clock frequency
    m_dwMaxClockRate = regDevice.ValueDW(SHC_FREQUENCY_MAX_KEY, SHC_FREQUENCY_MAX_DEF);
	DEBUGMSG(SDHC_INIT_ZONE,
		(TEXT("REGISTRY: m_dwMaxClockRate: %d\r\n"),
		m_dwMaxClockRate));

	fRet = TRUE;

error:
    if (hKeyDevice)
	{
		RegCloseKey(hKeyDevice);
	}
	
	return fRet;
}

//------------------------------------------------------------------------------
//
// sdInit
//
// Initialize class and context
//
DWORD sdCardController::sdInit(LPCTSTR pszActiveKey)
{
    SD_API_STATUS status;
    DWORD dwRet = 0;

    DEBUGMSG(SDHC_INIT_ZONE, (TEXT("SDHC +Init\r\n")));    

	// Setup initial driver values
	sdCardSetInitialValues();

	// Get registry settings
	if (sdCardGetRegistrySettings(pszActiveKey) == FALSE)
	{
        DEBUGMSG(SDHC_ERROR_ZONE,
			(TEXT("SDHC: Failed to get registry settings\r\n")));
        goto initfail;
	}

	// Open the parent bus driver handle
    m_hParentBus = CreateBusAccessHandle(pszActiveKey);
    if (m_hParentBus == NULL)
	{
        DEBUGMSG(SDHC_ERROR_ZONE,
			(TEXT("SDHC: Failed to obtain parent bus handle\r\n")));
        goto initfail;
    }

	// Allocate the context for 1 slot
    status = SDHCDAllocateContext(1, &m_pHCContext);
    if (!SD_API_SUCCESS(status)) {
        DEBUGMSG(SDHC_ERROR_ZONE,
			(TEXT("SDHC: Failed to allocate context : 0x%08X\r\n"),
            status));
        goto initfail;
    }

    // Set our extension
    m_pHCContext->pHCSpecificContext = this;

	//
    // Set the SDHC driver function callbacks
    // Set the host controller name
    SDHCDSetHCName(m_pHCContext, TEXT("SDHC"));

    // set init handler
    SDHCDSetControllerInitHandler(m_pHCContext,
		(PSD_INITIALIZE_CONTROLLER) &SDHCInitialize);

    // set deinit handler    
    SDHCDSetControllerDeinitHandler(m_pHCContext,
		(PSD_DEINITIALIZE_CONTROLLER) &SDHCDeinitialize);

    // set the Send packet handler
    SDHCDSetBusRequestHandler(m_pHCContext,
		(PSD_BUS_REQUEST_HANDLER) &SDHCBusRequestHandler);

    // set the cancel I/O handler
    SDHCDSetCancelIOHandler(m_pHCContext,
		(PSD_CANCEL_REQUEST_HANDLER) &SDHCCancelIoHandler);

    // set the slot option handler
    SDHCDSetSlotOptionHandler(m_pHCContext,
		(PSD_GET_SET_SLOT_OPTION) &SDHCSlotOptionHandler);

    // Register the host controller with the bus driver
    status = SDHCDRegisterHostController(m_pHCContext);
    if (!SD_API_SUCCESS(status)) {
        DEBUGMSG(SDHC_ERROR_ZONE,
			(TEXT("SDHC Failed to register host controller: %0x08X\r\n"),status));
        goto cleanup;
    }

	m_registeredWithBusDriver = TRUE;

	// Return the controller context
    dwRet = (DWORD) this;

initfail:
cleanup:
	if (dwRet == 0)
	{
		if (m_pHCContext)
		{
			sdCardFreeHostContext();
		}

		// Restore initial driver status
		sdCardSetInitialValues();
	}

	return dwRet;	
}

//------------------------------------------------------------------------------
//
// sdCardFreeHostContext
//
// Free host context
//
void sdCardController::sdCardFreeHostContext(void)
{
    // Deregister the host controller with the bust driver if needed
	if (m_registeredWithBusDriver)
	{
        SDHCDDeregisterHostController(m_pHCContext);
	}

	// De-init hardware
	if (m_hardwareInitialized != FALSE)
	{
	    sdHwShutdown();
	}

	// Return system resources
	SDHCDeinitializeImpl();

	// Free up bus handle
	if (m_hParentBus != NULL)
    {
        m_PowerState = D4;
        UpdateDevicePowerState();
        CloseBusAccessHandle(m_hParentBus);
        m_hParentBus = NULL;
    }

    // Cleanup the host context
	if (m_pHCContext != NULL)
	{
	    SDHCDDeleteContext(m_pHCContext);
		m_pHCContext = NULL;
	}
}

//********************************************************************
// Hardware setup functions - These functions are called whenever a
// card is inserted or removed to initialize or de-init specific
// system resources
//********************************************************************

//------------------------------------------------------------------------------
//
// sdHwSetup
//
// Hardware setup - sets up the hardware when a card is initially
// inserted into the device
//
BOOL sdCardController::sdHwSetup(void)
{
	DWORD threadID;

	// Hardware not yet initialized
	m_hardwareInitialized = FALSE;
	
	// Enable slot power and clocking
	sdHwSlotPowerControl(m_pGPIORegs, TRUE);
	sdCardEnableClocks(TRUE);
	Sleep(100);

	// Set the initial SD card setup
	sdCardClearController();
	m_pSDCardRegs->sd_power = (SD_OPENDRAIN_EN | SD_POWER_OFF_MODE); // Power off state, open drain mode
	m_pSDCardRegs->sd_clock = (SD_CLKDIV_MASK | SD_SDCLK_PWRSAVE); // Slowest/no clock, 1 bit mode

	// Take controller out of power OFF state, leave in open drain mode, enable
	// low power clock mode
	m_pSDCardRegs->sd_power = (SD_OPENDRAIN_EN | SD_POWER_ON_MODE);
	m_pSDCardRegs->sd_clock |= (SD_SDCLK_PWRSAVE | SD_SDCLK_EN);

	// Enable and setup TX DMA for the SD card controller
	m_dmaTXStp.dmaCh = DMAC_SDCARD_TXCH;
	m_dmaTXStp.perID = DMA_PERID_SDCARD;
	m_dmaTXStp.SrcInc = 1;
	m_dmaTXStp.DestInc = 0;
	m_dmaTXStp.SrcWidth = DMAC_CHAN_SRC_WIDTH_32;
	m_dmaTXStp.DestWidth = DMAC_CHAN_DEST_WIDTH_32;
	m_dmaTXStp.SrcBurstSize = DMAC_CHAN_SRC_BURST_8;
	m_dmaTXStp.DestBurstSize = DMAC_CHAN_DEST_BURST_8;
	m_dmaTXStp.perFlowSource = DMAC_CHAN_FLOW_P_M2P;
	m_dmaTXStp.destPeripheral = DMAC_DEST_PERIP(DMA_PERID_SDCARD);
	m_dmaTXStp.srcPeripheral = DMAC_SRC_PERIP(DMA_PERID_SDCARD);
	m_dmaTXCtl = dmaAllocate(&m_dmaTXStp, (64 * 1024)); // 64K of buffers
	if (m_dmaTXCtl == 0)
	{
		// Couldn't setup DMA
		DEBUGMSG(SDHC_ERROR_ZONE, 
			(TEXT("sdCardController: ERROR: Critical error setting up TX DMA\r\n")));
		m_dmaTXCtl = 0;
        goto exitInit;
	}

	// Get sysintr value for DMA channel interrupt
	m_dmaTXinfo = dmaGetInfo(m_dmaTXCtl);

	// Save DMA buffer data
	m_dmaTXBuffPhy = m_dmaTXinfo->pBuffPhy;
	m_dmaTXBuffVirt = m_dmaTXinfo->pBuffVirt;
	m_dmaTXBuffSizeBytes = m_dmaTXinfo->buffSize;

	DEBUGMSG(SDHC_INIT_ZONE, 
		(TEXT("sdCardController: INIT: DMA TX buffer PHY 0x%x VIRT 0x%x Size %d\r\n"),
		m_dmaTXBuffPhy, m_dmaTXBuffVirt, m_dmaTXBuffSizeBytes));

	// Enable and setup RX DMA for the SD card controller
	m_dmaRXStp.dmaCh = DMAC_SDCARD_RXCH;
	m_dmaRXStp.perID = DMA_PERID_SDCARD;
	m_dmaRXStp.SrcInc = 0;
	m_dmaRXStp.DestInc = 1;
	m_dmaRXStp.SrcWidth = DMAC_CHAN_SRC_WIDTH_32;
	m_dmaRXStp.DestWidth = DMAC_CHAN_DEST_WIDTH_32;
	m_dmaRXStp.SrcBurstSize = DMAC_CHAN_SRC_BURST_8;
	m_dmaRXStp.DestBurstSize = DMAC_CHAN_DEST_BURST_8;
	m_dmaRXStp.perFlowSource = DMAC_CHAN_FLOW_P_P2M;
	m_dmaRXStp.destPeripheral = DMAC_DEST_PERIP(DMA_PERID_SDCARD);
	m_dmaRXStp.srcPeripheral = DMAC_SRC_PERIP(DMA_PERID_SDCARD);
	m_dmaRXCtl = dmaAllocate(&m_dmaRXStp, (64 * 1024)); // 64K of buffers
	if (m_dmaRXCtl == 0)
	{
		// Couldn't setup DMA
		DEBUGMSG(SDHC_ERROR_ZONE, 
			(TEXT("sdCardController: ERROR: Critical error setting up RX DMA\r\n")));
		m_dmaRXCtl = 0;
        goto exitInit;

⌨️ 快捷键说明

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