📄 sdiocontrollerbase.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
// 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 <s3c2440a.h>
#include <s3c2440a_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 MMCFIFO_DWORD_PHYS 0x5A000040
#define MMCFIFO_WORD_PHYS 0x5A000044
#define MMCFIFO_BYTE_PHYS 0x5A000048
#define FCLK (399651840)
#define HCLK (FCLK / 3)
#define PCLK (FCLK / 6)
/////////////////////////////////////////////////////////////////////////
#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 (MAXIMUM_DMA_TRANSFER_SIZE / 0x200)
#define MINIMUM_BLOCK_TRANSFER_SIZE 1
#define IS_BUFFER_DWORD_ALIGNED(x) ((((DWORD)x) % 4) == 0)
#define IS_BUFFER_WORD_ALIGNED(x) ((((DWORD)x) % 2) == 0)
#define IS_BUFFER_SIZE_A_DWORD_MULTPLE(x) ((((DWORD)x) % 4 )== 0)
#define IS_BUFFER_SIZE_A_WORD_MULTPLE(x) ((((DWORD)x) % 2 )== 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_nControllerIstThreadPriority = 0;
m_hControllerInterruptEvent = NULL;
m_hControllerInterruptThread = NULL;
m_DMAIstThreadPriority = 0;
m_hDMAInterruptEvent = NULL;
m_hDMAInterruptThread = NULL;
m_bUseDMAForTransfer = FALSE;
m_bUseDMABurst = FALSE;
m_DATATransferSize = 1;
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;
}
///////////////////////////////////////////////////////////////////////////////
// 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\r\n")));
SD_API_STATUS status = SD_API_STATUS_SUCCESS; // intermediate status
DWORD threadID; // thread ID
InitializeCriticalSection(&m_ControllerCriticalSection);
//----- 1. Map the GPIO registers needed to enable the SDI controller -----
vm_pIOPreg = (S3C2440A_IOPORT_REG *)VirtualAlloc(0, sizeof(S3C2440A_IOPORT_REG), MEM_RESERVE, PAGE_NOACCESS);
if (vm_pIOPreg == NULL)
{
DEBUGMSG (1,(TEXT("GPIO registers not allocated\r\n")));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto INIT_ERROR;
}
if (!VirtualCopy((PVOID)vm_pIOPreg, (PVOID)(S3C2440A_BASE_REG_PA_IOPORT >> 8), sizeof(S3C2440A_IOPORT_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE)) {
DEBUGMSG (1,(TEXT("GPIO registers not mapped\r\n")));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto INIT_ERROR;
}
DEBUGMSG (1,(TEXT("GPIO registers mapped to %x\r\n"), vm_pIOPreg));
//----- 2. Map the SDI control registers into the device drivers address space -----
vm_pSDIReg = (S3C2440A_SDI_REG *)VirtualAlloc(0, sizeof(S3C2440A_SDI_REG), MEM_RESERVE, PAGE_NOACCESS);
if (vm_pSDIReg == NULL)
{
DEBUGMSG (1,(TEXT("SDI control registers not allocated\n\r")));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto INIT_ERROR;
}
if (!VirtualCopy((PVOID)vm_pSDIReg, (PVOID)(S3C2440A_BASE_REG_PA_SDI >> 8), sizeof(S3C2440A_SDI_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE)) {
DEBUGMSG (1,(TEXT("SDI control registers not mapped\n\r")));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto INIT_ERROR;
}
DEBUGMSG (1,(TEXT("SDI control registers mapped to %x\n\r"), vm_pSDIReg));
vm_pCLKPWR = (S3C2440A_CLKPWR_REG *)VirtualAlloc(0, sizeof(S3C2440A_CLKPWR_REG), MEM_RESERVE, PAGE_NOACCESS);
if (vm_pCLKPWR == NULL)
{
DEBUGMSG (1,(TEXT("Clock & Power Management Special Register not allocated\n\r")));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto INIT_ERROR;
}
if (!VirtualCopy((PVOID)vm_pCLKPWR, (PVOID)(S3C2440A_BASE_REG_PA_CLOCK_POWER >> 8), sizeof(S3C2440A_CLKPWR_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE)) {
DEBUGMSG (1,(TEXT("Clock & Power Management Special Register not mapped\n\r")));
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 -----
vm_pDMAreg = (S3C2440A_DMA_REG *)VirtualAlloc(0, sizeof(S3C2440A_DMA_REG), MEM_RESERVE, PAGE_NOACCESS);
if (vm_pDMAreg == NULL)
{
DEBUGMSG (1,(TEXT("DMA Register not allocated\n\r")));
status = SD_API_STATUS_INSUFFICIENT_RESOURCES;
goto INIT_ERROR;
}
if (!VirtualCopy((PVOID)vm_pDMAreg, (PVOID)(S3C2440A_BASE_REG_PA_DMA >> 8), sizeof(S3C2440A_DMA_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE)) {
DEBUGMSG (1,(TEXT("DMA Register not mapped\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->SDIFSTA |= FIFO_RESET; // 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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -