📄 sd_disk.c
字号:
/***************************************************************************
* 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 + -