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

📄 sd_data.c

📁 ARM9基于WINDOWSCE的BSP源代码
💻 C
字号:
/***************************************************************************
*   File:    sd_data.c  -   Read / Write Functions
* 
*   The content of this file or document is CONFIDENTIAL and PROPRIETARY
*   to Jade Technologies Co., Ltd.  It is subject to the terms of a
*   License Agreement between Licensee and Jade Technologies Co., Ltd.
*   restricting among other things, the use, reproduction, distribution
*   and transfer.  Each of the embodiments, including this information 
*   and any derivative work shall retain this copyright notice.
* 
*   Copyright (c) 2005 Jade Technologies Co., Ltd. 
*   All rights reserved.
****************************************************************************/
#include "sd.h"

unsigned long TempBufAl[SECTORS_PER_BATCH*BYTES_PER_SECTOR/4];
extern unsigned long RCA;

//------------------------------------------------------------------------------
//
// Block read - read a number of sectors from the card
//
// Arguments:
//		controller - instance created in SDI_InitInterface
//		SectorNum - the number of first sector to be read
//		SectorCnt - how many sectors to be read
//		buffer - buffer to receive data
//		errorcode - record error. 
//
// Functions:
//		Call function SDI_SafeRead to read data sector by sector. 
//
//------------------------------------------------------------------------------
BOOL 
SDI_BlockRead(
	SD_controller* controller, 
	unsigned long SectorNum, 
	unsigned long SectorCnt, 
	unsigned char* buffer, 
	unsigned long* errorcode
	)
{
	unsigned long error = 0;
	if (!controller)
		error = 1;
	if (!error)
	{
		unsigned long i;
		unsigned long sectors_this = 0;
		for (i=0; i<SectorCnt; i+=SECTORS_PER_BATCH)
		{
			sectors_this = MIN(SECTORS_PER_BATCH, (SectorCnt-i));
			if (!SDI_SafeRead(controller, SectorNum+i, sectors_this, buffer+i*BYTES_PER_SECTOR, &error))
			{
				error = 2;
				break;
			}
		}
	}
	if (error)
	{
		RETAILMSG(MSG_DATA, (_T("SD: SDI_BlockRead - error:%d\r\n"), error));
		if (errorcode)
			*errorcode = error;
		return	FALSE;
	}
	return TRUE;
}

//------------------------------------------------------------------------------
//
// Block write - write a number of sectors to the card
//
// Arguments:
//		controller - handle for the instance
//		SectorNum - the number of first sector to be write
//		SectorCnt - how many sectors to be write
//		buffer - buffer to send data
//		errorcode - record error
//
// Functions:
//		Call function SDI_SafeWrite to write data sector by sector. 
//
//------------------------------------------------------------------------------
BOOL 
SDI_BlockWrite(
	SD_controller* controller, 
	unsigned long SectorNum, 
	unsigned long SectorCnt, 
	unsigned char* buffer, 
	unsigned long* errorcode
	)
{
	unsigned long error = 0;
	if (!controller)
		error = 1;
	if (!error)
	{
		unsigned long i;
		unsigned long sectors_this = 0;
		for (i=0; i<SectorCnt; i+=SECTORS_PER_BATCH)
		{
			sectors_this = MIN(SECTORS_PER_BATCH, (SectorCnt-i));
			if (!SDI_SafeWrite(controller, SectorNum+i, sectors_this, buffer+i*BYTES_PER_SECTOR, &error))
			{
				error = 2;
				break;
			}
		}
	}
	if (error)
	{
		RETAILMSG(MSG_DATA, (_T("SD: SD_BlockWrite - error:%d\r\n"), error));
		if (errorcode)
			*errorcode = error;
		return	FALSE;
	}
	return TRUE;
}

// for safe, retry RETRYNUM times if error.
#define RETRYNUM 3	
//------------------------------------------------------------------------------
//
// Safe read - read a sector from the card
//
// Arguments:
//		controller - instance created in SDI_InitInterface
//		SectorNum - the number of first sector to be read
//		buffer - buffer to receive data
//		errorcode - record error. 
//
// Functions:
//		Call function SDI_SectorRead_FIFO or SDI_SectorRead_DMA 
//		to read data from a single sector. Reset if error occured, 
//		and retry last sector. 
//
//------------------------------------------------------------------------------
BOOL 
SDI_SafeRead(
	SD_controller* controller, 
	unsigned long SectorNum, 
	unsigned long SectorCnt,
	unsigned char* buffer, 
	unsigned long* errorcode
	)
{
	unsigned long error = 0;
	unsigned long retry = RETRYNUM+1;
	unsigned char * bufthis;

	if ((int)buffer&0x3)
		bufthis = (unsigned char*)TempBufAl;
	else
		bufthis = (unsigned char*)buffer;
	
	if (!controller)
		error = 1;
	if (!error)
	{
		while (--retry)
		{
			if (controller->ifDMA)
			{
				SDI_BatchRead_DMA(controller, SectorNum, SectorCnt, bufthis, &error);
			}
			else
			{
				return FALSE;
			}
			if (!error)
				break;
			else
			{
				if (error > 2)
				{
					error = 0;
					SDI_ResetInterface(controller, &error);
					SDI_StartUpCard(controller, &error);
					if (error)
					{
						error = 4;
						break;
					}
				}
				else
				{
					error = 3;
					break;
				}
			}
		}
		if (retry != (RETRYNUM))
			RETAILMSG(MSG_DATA, (_T("SD: SDI_SafeRead - retry:%d\r\n"), (RETRYNUM-retry)));
		if (!retry)
			error = 2;
	}
	
	if ((int)buffer&0x3)
		memcpy(buffer, TempBufAl, BYTES_PER_SECTOR*SectorCnt);
	if (error)
	{
		RETAILMSG(MSG_DATA, (_T("SD: SDI_SafeRead - error:%d\r\n"), error));
		if (errorcode)
			*errorcode = error;
		return FALSE;
	}
	return TRUE;
}

//------------------------------------------------------------------------------
//
// Safe write - write a sector to the card
//
// Arguments:
//		controller - instance created in SDI_InitInterface
//		SectorNum - the number of first sector to be write
//		buffer - buffer to send data
//		errorcode - record error. 
//
// Functions:
//		Call function SDI_SectorWrite_FIFO or SDI_SectorWrite_DMA 
//		to write data to a single sector. Reset if error occured, 
//		and retry last sector. 
//
//------------------------------------------------------------------------------
BOOL 
SDI_SafeWrite(
	SD_controller* controller, 
	unsigned long SectorNum, 
	unsigned long SectorCnt,
	unsigned char* buffer, 
	unsigned long* errorcode
	)
{
	unsigned long error = 0;
	unsigned long retry = RETRYNUM+1;
	unsigned char * bufthis;
	if ((int)buffer&0x3)
	{
		bufthis = (unsigned char*)TempBufAl;
		memcpy(TempBufAl, buffer, BYTES_PER_SECTOR*SectorCnt);
	}
	else
		bufthis = (unsigned char*)buffer;

	if (!controller)
		error = 1;
	if (!error)
	{
		while (--retry)
		{
			if (controller->ifDMA)
			{
				SDI_BatchWrite_DMA(controller, SectorNum, SectorCnt, bufthis, &error);
			}
			else
			{
				return FALSE;
			}
			if (!error)
				break;
			else
			{
				if (error > 2)
				{
					error = 0;
					SDI_ResetInterface(controller, &error);
					SDI_StartUpCard(controller, &error);
					if (error)
					{
						error = 4;
						break;
					}
				}
				else
				{
					error = 3;
					break;
				}
			}
		}
		if (retry != (RETRYNUM))
			RETAILMSG(MSG_DATA, (_T("SD: SDI_SafeWrite - retry:%d\r\n"), (RETRYNUM-retry)));
		if (!retry)
			error = 2;
	}
	
	if (error)
	{
		RETAILMSG(MSG_DATA, (_T("SD: SDI_SafeWrite - error:%d\r\n"), error));
		if (errorcode)
			*errorcode = error;
		return FALSE;
	}
	return TRUE;
}

//------------------------------------------------------------------------------
//
// Read data from SD FIFO register by DMA
//
// Arguments:
//		controller - instance created in SDI_InitInterface
//		SectorNum - the number of first sector to be read
//		SectorCnt - how many sectors to be write
//		buffer - buffer to receive data
//		errorcode - record error. 
//
// Functions:
//		Send command to card, then call functions SDI_InitDMA
//		and SDI_StartDMA finished the transfer. 
//
//------------------------------------------------------------------------------
BOOL 
SDI_BatchRead_DMA(
	SD_controller* controller, 
	unsigned long SectorNum, 
	unsigned long SectorCnt,
	unsigned char* buffer, 
	unsigned long* errorcode	
	)
{
	unsigned long error = 0;
	unsigned long DataCtrl = 0;
	SD_REG *regs;

	if (!controller || !buffer)
		error = 1;
	if (!error)
	{
		if (SectorNum >= controller->CardCSD.CardSize / BYTES_PER_SECTOR)
			error = 2;
	}
	if (!error)
	{
		if (!SDI_InitDMA(DISK_IOCTL_READ))
		{
			error = 5;
		}
	}
	regs = controller->Registers;
	if (!error)
	{
		if (!SDI_StartDMA(DISK_IOCTL_READ, ((unsigned long)PHYS_SD0_BASE+0x80), buffer, SectorCnt*BYTES_PER_SECTOR))
		{
			error = 6;
		}
	}
	if (!error)
	{
		unsigned long temp = 0;
		if (!SDI_SendCmd(controller, &CommandParameters[SET_BLOCKLEN], BYTES_PER_SECTOR, 0, &temp))
		{
			if (!SDI_SendCmd(controller, &CommandParameters[SET_BLOCKLEN], BYTES_PER_SECTOR, 0, &temp))
				error = 3;
		}
	}
	if (!error)
	{
		apBIT_SET(DataCtrl, MCI_DATA_ENABLE,1);
		apBIT_SET(DataCtrl, MCI_DATA_DIRECTION, apMCI_DATA_RECEIVE);
		apBIT_SET(DataCtrl, MCI_DATA_MODE, apMCI_DATA_BLOCKING);
		apBIT_SET(DataCtrl, MCI_DATA_DMA_ENABLE, 1);
		apBIT_SET(DataCtrl, MCI_DATA_BLOCKSIZE, BYTES_PER_SECTOR_SH);
		regs->sd_MASK0	= 0;
		regs->sd_CLEAR	= MCI_STATUS_STATIC_MASK;
		regs->sd_DATATMR  = 0xFFFFFFFF;
		regs->sd_DATALEN  = 0xFFFF;
		regs->sd_DATACTRL = DataCtrl;
		if (!SDI_SendCmd(controller, &CommandParameters[READ_MULTIPLE_BLOCK], SectorNum * BYTES_PER_SECTOR, 0, &error))
		{
			error = 4;
		}
	}
	if (!error)
	{
		if (!SDI_WaitDMA(DISK_IOCTL_READ, ((unsigned long)PHYS_SD0_BASE+0x80), buffer, SectorCnt*BYTES_PER_SECTOR))
		{
			error = 8;
		}
	}
	if (!error)
	{
		unsigned long FIFO_Dumper = 0;
		while (regs->sd_STATUS & MCI_STATUS_RXDATAAVLBL)
			FIFO_Dumper = regs->sd_FIFO;
	}	
	if (!error)
	{
		if (!SDI_SendCmd(controller, &CommandParameters[STOP_TRANSMISSION], 0, 0, &error))
		{
			error = 7;
		}	
	}
	if (!error)
	{
		apMCI_sResponse response;
		int i;
		response.ShortResponse = 0;
		for (i=0; i<100; i++)
		{
			SDI_SendCmd(controller, &CommandParameters[SEND_STATUS], RCA, &response, 0) ;
			if (((response.ShortResponse >> 9) & 0x0F) == ST_TRAN)
				break;
			Sleep(1);
		}
	}
	if (!error)
	{
		regs->sd_DATACTRL = 0;
		regs->sd_CLEAR = MCI_STATUS_STATIC_MASK;
	}
	if (error)
	{
		RETAILMSG(MSG_DATA, (_T("SD: SDI_BatchRead_DMA - error:%d\r\n"), error));
		if (errorcode)
			*errorcode = error;
		return FALSE;
	}
	return TRUE;
}

