📄 sdiocontrollerbase.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
// Copyright (c) 2002 BSQUARE Corporation. All rights reserved.
// DO NOT REMOVE --- BEGIN EXTERNALLY DEVELOPED SOURCE CODE ID 40973--- DO NOT REMOVE
#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include <s3c2410x.h>
#include <s3c2410x_dmatransfer.h>
#include <creg.hxx>
#include <ddkreg.h>
#include <SDCardDDK.h>
#include <SDHCD.h>
#include "SDIOControllerBase.h"
#define SDIO_DMA_PHYSICAL_MEMORY_SIZE 0x00010000
#define MMCFIF_PHYS 0x5A00003C
#define FCLK (203000000)
#define UCLK (50331648) // 48 MHz
#define HCLK (FCLK / 2)
#define PCLK (FCLK / 4)
/////////////////////////////////////////////////////////////////////////
#define WAIT_TIME 0x200000 // while loop delay
#define START_BIT 0x00
#define TRANSMISSION_BIT 0x00
#define START_RESERVED 0x3F
#define END_RESERVED 0xFE
#define END_BIT 0x01
#define MAXIMUM_DMA_TRANSFER_SIZE SDIO_DMA_PHYSICAL_MEMORY_SIZE
#define MAXIMUM_BLOCK_TRANSFER_SIZE 0xfff
#define MINIMUM_BLOCK_TRANSFER_SIZE 1
#define IS_BUFFER_DWORD_ALIGNED(x) ((((DWORD)x) % 4) == 0)
#define IS_BUFFER_SIZE_A_DWORD_MULTPLE(x) ((((DWORD)x) % 4 )== 0)
#define DMA_CHANNEL_TEXT TEXT("DMAChannel")
#define DMA_IRQ_TEXT TEXT("DMAIrq")
#define DMA_IST_PRIORITY_TEXT TEXT("DMA_IST_Priority")
#define SDIO_IRQ_TEXT TEXT("SDIOIrq")
#define SDIO_IST_PRIORITY_TEXT TEXT("SDIO_IST_Priority")
#define POLLING_TIMEOUT_TEXT TEXT("PollingTimeout")
#define CARD_DETECT_THREAD_PRIORITY_TEXT TEXT("CardDetect_Thread_Priority")
#define HANDLE_BUSY_FINISH_ON_COMMAND38_TEXT TEXT("HandleBusyFinishOnCommand38")
#define DMA_TRANSFER_TIMEOUT_FACTOR_TEXT TEXT("DmaTransferTimeoutFactor")
#define DMA_TRANSFER_TIMEOUT_CONSTANT_TEXT TEXT("DmaTransferTimeoutConstant")
///////////////////////////////////////////////////////////////////////////////
// CSDIOControllerBase::CSDIOControllerBase - CSDIOControllerBase constructor
// Input: pHCContext - hardware context
// Notes:
//
///////////////////////////////////////////////////////////////////////////////
CSDIOControllerBase::CSDIOControllerBase( PSDCARD_HC_CONTEXT pHCContext )
{
vm_pSDIReg = NULL;
vm_pIOPreg = NULL;
vm_pCLKPWR = NULL;
vm_pDMAreg = NULL;
m_pDMABuffer = NULL;
m_dwDMAChannel = 0;
m_pHCContext = pHCContext;
m_hResponseReceivedEvent = NULL;
m_nCardDetectIstThreadPriority = 0;
m_hCardInsertInterruptEvent = NULL;
m_hCardInsertInterruptThread = NULL;
m_nSDIOIstThreadPriority = 0;
m_hSDIOInterruptEvent = NULL;
m_hSDIOInterruptThread = NULL;
m_DMAIstThreadPriority = 0;
m_hDMAInterruptEvent = NULL;
m_hDMAInterruptThread = NULL;
m_bUseDMAForTransfer = FALSE;
m_bDriverShutdown = FALSE;
m_bDevicePresent = FALSE;
m_CurrentState = Idle;
m_bSendInitClocks = TRUE;
m_dwLastTypeOfTransfer = SD_READ;
m_dwNumBytesToTransfer = 0;
m_dwNumBytesUnaligned = 0;
m_dwNumBytesExtra = 0;
m_rgchRegPath[0] = 0;
m_dwSDIBusWidth = 0;
m_bReinsertTheCard = FALSE;
m_fHandleBusyCheckOnCommand38 = FALSE;
m_dwDMATransferTimeoutFactor = 8;
m_dwDMATransferTimeoutConstant = 3000;
m_fCardInTheSlot = FALSE;
m_fInitialized = FALSE;
m_pszRegistryPath = NULL;
}
///////////////////////////////////////////////////////////////////////////////
// CSDIOControllerBase::~CSDIOControllerBase - CSDIOControllerBase destructor
// Input:
// Notes:
//
///////////////////////////////////////////////////////////////////////////////
CSDIOControllerBase::~CSDIOControllerBase()
{
}
///////////////////////////////////////////////////////////////////////////////
// CSDIOControllerBase::PreDeinit() - PreDeinit routine
// Input:
// Notes:
//
///////////////////////////////////////////////////////////////////////////////
void CSDIOControllerBase::PreDeinit()
{
if( !m_bDriverShutdown )
{
Deinitialize();
}
}
///////////////////////////////////////////////////////////////////////////////
// CSDIOControllerBase::Initialize - Initializes the the SDIO Host Controller
// Input: pHCContext - newly allocated hardware context
//
// Output:
// Return: SD_API_STATUS code
// Notes:
//
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS CSDIOControllerBase::Initialize()
{
DEBUGMSG (SDCARD_ZONE_INIT,(TEXT("SDHCDInitialize starts")));
SD_API_STATUS status = SD_API_STATUS_SUCCESS; // intermediate status
DWORD threadID; // thread ID
ULONG fInIOSpace = FALSE;
PHYSICAL_ADDRESS S3C2410X_IOPORT_Base = {S3C2410X_BASE_REG_PA_IOPORT};
PHYSICAL_ADDRESS S3C2410X_SDI_Base = {S3C2410X_BASE_REG_PA_SDI};
PHYSICAL_ADDRESS S3C2410X_CLOCK_POWER_Base = {S3C2410X_BASE_REG_PA_CLOCK_POWER};
PHYSICAL_ADDRESS S3C2410X_DMA_Base = {S3C2410X_BASE_REG_PA_DMA};
InitializeCriticalSection(&m_ControllerCriticalSection);
m_fInitialized = TRUE;
//----- 1. Map the GPIO registers needed to enable the SDI controller -----
HANDLE hBusHandle = CreateBusAccessHandle( m_pszRegistryPath );
if( hBusHandle == NULL )
{
DEBUGMSG (1,(TEXT("Failed to create parent bus access handle!")));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto INIT_ERROR;
}
if( !BusTransBusAddrToVirtual( hBusHandle, Internal, 0, S3C2410X_IOPORT_Base, sizeof(S3C2410X_IOPORT_REG), &fInIOSpace, (PPVOID)&vm_pIOPreg ) )
{
DEBUGMSG (1,(TEXT("GPIO registers not allocated")));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto INIT_ERROR;
}
DEBUGMSG (1,(TEXT("GPIO registers mapped to %x"), vm_pIOPreg));
//----- 2. Map the SDI control registers into the device drivers address space -----
if( !BusTransBusAddrToVirtual( hBusHandle, Internal, 0, S3C2410X_SDI_Base, sizeof(S3C2410X_SDI_REG), &fInIOSpace, (PPVOID)&vm_pSDIReg ) )
{
DEBUGMSG (1,(TEXT("SDI control registers not allocated\n\r")));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto INIT_ERROR;
}
DEBUGMSG (1,(TEXT("SDI control registers mapped to %x\n\r"), vm_pSDIReg));
if( !BusTransBusAddrToVirtual( hBusHandle, Internal, 0, S3C2410X_CLOCK_POWER_Base, sizeof(S3C2410X_CLKPWR_REG), &fInIOSpace, (PPVOID)&vm_pCLKPWR ) )
{
DEBUGMSG (1,(TEXT("Clock & Power Management Special Register not allocated\n\r")));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto INIT_ERROR;
}
DEBUGMSG (1,(TEXT("Clock & Power Management Special Register mapped to %x\n\r"), vm_pCLKPWR));
if( m_dwDMAChannel != 0xffffffff )
{
//----- 3. Map the DMA control registers used for SDI data transfers -----
if( !BusTransBusAddrToVirtual( hBusHandle, Internal, 0, S3C2410X_DMA_Base, sizeof(S3C2410X_DMA_REG), &fInIOSpace, (PPVOID)&vm_pDMAreg ) )
{
DEBUGMSG (1,(TEXT("DMA Register not allocated\n\r")));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto INIT_ERROR;
}
DEBUGMSG (1,(TEXT("DMA Register mapped to %x\n\r"), vm_pDMAreg));
//----- 4. Allocate a block of memory for DMA transfers -----
DMA_ADAPTER_OBJECT dmaAdapter;
dmaAdapter.ObjectSize = sizeof(dmaAdapter);
dmaAdapter.InterfaceType = Internal;
dmaAdapter.BusNumber = 0;
m_pDMABuffer = (PBYTE)HalAllocateCommonBuffer( &dmaAdapter, MAXIMUM_DMA_TRANSFER_SIZE, &m_pDMABufferPhys, FALSE );
if( m_pDMABuffer == NULL )
{
RETAILMSG(1, (TEXT("SHCDriver: - Unable to allocate memory for DMA buffers!\r\n")));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto INIT_ERROR;
}
}
// Supply the clock to the SDI controller
MMC_Hardware_PowerUp();
//----- 6. Configure the GPIO lines for SDI mode and enable the pullup resistor -----
vm_pIOPreg->GPEUP &= 0xF83F;
vm_pIOPreg->GPECON |= 0x2AA800;
//----- 7. Set the SD/SDI controller to some reasonable default values -----
SetClockRate(SD_DEFAULT_CARD_ID_CLOCK_RATE); // 100Khz
vm_pSDIReg->SDICON |= LITTLE_ENDIAN_BYTE_ORDER; // Windows CE is always Little Endian.
vm_pSDIReg->SDICON |= RESET_FIFO; // Reset the FIFO
vm_pSDIReg->SDIBSIZE = BYTES_PER_SECTOR;
vm_pSDIReg->SDIDTIMER = MAX_DATABUSY_TIMEOUT; // Data/busy timeout
//----- 8. Setup the thread for detecting card insertion/deletion -----
m_hCardInsertInterruptEvent = CreateEvent(NULL, FALSE, FALSE,NULL);
if(NULL == m_hCardInsertInterruptEvent)
{
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto INIT_ERROR;
}
m_bDevicePresent = FALSE;
m_hCardInsertInterruptThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)SD_CardDetectThread,
this, 0, &threadID);
if(NULL == m_hCardInsertInterruptThread)
{
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto INIT_ERROR;
}
//----- 9 . Setup an event used for signaling our response thread -----
m_hResponseReceivedEvent = CreateEvent(NULL, FALSE, FALSE,NULL);
if(NULL == m_hResponseReceivedEvent)
{
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto INIT_ERROR;
}
//----- 10. Setup the IST for handling SDIO data transfer interrupts -----
m_hSDIOInterruptEvent = CreateEvent(NULL, FALSE, FALSE,NULL);
if(NULL == m_hSDIOInterruptEvent)
{
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto INIT_ERROR;
}
// initialize the card insertion interrupt event
if(!InterruptInitialize (m_dwSDIOSysIntr, m_hSDIOInterruptEvent,
NULL, 0))
{
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto INIT_ERROR;
}
m_hSDIOInterruptThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)SD_IOInterruptIstThread,
this, 0, &threadID);
if(NULL == m_hSDIOInterruptThread)
{
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto INIT_ERROR;
}
//----- 11. Setup the interrupt event for handling SDIO DMA data transfers -----
m_hDMAInterruptEvent = CreateEvent(NULL, FALSE, FALSE,NULL);
if(NULL == m_hDMAInterruptEvent)
{
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto INIT_ERROR;
}
// initialize the dma transfer interrupt event
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -