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

📄 sd_disk.c

📁 ARM9基于WINDOWSCE的BSP源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************
*   File:    sd_disk.c  -   Control the instance of the card
* 
*   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"

//------------------------------------------------------------------------------
// Global Variables in SD_DISK.C
//------------------------------------------------------------------------------
unsigned long RCA = 0;

extern unsigned char	ChannelNumber;
extern unsigned long	InterruptID;
extern HANDLE		DMAIntrEvent;
//------------------------------------------------------------------------------
//
// Initialize all the things especially the card 
//
// Arguments:
//		controller - instance will be created
//		errorcode - record error. 
//
// Functions:
//		Create an instance.
//		Create the interrupt event.
//		Allocate DMA.
//
//------------------------------------------------------------------------------
SD_controller* 
SDI_InitInterface(
	SD_controller *controller,
	unsigned long *errorcode
	)
{
	unsigned long error = 0;
	if (!controller)
		error = 1;
	if (!error)
	{
		PHYSICAL_ADDRESS sd;
		memset(controller, 0, sizeof(SD_controller));
		sd.HighPart = 0 ;
		sd.LowPart  = PHYS_SD0_BASE;
		
		controller->Registers = (SD_REG*)MmMapIoSpace(sd, (unsigned long)sizeof(SD_REG), FALSE);
		if (!controller->Registers)
			error = 2;
	}
	if (!error)
	{
		controller->InterruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
		if (!controller->InterruptEvent)
		{
			error = 3;
		}
	}
	if (!error)
	{
		SDI_ResetInterface(controller, 0);
	}
	if (!error)
	{
		DMAIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
		if (SDI_AllocateDMA())
		{
			controller->ifDMA = TRUE;
			RETAILMSG(MSG_DISK, (_T("SD: SDI_InitInterface - USE DMA\r\n")));
		}
		else
		{
			controller->ifDMA = FALSE;
			RETAILMSG(MSG_DISK, (_T("SD: SDI_InitInterface - UNUSE DMA\r\n")));
		}
	}
	if (error)
	{
		RETAILMSG(MSG_DISK, (_T("SD: SDI_InitInterface - error:%d\r\n"), error));
		if (errorcode)
			*errorcode = error;
		SDI_DeinitInterface(controller, 0);
		return	0;
	}
	return controller;
}

//------------------------------------------------------------------------------
//
// Start up the card - make it into a work state
//
// Arguments:
//		controller - instance created in SDI_InitInterface
//		errorcode - record error. 
//
// Functions:
//		Power on. 
//		Inialize the interrupt event. 
//		Ask the card to respond. 
//		Get CID & CSD
//		Set clock frequency. (If no DMA, the frequency should be very low)
//
//------------------------------------------------------------------------------
BOOL 
SDI_StartUpCard(
	SD_controller *controller, 
	unsigned long *errorcode
	)
{
	unsigned long error = 0;
	SD_REG *regs;

	RETAILMSG(MSG_DISK, (_T("SD: SDI_StartUpCard +\r\n")));
	
	if (!controller)
		error = 1;
	if (!SDI_IsCardIn(controller, 0))
		error = 7;
	if (!error)
	{
		regs = controller->Registers;
		regs->sd_CLOCK = (1<<8) | (0x40);
		// Set the voltage
		regs->sd_POWER = (15<<2);
		// Power up
		regs->sd_POWER = (1<<7) | (1<<6) | (15<<2) | MCI_POWER_UP;
		Sleep(1);
		// Power on
		regs->sd_POWER = (1<<7) | (1<<6) | (15<<2) | MCI_POWER_ON;
		Sleep(1);
	}
	if (!error)
	{
		if (controller->InterruptEvent)
		{
			if (!InterruptInitialize(SYSINTR_SD0, controller->InterruptEvent, NULL, 0))
				error = 7;
		}
	}
	if (!error)
	{
		int i;
		apMCI_sResponse response;
		response.ShortResponse = 0;	
		
		SDI_SendCmd(controller, &CommandParameters[GO_IDLE_STATE], 0, 0, &error);

		for (i=0; i<10; i++)
		{	// send command to card and wait for respond. 
			SDI_SendCmd(controller, &CommandParameters[APP_CMD], 0, &response, &error);
			SDI_SendCmd(controller, &CommandParameters[SEND_OP_COND], 0xFF8000, &response, &error);
			if ((response.ShortResponse & 0x80000000))
			{
				RETAILMSG(MSG_DISK, (_T("SD: SDI_StartUpCard SEND_OP_COND finished\r\n")));
				break;
			}
			Sleep(1);
		}
		if (i == 200)
			error = 2;
		else
			error = 0;
	}
	if (!error)
	{	// get card identification data
		if (!SDI_GetCID(controller, &controller->CardCID, &error))
			error = 3;
	}
	if (!error)
	{
		apMCI_sResponse response;
		if (!SDI_SendCmd(controller, &CommandParameters[SET_RELATIVE_ADDR], 0, &response, &error))
			error = 4;
		else
		{
			RCA = (unsigned long)(response.ShortResponse) & 0xFFFF0000;
			RETAILMSG(MSG_DISK, (_T("SD: SDI_StartUpCard - RCA=0x%x\r\n"), RCA));
		}
	}
	if (!error)
	{	// get card specific data
		if (!SDI_GetCSD(controller, &controller->CardCSD, RCA, &error))
		{
			error = 5;
		}
	}
	if (!error)
	{
		if (!SDI_SendCmd( controller, &CommandParameters[SELECT_CARD], RCA, 0, errorcode))
		{
			if (!SDI_SendCmd(controller, &CommandParameters[SELECT_CARD], RCA, 0, errorcode))
				error = 8;
		}
	}
	if (!error)	// wide bus mode
	{
		if (!SDI_SendCmd(controller, &CommandParameters[APP_CMD], RCA, 0, errorcode))
			error = 9;
		if (!SDI_SendCmd(controller, &CommandParameters[SET_BUS_WIDTH], (IF_WIDE_BUS<<1), 0, errorcode))
			error = 10;
	}
	if (!error)
	{
		regs->sd_POWER &= ~(1<<6);	// don't use open drain
		if (controller->ifDMA)
			regs->sd_CLOCK = (1<<8) | (0x03);	// set high speed
		else
			return FALSE;
		if (IF_WIDE_BUS)
			regs->sd_CLOCK |= (1<<11);
	}
	if (error)
	{
		RETAILMSG(MSG_DISK, (_T("SD: SDI_StartUpCard - error:%d\r\n"), error));
		if (errorcode)
			*errorcode = error;
		return	FALSE;
	}
	return TRUE;
}

