?? sdmmcboot.c
字號(hào):
//
//
#include <windows.h>
#include <nkintr.h>
#include <bulverde.h>
#include <mainstoneii.h>
#include <oal_memory.h>
#include <pcireg.h>
#include <fmd.h>
#include <xllp_pccardsocket.h>
#include <bsp.h>
#include "loader.h"
#include "sd.h"
#include "fatsys.h"
#define MSC_PASSED 1
#define MSC_FAILED 0
#define Log EdbgOutputDebugString
//#define USE_DMA_CHANNEL 2
#define MAX_READ_BLOCK 0x800 // 1M size Must < 16M since DMA
#define MAX_SEC_PER_CLUS 0x8
#define NK_FILENAME "nk"
#define NK_EXTNAME "nb0"
unsigned int ReadDataBuf[0x80 * MAX_SEC_PER_CLUS], ReadFatBuf[0x80 * MAX_SEC_PER_CLUS];
unsigned int PartInfoBuf[0x100];
volatile BULVERDE_MMC_REG *pSDMMCRegisters;
volatile BULVERDE_CLKMGR_REG *pClkMgrRegisters;
volatile BULVERDE_GPIO_REG *pGPIORegisters;
void dump_sector (unsigned int *);
int send_command_to_cards (unsigned char cmd, unsigned int arg, unsigned int cmdat,
unsigned int nob, unsigned wait, unsigned int slow);
unsigned int CardAddr, read_file = 0, datwidth = 0;
struct BootSec *pBootSec;
struct PartInfo bootPartInfo;
struct FileInfo imagefile;
unsigned char nk_name[9] = NK_FILENAME;
unsigned char nk_ext[4] = NK_EXTNAME;
void WRITE_MMC_REGISTER_DWORD(volatile BULVERDE_MMC_REG *pSDMMCRegisters, DWORD RegOffset, DWORD Value)
{
BYTE *pRegBaseAddr, *regAddr;
volatile DWORD *pdwRegAddr;
pRegBaseAddr = (BYTE*)pSDMMCRegisters;
regAddr = pRegBaseAddr + RegOffset;
pdwRegAddr = (DWORD*)regAddr;
*pdwRegAddr = Value;
}
DWORD READ_MMC_REGISTER_DWORD(volatile BULVERDE_MMC_REG *pSDMMCRegisters, DWORD RegOffset)
{
BYTE *pRegBaseAddr, *regAddr;
volatile DWORD *pdwRegAddr;
pRegBaseAddr = (BYTE*)pSDMMCRegisters;
regAddr = pRegBaseAddr + RegOffset;
pdwRegAddr = (DWORD*)regAddr;
return (*pdwRegAddr);
}
int send_command_to_cards (unsigned char cmd, unsigned int arg, unsigned int cmdat,
unsigned int nob, unsigned wait, unsigned int slow)
{
volatile DWORD mmc_stat;
//stop the clock
mmc_stat = READ_MMC_REGISTER_DWORD( pSDMMCRegisters, MMC_STAT );
if (mmc_stat & MMC_STAT_CLOCK_ENABLED)
{
WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_STRPCL, MMC_STRPCL_STOP_CLOCK);
do {
mmc_stat = READ_MMC_REGISTER_DWORD( pSDMMCRegisters, MMC_STAT );
} while (mmc_stat & MMC_STAT_CLOCK_ENABLED);
}
if (slow)
WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_CLKRT, 0x6);
else
WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_CLKRT, 0x1);
if (datwidth)
{
cmdat |= MMC_CMDAT_SD_4DAT;
//Log (" ***************** buswidth is 0x%x **********\n", datwidth);
}
WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_CMDAT, cmdat);
WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_RESTO, 0x7f);
WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_RDTO, 0xffff);
if (cmd == 17 || cmd == 18)
WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_BLKLEN, 0x200);
else
WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_BLKLEN, 0);
WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_NOB, nob);
WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_IMASK, 0x1fff);
WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_CMD, cmd);
WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_ARGH, (arg >> 16));
WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_ARGL, (arg & 0xffff));
// clock is on
mmc_stat = READ_MMC_REGISTER_DWORD( pSDMMCRegisters, MMC_STAT ); // & MMC_STAT_CLOCK_ENABLED
if (! (mmc_stat & MMC_STAT_CLOCK_ENABLED))
{
WRITE_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_STRPCL, MMC_STRPCL_START_CLOCK);
do {
mmc_stat = READ_MMC_REGISTER_DWORD( pSDMMCRegisters, MMC_STAT );
} while (! (mmc_stat & MMC_STAT_CLOCK_ENABLED));
}
if (wait)
{
// get respond complete
do {
mmc_stat = READ_MMC_REGISTER_DWORD( pSDMMCRegisters, MMC_STAT );
} while (! (mmc_stat & MMC_STAT_END_CMD_RES));
if ((mmc_stat & 0x3f) != 0)
{
Log ("!! Error !!: mmc_status is 0x%x\n", mmc_stat);
return MSC_FAILED;
}
}
return MSC_PASSED;
}
int getrespondR1 (int dump)
{
unsigned int respbuf[0x10], i, status;
unsigned char *bufp;
unsigned short val16;
volatile DWORD mmc_stat;
mmc_stat = READ_MMC_REGISTER_DWORD( pSDMMCRegisters, MMC_STAT );
if ((mmc_stat & 0x3f) != 0)
{
Log ("!! Error !!: status is 0x%x\n", mmc_stat);
return MSC_FAILED;
}
// get respond with R1
bufp = (unsigned char *)respbuf;
for (i = 0; i < 3; i++)
{
val16 = (USHORT)(READ_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_RES));
*bufp++ = (val16 >> 8) & 0xff;
*bufp++ = val16 & 0xff;
}
bufp = (unsigned char *)respbuf;
status = (bufp[1] << 24) | (bufp[2] << 16) | (bufp[3] << 8) | (bufp[4] << 0);
imagefile.SDcardState = (status >> 8) & 0x0F;
if (dump)
{
Log ("Get response <R1> (0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
bufp[0], bufp[1], bufp[2], bufp[3], bufp[4], bufp[5]);
}
else
if ((status & 0xFFFFF000) != 0)
{
Log ("!! Error !!: response <R1> (0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
bufp[0], bufp[1], bufp[2], bufp[3], bufp[4], bufp[5]);
return MSC_FAILED;
}
return MSC_PASSED;
}
int checkSDcard (void)
{
unsigned int respbuf[0x30];
unsigned char *bufp;
volatile unsigned int i;
unsigned short val16;
/**********************************************************************************/
DWORD dwRegVal;
volatile DWORD mmc_stat;
datwidth = 0;
pGPIORegisters = (volatile BULVERDE_GPIO_REG *) OALPAtoVA(BULVERDE_BASE_REG_PA_GPIO, FALSE);
pClkMgrRegisters = (volatile BULVERDE_CLKMGR_REG *) OALPAtoVA(BULVERDE_BASE_REG_PA_CLKMGR, FALSE);
pSDMMCRegisters = (volatile BULVERDE_MMC_REG *) OALPAtoVA (BULVERDE_BASE_REG_PA_MMC, FALSE);
//////////////////////////////////////////////////////////
// Configure GPIO_32 as Alternate Function 2 out (MMC_CLK)
// assume that the MMC_CLK is active-low signal driven
dwRegVal = pGPIORegisters->GPCR1;
dwRegVal |= 0x00000001;
pGPIORegisters->GPCR1 = dwRegVal;
// change the direction to OUT
dwRegVal = pGPIORegisters->GPDR1;
dwRegVal |= 0x00000001;
pGPIORegisters->GPDR1 = dwRegVal;
// change to Alternate Function 2
dwRegVal = pGPIORegisters->GAFR1_L;
dwRegVal = ( dwRegVal & 0xfffffffc ) | 0x00000002;
pGPIORegisters->GAFR1_L = dwRegVal;
//////////////////////////////////////////////////////////
// Configure GPIO_112 as Alternate Function 1 (MMC_CMD)
// assume that the MMC_CLK is active-high signal driven
dwRegVal = pGPIORegisters->GPSR3;
dwRegVal |= 0x00010000;
pGPIORegisters->GPSR3 = dwRegVal;
// change the direction to OUT
dwRegVal = pGPIORegisters->GPDR3;
dwRegVal |= 0x00010000;
pGPIORegisters->GPDR3 = dwRegVal;
// change to Alternate Function 1
dwRegVal = pGPIORegisters->GAFR3_U;
dwRegVal = ( dwRegVal & 0xfffffffc ) | 0x00000001;
pGPIORegisters->GAFR3_U = dwRegVal;
//////////////////////////////////////////////////////////
// Configure GPIO_92 as Alternate Function 1 (MMC_DAT0)
// assume that the MMC_CLK is active-high signal driven
dwRegVal = pGPIORegisters->GPSR2;
dwRegVal |= 0x10000000;
pGPIORegisters->GPSR2 = dwRegVal;
// change the direction to OUT
dwRegVal = pGPIORegisters->GPDR2;
dwRegVal |= 0x10000000;
pGPIORegisters->GPDR2 = dwRegVal;
// change to Alternate Function 1
dwRegVal = pGPIORegisters->GAFR2_U;
dwRegVal = ( dwRegVal & 0xfcffffff ) | 0x01000000;
pGPIORegisters->GAFR2_U = dwRegVal;
//////////////////////////////////////////////////////////
// Configure GPIO_109-GPIO_111 as Alternate Function 1 (MMC_DAT1-MMC_DAT3)
// assume that the MMC_CLK is active-high signal driven
dwRegVal = pGPIORegisters->GPSR3;
dwRegVal |= 0x0000e000;
pGPIORegisters->GPSR3 = dwRegVal;
// change the direction to OUT
dwRegVal = pGPIORegisters->GPDR3;
dwRegVal |= 0x0000e000;
pGPIORegisters->GPDR3 = dwRegVal;
// change to Alternate Function 1
dwRegVal = pGPIORegisters->GAFR3_L;
dwRegVal = ( dwRegVal & 0x03ffffff ) | 0x54000000;
pGPIORegisters->GAFR3_L = dwRegVal;
// enable the MMC Unit Clock
dwRegVal = pClkMgrRegisters->cken;
dwRegVal |= (1 << 12);
pClkMgrRegisters->cken = dwRegVal;
//EdbgOutputDebugString("Address init complete\r\n");
// Reset SD/MMC card (CMD0) (state 0: idle)
Log ("Send command 0 to card (Reset SD/MMC).\n");
if (send_command_to_cards (0, 0, (MMC_CMDAT_INIT | MMC_CMDAT_RESPONSE_NONE), 0, 0, 1)
!= MSC_PASSED)
return MSC_FAILED;
// get respond complete
do {
mmc_stat = READ_MMC_REGISTER_DWORD( pSDMMCRegisters, MMC_STAT );
} while (! (mmc_stat & MMC_STAT_END_CMD_RES));
// send ACMD41 (SD_SEND_OP_COND) (01: redy) ****************
Log ("Send ACMD41 to card (Reset SD/MMC).\n");
Log ("MMC stat is 0x%x\n", mmc_stat);
while (1)
{
// send cmd55 with R1
// send cmd55 with R1
if (send_command_to_cards (55, 0, MMC_CMDAT_RESPONSE_R1, 0, 1, 1) != MSC_PASSED)
return MSC_FAILED;
if (getrespondR1 (1) != MSC_PASSED)
return MSC_FAILED;
// send acmd41 (SD_SEND_OP_COND) with R3
if (send_command_to_cards (41, 0x00ff8000, MMC_CMDAT_RESPONSE_R3, 0, 1, 1) != MSC_PASSED)
return MSC_FAILED;
// get respond with R3
bufp = (unsigned char *)respbuf;
for (i = 0; i < 3; i++)
{
val16 = (USHORT)(READ_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_RES));
*bufp++ = (val16 >> 8) & 0xff;
*bufp++ = val16 & 0xff;
}
bufp = (unsigned char *)respbuf;
if (bufp[1] & 0x80)
break;
}
Log ("SD card is reay for operation.\n");
return MSC_PASSED;
}
int initSDcard (void)
{
unsigned int respbuf[0x30];
unsigned char *bufp;
volatile unsigned int i;
unsigned short val16;
// send CMD2 (ALL_SEND_CID) with R2 (02: ident) ******************
Log ("Begin send CMD2 (ALL_SEND_CID) to card.\n");
if (send_command_to_cards (2, 0,MMC_CMDAT_RESPONSE_R2, 0, 1, 1) != MSC_PASSED)
return MSC_FAILED;
// get respond with R2
bufp = (unsigned char *)respbuf;
for (i = 0; i < 9; i++)
{
val16 = (USHORT)(READ_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_RES));
*bufp++ = (val16 >> 8) & 0xff;
*bufp++ = val16 & 0xff;
}
// send CMD3 (SEND_RELATIVE_ADDR) with R6 (03: stdby) ******************
Log ("Begin send CMD3 (SEND_RELATIVE_ADDR) to card.\n");
if (send_command_to_cards (3, 0, MMC_CMDAT_RESPONSE_R1/*CMDAT_RESP_R6*/, 0, 1, 1) != MSC_PASSED)
return MSC_FAILED;
// get respond with R6
bufp = (unsigned char *)respbuf;
for (i = 0; i < 3; i++)
{
val16 = (USHORT)(READ_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_RES));
*bufp++ = (val16 >> 8) & 0xff;
*bufp++ = val16 & 0xff;
}
bufp = (unsigned char *)respbuf;
CardAddr = (bufp[1] << 8) | bufp[2];
// send CMD13 (SEND_STATUS) with R1 (03: stdby) ******************
Log ("Begin send CMD13 (SEND_STATUS) to card.\n");
if (send_command_to_cards (13, CardAddr << 16, MMC_CMDAT_RESPONSE_R1, 0, 1, 1)
!= MSC_PASSED)
return MSC_FAILED;
if (getrespondR1 (0) != MSC_PASSED)
return MSC_FAILED;
// send CMD7 (Select/deselect_card) with R1 (04: trans) ******************
Log ("Begin send CMD7 (Select/deselect_card) to card.\n");
if (send_command_to_cards (7, CardAddr << 16,
(MMC_CMDAT_EXPECT_BUSY | MMC_CMDAT_RESPONSE_R1), 0, 1, 0)
!= MSC_PASSED)
return MSC_FAILED;
// get respond with R6
bufp = (unsigned char *)respbuf;
for (i = 0; i < 3; i++)
{
val16 = (USHORT)(READ_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_RES));
*bufp++ = (val16 >> 8) & 0xff;
*bufp++ = val16 & 0xff;
}
/* Set busWidth as 4. */
Log ("Begin send ACMD6 (SET_BUS_WIDTH) to card.\n");
if (send_command_to_cards (55, CardAddr << 16, MMC_CMDAT_RESPONSE_R1, 0, 1, 0) != MSC_PASSED)
return MSC_FAILED;
if (getrespondR1 (0) != MSC_PASSED)
return MSC_FAILED;
if (send_command_to_cards (6, 0x2, MMC_CMDAT_RESPONSE_R1, 0, 1, 1) != MSC_PASSED)
return MSC_FAILED;
if (getrespondR1 (0) != MSC_PASSED)
return MSC_FAILED;
datwidth = 4;
// send CMD13 (SEND_STATUS) with R1 (04: trans) ******************
Log ("Begin send CMD13 (SEND_STATUS) to card.\n");
if (send_command_to_cards (13, CardAddr << 16, MMC_CMDAT_RESPONSE_R1, 0, 1, 0)
!= MSC_PASSED)
return MSC_FAILED;
if (getrespondR1 (0) != MSC_PASSED)
return MSC_FAILED;
return MSC_PASSED;
}
void dump_copying_process ()
{
int len;
if (imagefile.BlockCnt < MAX_READ_BLOCK)
return;
imagefile.OutCnt++;
imagefile.BlockCnt -= MAX_READ_BLOCK;
len = (imagefile.OutCnt * MAX_READ_BLOCK * bootPartInfo.BytesPerSec);
Log ("--- Reading file: 0x%x (%d) completed !! \n", len, len);
}
int ReadBlocks (unsigned int *DataBuf, unsigned int BlockAddr, unsigned int blocks)
{
unsigned int i, j, blk, base, total_blocks = blocks;
volatile DWORD mmc_ireg, mmc_stat;
volatile UCHAR *pMMC_RX_Fifo = (volatile UCHAR *)&(pSDMMCRegisters->rxfifo);
UINT8 *pBufPtr;
pBufPtr = (UINT8 *)DataBuf;
if (blocks == 1) //Single block Read
{
if (send_command_to_cards (17, (BlockAddr * 0x200),
(MMC_CMDAT_DATA_EN | MMC_CMDAT_RESPONSE_R1), blocks, 1, 0)
!= MSC_PASSED)
return MSC_FAILED;
if (getrespondR1 (0) != MSC_PASSED)
return MSC_FAILED;
i = 0;
while (i < 0x200)
{
do {
mmc_ireg = READ_MMC_REGISTER_DWORD(pSDMMCRegisters, MMC_IREG);
} while(! (mmc_ireg & MMC_IREG_RXFIFO_REQ));
if (mmc_ireg & MMC_IREG_RXFIFO_REQ)
{
for (j = 0; j < 32; j++)
pBufPtr[i++] = *pMMC_RX_Fifo;
}
}
pBufPtr += i;
//dump_sector (DataBuf);
do {
mmc_stat = READ_MMC_REGISTER_DWORD( pSDMMCRegisters, MMC_STAT);
} while (!(mmc_stat & MMC_STAT_DATA_TRANSFER_DONE)) ;
// Dump the message about reading process.
if (read_file)
{
imagefile.BlockCnt++;
dump_copying_process ();
}
}
else //Multiple block Read
{
#ifdef USE_DMA_CHANNEL
unsigned int addr;
addr = (unsigned int)&(msc_reg->rxfifo_w32);
dmac_reg->channel[USE_DMA_CHANNEL].dma_sar = addr & 0x1FFFFFFF;
dmac_reg->channel[USE_DMA_CHANNEL].dma_rsr = DMA_DRSR_MSC_IN;
#endif
base = 0;
while (blocks > 0)
{
blk = (blocks > MAX_READ_BLOCK) ? MAX_READ_BLOCK : blocks;
#ifdef USE_DMA_CHANNEL
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -