//
// 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 OR INDEMNITIES.
//
//
// (C) Copyright 2006 Marvell International Ltd.
// All Rights Reserved
//
//
// Copyright (c) 2002 BSQUARE Corporation. All rights reserved.
// DO NOT REMOVE --- BEGIN EXTERNALLY DEVELOPED SOURCE CODE ID 40973--- DO NOT REMOVE
//
// Module Name:
//
// SDControl.c
//
// Abstract:
//
// PXA SDIO controller implementation
//
// Notes:
//
///////////////////////////////////////////////////////////////////////////////
//#define EXTENSIVE_DEBUGGING
#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include "SD.h"
#if(CEATA_CCS_MODE)
HANDLE hCEATACCSIntrEvent;
XLLP_UINT32_T CCSStatus;
#define SYSINTR_CEATACCS 21
#endif
#define DMA_TEST_MODE
#ifdef DMA_TEST_MODE
#include "xllp_dmac.h"
#include "dmawince.h"
//#include <monahans_base_regs.h>
//#include <monahans_mmc.h>
//#define PAGE_SIZE 0x1000 // ?? Put this is drvglob.h ?? // See ceddk.h
#define TRANSFER_BUF_SIZE ( 2 * 16 * 0x400) // 32KB. Good to be multiple of 4KB, the PAGE_SIZE.
// Double buffering used for Xmt and Rcv.
#define NUM_DESC 0x10 // Desc in a Xmt or Rcv chain
//#define NUM_SDIO_XMT_DESC (2 * NUM_DESC) // Two Xmt Desc chains
//#define NUM_SDIO_RCV_DESC (2 * NUM_DESC) // Two Rcv Desc chains
#define NUM_SDIO_XR_DESC (2 * NUM_DESC) // Two Desc chains. Xmt or Rcv, but never both.
#define SIZE_SDIO_DESC sizeof(XLLP_DMAC_DESCRIPTOR_T)
#define TOTAL_BUF_SIZE (( NUM_SDIO_XR_DESC * SIZE_SDIO_DESC) + TRANSFER_BUF_SIZE )
typedef enum
{
XMT_SDIO,
RCV_SDIO
} SDIOTRANFER;
typedef struct _NextXRBuffers
{
volatile XLLP_DMAC_DESCRIPTOR_T *pVirtDescriptor; // Descriptor Virt Start Addr.
P_XLLP_DMAC_DESCRIPTOR_T pPhysDescriptor; // Descriptor Phys Start Addr.
P_XLLP_INT8_T pStartVirtDataBuffer; //
P_XLLP_INT8_T pStartPhysDataBuffer; //
XLLP_UINT32_T Length; // Bytes specified in Desc chain transfer.
BOOL MoreDataToTransfer;
} NextXRBuffers;
typedef struct _SDHCDmacDescriptor{
XLLP_DMAC_CHANNEL_T RcvChannel ;
XLLP_DMAC_CHANNEL_T XmtChannel ;
HANDLE DMATxEventHandle ;
HANDLE DMARxEventHandle ;
P_XLLP_DMAC_T pDMACHandle ;
XLLP_DMAC_DESCRIPTOR_T *pDescVirtXR ; // Used for both Xmt and Rcv.
P_XLLP_DMAC_DESCRIPTOR_T pDescPhysXR ; // SD/SDIO bus is simplex.
// Buffer pointers for use with HalAllocateCommonBuffer(...)
PHYSICAL_ADDRESS PhysAdr_HalAlloComBuf;
P_XLLP_UINT8_T VirtAdr_HalAlloComBuf;
NextXRBuffers NextTransfer[2]; // Double buffering for Xmt and Rcv DMA.
ULONG i_NT; // Index for NextTransfer array.
ULONG CommittedToRcvNT; // Total Rcv bytes spec'd in current descriptor set.
_TCHAR DMAEventName[20]; //
//other configures to replace hard code
XLLP_DMAC_DRCMR_T rxChannel, txChannel;
}SDHCDmacDescriptor, * PSDHCDmacDescriptor;
//static SDHCDmacDescriptor SDHCDmacDscr;
#endif //end #ifdef DMA_TEST_MODE
// prototypes
DWORD SDControllerIstThread(PSDH_HARDWARE_CONTEXT pHCDevice);
#ifndef DDEBUG
void DumpRegisters(PSDH_HARDWARE_CONTEXT pController) {}
void DumpGPIORegisters(PSDH_HARDWARE_CONTEXT pController) {}
#endif
#ifdef DEBUG
#define HEXBUFSIZE 1024
char szHexBuf[HEXBUFSIZE];
#define TRANSFER_SIZE(pRequest) ((pRequest)->BlockSize * (pRequest)->NumBlocks)
char* HexDisplay(PSD_BUS_REQUEST pRequest, BYTE *pBuffer, DWORD dwLength )
{
DWORD dwTemp = 0;
// we are touching the block buffer, we must set the process permissions
SD_SET_PROC_PERMISSIONS_FROM_REQUEST(pRequest) {
while( dwTemp < dwLength && (dwTemp < (HEXBUFSIZE / 2 - 1) ) )
{
szHexBuf[dwTemp*2] = pBuffer[dwTemp] / 16;
szHexBuf[dwTemp*2+1] = pBuffer[dwTemp] % 16;
if( szHexBuf[dwTemp*2] < 10 )
szHexBuf[dwTemp*2] += '0';
else
szHexBuf[dwTemp*2] += 'a' - 10;
if( szHexBuf[dwTemp*2+1] < 10 )
szHexBuf[dwTemp*2+1] += '0';
else
szHexBuf[dwTemp*2+1] += 'a' - 10;
dwTemp++;
}
} SD_RESTORE_PROC_PERMISSIONS();
szHexBuf[dwTemp*2] = 0;
return szHexBuf;
}
#endif
__inline void WRITE_MMC_REGISTER_DWORD(PSDH_HARDWARE_CONTEXT pHc, DWORD RegOffset, DWORD Value)
{
BYTE *pRegBaseAddr, *regAddr;
volatile DWORD *pdwRegAddr;
pRegBaseAddr = (BYTE*)(pHc->pSDMMCRegisters);
regAddr = pRegBaseAddr + RegOffset;
pdwRegAddr = (DWORD*)regAddr;
*pdwRegAddr = Value;
}
__inline DWORD READ_MMC_REGISTER_DWORD(PSDH_HARDWARE_CONTEXT pHc, DWORD RegOffset)
{
BYTE *pRegBaseAddr, *regAddr;
volatile DWORD *pdwRegAddr;
pRegBaseAddr = (BYTE*)(pHc->pSDMMCRegisters);
regAddr = pRegBaseAddr + RegOffset;
pdwRegAddr = (DWORD*)regAddr;
return (*pdwRegAddr);
}
#define IS_PROGRAM_DONE(pHc) (READ_MMC_REGISTER_DWORD((pHc), MMC_STAT) & MMC_STAT_PROGRAM_DONE)
#define IS_TRANSFER_DONE(pHc) (READ_MMC_REGISTER_DWORD((pHc), MMC_STAT) & MMC_STAT_DATA_TRANSFER_DONE)
//#define RX_FIFO_FULL(pHc) (READ_MMC_REGISTER_DWORD((pHc), MMC_STAT) & MMC_STAT_RCV_FIFO_FULL)
//#define TX_FIFO_EMPTY(pHc) (READ_MMC_REGISTER_DWORD((pHc), MMC_STAT) & MMC_STAT_XMIT_FIFO_EMPTY)
#define TRANSFER_IS_WRITE(pRequest) ((SD_WRITE == (pRequest)->TransferClass))
#define TRANSFER_IS_READ(pRequest) ((SD_READ == (pRequest)->TransferClass))
BOOL CLOCK_IS_ON(PSDH_HARDWARE_CONTEXT pHc)
{
if( READ_MMC_REGISTER_DWORD( pHc, MMC_STAT ) & MMC_STAT_CLOCK_ENABLED )
{
return TRUE;
}
else
{
return FALSE;
}
}
__inline void READ_MOD_WRITE_MMC_REGISTER_AND_OR(PSDH_HARDWARE_CONTEXT pHc, DWORD RegOffset, DWORD AndValue, DWORD OrValue)
{
DWORD regValue;
regValue = READ_MMC_REGISTER_DWORD(pHc, RegOffset);
regValue &= (AndValue);
regValue |= (OrValue);
DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("SHCDriver: - Setting MMC Reg 0x%x to 0x%x\r\n"), RegOffset, regValue));
WRITE_MMC_REGISTER_DWORD(pHc, RegOffset, regValue);
}
__inline void WRITE_MMC_IMASK_DWORD(PSDH_HARDWARE_CONTEXT pHc, DWORD Value)
{
EnterCriticalSection(&(pHc->intrRegCriticalSection));
WRITE_MMC_REGISTER_DWORD( pHc, MMC_IMASK, Value);
LeaveCriticalSection(&(pHc->intrRegCriticalSection));
}
__inline DWORD READ_MMC_IMASK_DWORD(PSDH_HARDWARE_CONTEXT pHc)
{
DWORD dwRetVal;
EnterCriticalSection(&(pHc->intrRegCriticalSection));
dwRetVal = READ_MMC_REGISTER_DWORD( pHc, MMC_IMASK );
LeaveCriticalSection(&(pHc->intrRegCriticalSection));
return dwRetVal;
}
__inline void READ_MOD_WRITE_MMC_IMASK_AND_OR(PSDH_HARDWARE_CONTEXT pHc, DWORD AndValue, DWORD OrValue)
{
EnterCriticalSection(&(pHc->intrRegCriticalSection));
READ_MOD_WRITE_MMC_REGISTER_AND_OR( pHc, MMC_IMASK, AndValue, OrValue );
LeaveCriticalSection(&(pHc->intrRegCriticalSection));
}
#define CLOCK_OFF_INTERRUPT_OFF(pHc) \
READ_MOD_WRITE_MMC_IMASK_AND_OR(pHc, 0xffffffff, MMC_IMASK_CLOCK_OFF_INT_MASKED)
// macro to turn SDIO interrupts on
#define SDIO_INTERRUPT_ON(pHc) \
READ_MOD_WRITE_MMC_IMASK_AND_OR(pHc, ~MMC_IMASK_SDIO_INT_MASKED, 0)
// macro to turn SDIO interrupts off
#define SDIO_INTERRUPT_OFF(pHc) \
READ_MOD_WRITE_MMC_IMASK_AND_OR(pHc, 0xffffffff, MMC_IMASK_SDIO_INT_MASKED)
// macro to turn RX FIFO interrupts on
#define RX_FIFO_INTERRUPT_ON(p