//------------------------------------------------------------------------------
//
// Re-start up the card - make it into a work state
//
// Arguments:
//		controller - instance created in SDI_InitInterface
//		errorcode - record error. 
//
// Functions:
//		Power on. 
//		Inialize the interrupt event. 
//		Ask the card to respond. 
//		Get CID & CSD
//		Set clock frequency. (If no DMA, the frequency should be very low)
//
//------------------------------------------------------------------------------
BOOL 
SDI_ReStartUpCard(
	SD_controller *controller, 
	unsigned long *errorcode
	)
{
	unsigned long error = 0;
	SD_REG *regs;

	RETAILMSG(MSG_DISK, (_T("SD: SDI_ReStartUpCard +\r\n")));
	
	if (!controller)
		error = 1;
	if (!SDI_IsCardIn(controller, 0))
		error = 7;
	if (!error)
	{
		regs = controller->Registers;
		regs->sd_CLOCK = (1<<8) | (0x40);
		// Set the voltage
		regs->sd_POWER = (15<<2);
		// Power up
		regs->sd_POWER = (1<<7) | (1<<6) | (15<<2) | MCI_POWER_UP;
		Sleep(1);
		// Power on
		regs->sd_POWER = (1<<7) | (1<<6) | (15<<2) | MCI_POWER_ON;
		Sleep(1);
	}
	if (!error)
	{
		if (controller->InterruptEvent)
		{
			if (!InterruptInitialize(SYSINTR_SD0, controller->InterruptEvent, NULL, 0))
				error = 7;
		}
	}
	if (!error)
	{
		int i;
		apMCI_sResponse response;
		response.ShortResponse = 0;	
		
		SDI_SendCmd(controller, &CommandParameters[GO_IDLE_STATE], 0, 0, &error);

		for (i=0; i<10; i++)
		{	// send command to card and wait for respond. 
			SDI_SendCmd(controller, &CommandParameters[APP_CMD], 0, &response, &error);
			SDI_SendCmd(controller, &CommandParameters[SEND_OP_COND], 0xFF8000, &response, &error);
			if ((response.ShortResponse & 0x80000000))
			{
				RETAILMSG(MSG_DISK, (_T("SD: SDI_ReStartUpCard SEND_OP_COND finished\r\n")));
				break;
			}
			Sleep(1);
		}
		if (i == 200)
			error = 2;
		else
			error = 0;
	}
	if (!error)
	{
		apMCI_sResponse response;
		if (!SDI_SendCmd(controller, &CommandParameters[SET_RELATIVE_ADDR], 0, &response, &error))
			error = 4;
		else
		{
			RCA = (unsigned long)(response.ShortResponse) & 0xFFFF0000;
			RETAILMSG(MSG_DISK, (_T("SD: SDI_ReStartUpCard - RCA=0x%x\r\n"), RCA));
		}
	}
	if (!error)
	{
		if (!SDI_SendCmd( controller, &CommandParameters[SELECT_CARD], RCA, 0, errorcode))
		{
			if (!SDI_SendCmd(controller, &CommandParameters[SELECT_CARD], RCA, 0, errorcode))
				error = 8;
		}
	}
	if (!error)	// wide bus mode
	{
		if (!SDI_SendCmd(controller, &CommandParameters[APP_CMD], RCA, 0, errorcode))
			error = 9;
		if (!SDI_SendCmd(controller, &CommandParameters[SET_BUS_WIDTH], (IF_WIDE_BUS<<1), 0, errorcode))
			error = 10;
	}
	if (!error)
	{
		regs->sd_POWER &= ~(1<<6);	// don't use open drain
		if (controller->ifDMA)
			regs->sd_CLOCK = (1<<8) | (0x03);	// set high speed
		else
			return FALSE;
		if (IF_WIDE_BUS)
			regs->sd_CLOCK |= (1<<11);
	}
	if (error)
	{
		RETAILMSG(MSG_DISK, (_T("SD: SDI_ReStartUpCard - error:%d\r\n"), error));
		if (errorcode)
			*errorcode = error;
		return	FALSE;
	}
	return TRUE;
}
//------------------------------------------------------------------------------
//
// Reset the card - used when the instance been closed or error occured
//
// Arguments:
//		controller - instance passed by SDI_StartUpCard
//		errorcode - record error. 
//
// Functions:
//		Power off. 
//		Clear interrupt mask
//
//------------------------------------------------------------------------------
BOOL 
SDI_ResetInterface(
	SD_controller *controller, 
	unsigned long *errorcode
	)
{
	unsigned long error = 0;
	if (!controller)
		error = 1;
	if (!error)
	{
		controller->Registers->sd_CLOCK = 0;
		controller->Registers->sd_POWER = 0;
		
		controller->Registers->sd_COMMAND = 0;
		controller->Registers->sd_DATACTRL = 0;
		controller->Registers->sd_CLEAR = MCI_STATUS_STATIC_MASK;
		controller->Registers->sd_MASK0 = controller->Registers->sd_MASK1 = 0;
		
		controller->Registers->sd_CLOCK = apMCI_CLOCK_POWERSAVE;
		
		controller->Registers->sd_POWER = MCI_POWER_OFF;

		InterruptDisable(SYSINTR_SD0);

		Sleep(10);

⌨️ 快捷键说明

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