//------------------------------------------------------------------------------
//
// Write data to SD FIFO register by DMA
//
// Arguments:
//		controller - instance created in SDI_InitInterface
//		SectorNum - the number of first sector to be write
//		SectorCnt - how many sectors to be write
//		buffer - buffer to send data
//		errorcode - record error. 
//
// Functions:
//		Send command to card, then call functions SDI_InitDMA
//		and SDI_StartDMA finished the transfer. 
//
//------------------------------------------------------------------------------
BOOL 
SDI_BatchWrite_DMA(
	SD_controller* controller, 
	unsigned long SectorNum, 
	unsigned long SectorCnt, 
	unsigned char* buffer, 
	unsigned long* errorcode
	)
{
	unsigned long error = 0;
	unsigned long DataCtrl = 0;
	SD_REG *regs;
	if (!controller || !buffer)
		error = 1;
	if (!error)
	{
		if (SectorNum >= controller->CardCSD.CardSize / BYTES_PER_SECTOR)
			error = 2;
	}
	if (!error)
	{
		if (!SDI_InitDMA(DISK_IOCTL_WRITE))
		{
			error = 5;
		}
	}
	regs = controller->Registers;
	if (!error)
	{
		unsigned long temp = 0;
		if (!SDI_SendCmd(controller, &CommandParameters[SET_BLOCKLEN], BYTES_PER_SECTOR, 0, &temp))
		{
			if (!SDI_SendCmd(controller, &CommandParameters[SET_BLOCKLEN], BYTES_PER_SECTOR, 0, &temp))
				error = 3;
		}
	}
	if (!error)
	{
		apBIT_SET(DataCtrl, MCI_DATA_ENABLE,1);
		apBIT_SET(DataCtrl, MCI_DATA_DIRECTION, apMCI_DATA_TRANSMIT);
		apBIT_SET(DataCtrl, MCI_DATA_MODE, apMCI_DATA_BLOCKING);
		apBIT_SET(DataCtrl, MCI_DATA_DMA_ENABLE, 1);
		apBIT_SET(DataCtrl, MCI_DATA_BLOCKSIZE, BYTES_PER_SECTOR_SH);
		regs->sd_MASK0	= 0;
		regs->sd_CLEAR	= MCI_STATUS_STATIC_MASK;
		regs->sd_DATATMR  = 0xFFFFFFFF;
		regs->sd_DATALEN  = 0xFFFF;
		regs->sd_DATACTRL = DataCtrl;
		if (!SDI_SendCmd(controller, &CommandParameters[WRITE_MULTIPLE_BLOCK], SectorNum * BYTES_PER_SECTOR, 0, &error))
		{
			error = 4;
		}
	}
	if (!error)
	{
		if (!SDI_StartDMA(DISK_IOCTL_WRITE, ((unsigned long)PHYS_SD0_BASE+0x80), buffer, SectorCnt*BYTES_PER_SECTOR))
		{
			error = 6;
		}
	}
	if (!error)
	{
		if (!SDI_WaitDMA(DISK_IOCTL_WRITE, ((unsigned long)PHYS_SD0_BASE+0x80), buffer, SectorCnt*BYTES_PER_SECTOR))
		{
			error = 8;
		}
	}
	if (!error)
	{
		while (regs->sd_STATUS & MCI_STATUS_TXDATAAVLBL);	// wait the Tx FIFO empty
	}
	if (!error)
	{
		if (!SDI_SendCmd(controller, &CommandParameters[STOP_TRANSMISSION], 0, 0, &error))
		{
			error = 7;
		}	
	}
	if (!error)
	{
		apMCI_sResponse response;
		int i;
		response.ShortResponse = 0;
		for (i=0; i<100; i++)
		{
			SDI_SendCmd(controller, &CommandParameters[SEND_STATUS], RCA, &response, 0) ;
			if (((response.ShortResponse >> 9) & 0x0F) == ST_TRAN)
				break;
			Sleep(1);
		}
	}
	if (!error)
	{
		regs->sd_DATACTRL = 0;
		regs->sd_CLEAR = MCI_STATUS_STATIC_MASK;
	}
	if (error)
	{
		RETAILMSG(MSG_DATA, (_T("SD: SDI_BatchWrite_DMA - error:%d\r\n"), error));
		if (errorcode)
			*errorcode = error;
		return FALSE;
	}
	return TRUE;
}

⌨️ 快捷键说明

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