📄 sdi2410.c
字号:
//---------------------------------------------------------------------------------
// Copyright jinhailiao 2008-2010
// E-mail: jinhailiao@163.com
// Project: HFAT16/32
// File: sdi2410.c
// Description:
//-------------------------------------------------------------
// Reversion Histroy:
//-------------------------------------------------------------
// Version date operations by who
// 1.0.0 2008-09-09 create Kingsea
//---------------------------------------------------------------------------------
#include "hfstype.h"
#include "ftdevice.h"
#include "haiclib.h"
#ifdef ADD_S3C2410_SDI
#include "cfg2410.h"
#include "reg2410.h"
//note: only support SD_CARD partition 1 now.
//macro define
//
#define SDT_NO_CARD 0
#define SDT_MMC_CARD 1
#define SDT_SD_CARD 2
#define SDT_SDHC_CARD 3
#define SD_BUSW_1BIT 0x00
#define SD_BUSW_4BIT 0x01
#define SD_BUSW_MASK 0x01
#define SD_WTPROT_NON 0x00
#define SD_WTPROT_YES 0x02
#define SD_WTPROT_MSK 0x02
#define pSD_MBR(p) (p+0)
#define pSD_MBR_PT1(p) (p+446)
#define pSD_MBR_PT2(p) (p+462)
#define pSD_MBR_PT3(p) (p+478)
#define pSD_MBR_PT4(p) (p+494)
#define pSD_MBR_SW(p) (p+510)
#define sSD_MBR 446
#define sSD_MBR_PT 16
#define sSD_MBR_SW 2
#define pSD_PT_BOOTINDIC(p) (p+0)
#define pSD_PT_STARTHEAD(p) (p+1)
#define pSD_PT_STARTSECCYL(p) (p+2)
#define pSD_PT_SYSTEMID(p) (p+4)
#define pSD_PT_ENDHEAD(p) (p+5)
#define pSD_PT_ENDSECCYL(p) (p+6)
#define pSD_PT_RELATIVESEC(p) (p+8)
#define pSD_PT_TOTALSECTOR(p) (p+12)
#define sSD_PT_BOOTINDIC 1
#define sSD_PT_STARTHEAD 1
#define sSD_PT_STARTSECCYL 2
#define sSD_PT_SYSTEMID 1
#define sSD_PT_ENDHEAD 1
#define sSD_PT_ENDSECCYL 2
#define sSD_PT_RELATIVESEC 4
#define sSD_PT_TOTALSECTOR 4
#define SDI_INITIALCLK 400000
#define SDI_NORMALCLK 5000000
//command format
//
// 10 9 8 7 6 5...0
//LRSP WTRSP CMDStart startbit:0 host:1 CMDIDX
#define SDICMD_HOST 0x00000040UL//(1<<6)
#define SDICMD_START 0x00000100UL//(1<<8)
#define SDICMD_WTRSP 0x00000200UL//(1<<9)
#define SDICMD_L_RSP 0x00000400UL//(1<<10)
#define SDICMD_NORSP 0x00000000UL//(0<<9)
#define SDICMD_S_RSP 0x00000000UL//(0<<10)
#define SDICMD_IDXMSK 0x0000003FUL
//command class
//
#define SDICMD_GO_IDLE_STATE 0
#define SDICMD_OP_COND 1
#define SDICMD_ALL_SEND_CID 2
#define SDICMD_SEND_REL_ADDR 3
#define SDICMD_SEL_DSEL_CARD 7
#define SDICMD_SEND_CSD 9
#define SDICMD_SEND_CID 10
#define SDICMD_STOP_TRANS 12
#define SDICMD_SEND_STATUS 13
#define SDICMD_SET_BLOCKLEN 16
#define SDICMD_READ_SINGLBLK 17
#define SDICMD_READ_MULTIBLK 18
#define SDICMD_WRITE_SINGLBLK 24
#define SDICMD_WRITE_MULTIBLK 25
#define SDICMD_SEND_WRIT_PROT 30
#define SDICMD_APP_CMD 55
#define SDICMD_SET_BUS_WIDTH 6
#define SDICMD_SD_STATUS 13
#define SDICMD_SD_APP_OP_COND 41
#define SDCARD_BLOCK_LENG_MAX 1024
#define SDCARD_BUFFER_BLOCK_MAX 10
#define SDCARD_FAT_SECTOR_BYTES 512
#define SDCARD_BUFFER_NEEDFLUSH 0x01000000
//assert struct
//
typedef struct tagPartTab
{
S_BYTE BootIndicator;//active partition:0x80;otherwise:0x00
S_BYTE StartHead;
S_WORD StartSecCyl;
S_BYTE SystemID;//0x01 or 0x04 or 0x06
S_BYTE EndHead;
S_WORD EndSecCyl;
S_DWORD RelativeSec;
S_DWORD TotalSector;
}
S_PARTTAB, *SP_PARTTAB;
typedef struct tagCID
{
S_BYTE MID;//binary:0x03
S_BYTE OID[2];//ASCII:"SD"
S_BYTE PNM[5];//ASCII:"SD128"
S_BYTE PRV;//BCD:30
S_BYTE PSN[4];//binary
S_BYTE MDT[2];//BCD:yym(offset from 2000)
S_BYTE CRC;//binary
}
S_CID, *SP_CID;
typedef struct tagCSD
{
S_BYTE CSDStruct;
// S_BYTE ReadAccessTime1;
// S_BYTE ReadAccessTime2;
// S_BYTE DataTransRate;
// S_WORD CardCmdClasses;
S_BYTE ReadBlockLen;
// S_BYTE ReadBlockPartial;
S_WORD DeviceSize;
S_BYTE DeviceSizeMulti;
}
S_CSD, *SP_CSD;
typedef struct tagSDCARD
{
S_BYTE CardType;
S_BYTE flag;
S_WORD BlockLen;
S_WORD RCA;
S_CID CID;
S_CSD CSD;
S_PARTTAB part[4];//only support part[0] now.
}
S_SDCARD, *SP_SDCARD;
static S_SDCARD sdcard;
//function prototype
//
int s3c2410sdiInit(void);
int s3c2410sdiStatus(void);
int s3c2410sdiRead(S_DWORD sector, S_BYTE *OutBuf);
int s3c2410sdiWrite(S_DWORD sector, S_BYTE *InBuf);
int s3c2410sdiCmd(S_DWORD cmd, S_DWORD arg, S_DWORD *OutVal);
int s3c2410sdiFlush(S_DWORD sector, S_BOOL FreeBuffer);
static int sdi_SendCmd(int rCMD, int rARG);
static int sdi_CMD55(S_WORD RCA);
static int sdi_ChkMMCOCR(void);
static int sdi_ChkSDOCR(void);
static int sdi_GetCID(S_WORD RCA, SP_CID pCID);
static int sdi_GetCSD(S_WORD RCA, SP_CSD pCSD);
static int sdi_MakeIdent(void);
static int sdi_MakeStandby(S_WORD *pRCA);
static int sdi_CardSelect(S_WORD RCA);
static int sdi_SetBusWidth(S_WORD RCA, int BUSW);
static int sdi_CheckDATend(void);
static int sdi_SDcardInit(void);
static int sdi_ReadBlock(S_DWORD block, S_BYTE *OutBuf);
static int sdi_WriteBlock(S_DWORD block, S_BYTE *InBuf);
static void sdi_IncUseCount(int BufNo);
static int sdi_FindLeastUseCluster(void);
//assert driver struct
//
const S_FATDEVDRV s3c2410sdiDrv =
{
"S3C2410_SDI",
s3c2410sdiInit,
s3c2410sdiStatus,
s3c2410sdiRead,
s3c2410sdiWrite,
s3c2410sdiCmd,
s3c2410sdiFlush,
};
//Driver Buffer
//
static S_BYTE SDCARDBuf[SDCARD_BUFFER_BLOCK_MAX][SDCARD_BLOCK_LENG_MAX];
static S_DWORD SDCARDFlag[SDCARD_BUFFER_BLOCK_MAX];
static S_DWORD SDCARDClst[SDCARD_BUFFER_BLOCK_MAX];
//driver function define
//
int s3c2410sdiInit(void)
{
int err, try = 3;
S_BYTE *pPart, *pMBR = SDCARDBuf[0];
do
{
err = sdi_SDcardInit();
}while (err && try--);
if (err) return err;
//read partition
try = 3;
do
{
err = sdi_ReadBlock(0, pMBR);
}while (err && try--);
if (err) return err;
pPart = pSD_MBR_PT1(pMBR);
sdcard.part[0].BootIndicator = *pSD_PT_BOOTINDIC(pPart);
sdcard.part[0].StartHead = *pSD_PT_STARTHEAD(pPart);
sdcard.part[0].StartSecCyl = HAI_MAKEWORD(pSD_PT_STARTSECCYL(pPart));
sdcard.part[0].SystemID = *pSD_PT_SYSTEMID(pPart);
sdcard.part[0].EndHead = *pSD_PT_ENDHEAD(pPart);
sdcard.part[0].EndSecCyl = HAI_MAKEWORD(pSD_PT_ENDSECCYL(pPart));
sdcard.part[0].RelativeSec = HAI_MAKEDWORD(pSD_PT_RELATIVESEC(pPart));
sdcard.part[0].TotalSector = HAI_MAKEDWORD(pSD_PT_TOTALSECTOR(pPart));
for (try = 0; try < SDCARD_BUFFER_BLOCK_MAX; try++)
SDCARDFlag[try] = 0;
for (try = 0; try < SDCARD_BUFFER_BLOCK_MAX; try++)
SDCARDClst[try] = 0xFFFFFFFF;
return err;
}
int s3c2410sdiStatus(void)
{
return 0;//always OK.
}
int s3c2410sdiRead(S_DWORD sector, S_BYTE *OutBuf)
{
int err, try;
int i, m = SDCARD_BUFFER_BLOCK_MAX-1;
S_DWORD cluster, current;
sector += sdcard.part[0].RelativeSec;
cluster = sector/(sdcard.BlockLen/SDCARD_FAT_SECTOR_BYTES);
current = sector%(sdcard.BlockLen/SDCARD_FAT_SECTOR_BYTES);
//find if in driver buffer
for (i = 0; i < SDCARD_BUFFER_BLOCK_MAX; i++)
{
if (SDCARDClst[i] == 0xFFFFFFFF)
m = i;
else if (SDCARDClst[i] == cluster)
break;
}
if (i == SDCARD_BUFFER_BLOCK_MAX)// not found out
{
if (SDCARDClst[m] != 0xFFFFFFFF) // have not idle cluster, make one idle cluster
{
m = sdi_FindLeastUseCluster();
if ((SDCARDFlag[m]&SDCARD_BUFFER_NEEDFLUSH) == SDCARD_BUFFER_NEEDFLUSH)
{
try = 3;
do
{
err = sdi_WriteBlock(SDCARDClst[m], SDCARDBuf[m]);
}while (err && try--);
if (err)
return err;
}
}
SDCARDFlag[m] = 0;
SDCARDClst[m] = cluster;//ok, have one idle cluster
try = 3;
do
{
err = sdi_ReadBlock(SDCARDClst[m], SDCARDBuf[m]);
}while (err && try--);
if (err)
{
SDCARDClst[m] = 0xFFFFFFFF;//Oh, shit! fail on read disk
return err;
}
i = m;//make it as found successful....
}
if (SDCARDClst[i] == cluster)//OK, found out
{
#if 0
S_BYTE *pDat = &SDCARDBuf[i][current*SDCARD_FAT_SECTOR_BYTES];
hai_memcpy(OutBuf, pDat, SDCARD_FAT_SECTOR_BYTES);
#else
int *pDat = (int *)&SDCARDBuf[i][current*SDCARD_FAT_SECTOR_BYTES];
int *pOut = (int *)OutBuf;
for (try = 0; try < SDCARD_FAT_SECTOR_BYTES/4; try++)
*pOut++ = *pDat++;
#endif
sdi_IncUseCount(i);
}
return 0;
}
int s3c2410sdiWrite(S_DWORD sector, S_BYTE *InBuf)
{
int err, try;
int i, m = SDCARD_BUFFER_BLOCK_MAX-1;
S_DWORD cluster, current;
sector += sdcard.part[0].RelativeSec;
cluster = sector/(sdcard.BlockLen/SDCARD_FAT_SECTOR_BYTES);
current = sector%(sdcard.BlockLen/SDCARD_FAT_SECTOR_BYTES);
//find if in driver buffer
for (i = 0; i < SDCARD_BUFFER_BLOCK_MAX; i++)
{
if (SDCARDClst[i] == 0xFFFFFFFF)
m = i;
else if (SDCARDClst[i] == cluster)
break;
}
if (i == SDCARD_BUFFER_BLOCK_MAX)// not found out
{
if (SDCARDClst[m] != 0xFFFFFFFF) // have not idle cluster, make one idle cluster
{
m = sdi_FindLeastUseCluster();
if ((SDCARDFlag[m]&SDCARD_BUFFER_NEEDFLUSH) == SDCARD_BUFFER_NEEDFLUSH)
{
try = 3;
do
{
err = sdi_WriteBlock(SDCARDClst[m], SDCARDBuf[m]);
}while (err && try--);
if (err)
return err;
}
}
SDCARDFlag[m] = 0;
SDCARDClst[m] = cluster;//ok, have one idle cluster
try = 3;
do
{
err = sdi_ReadBlock(SDCARDClst[m], SDCARDBuf[m]);
}while (err && try--);
if (err)
{
SDCARDClst[m] = 0xFFFFFFFF;//Oh, shit! fail on read disk
return err;
}
i = m;//make it as found successful....
}
if (SDCARDClst[i] == cluster)//OK, found out
{
#if 0
S_BYTE *pDat = &SDCARDBuf[i][current*SDCARD_FAT_SECTOR_BYTES];
hai_memcpy(pDat, InBuf, SDCARD_FAT_SECTOR_BYTES);
#else
int *pDat = (int *)&SDCARDBuf[i][current*SDCARD_FAT_SECTOR_BYTES];
int *pIn = (int *)InBuf;
for (try = 0; try < SDCARD_FAT_SECTOR_BYTES/4; try++)
*pDat++ = *pIn++;
#endif
SDCARDFlag[i] |= SDCARD_BUFFER_NEEDFLUSH;
sdi_IncUseCount(i);
}
return 0;
}
int s3c2410sdiCmd(S_DWORD cmd, S_DWORD arg, S_DWORD *OutVal)
{
int err = 0;
switch (cmd)
{
case DEVCMD_WRITE_PROTECT:
*OutVal = (sdcard.flag&SD_WTPROT_MSK)?1:0;
break;
case DEVCMD_SECTOR_SIZE:
*OutVal = SDCARD_FAT_SECTOR_BYTES;//this is a recommand val, otherwise:1024, 2048, 4096.
break;
case DEVCMD_TOTAL_SECTOR:
*OutVal = sdcard.part[0].TotalSector;
break;
case DEVCMD_SEC_PER_CLUS:
*OutVal = 0; //or 1, 2, 4, 8, 16, 32, 64, 128;
break;
default:
*OutVal = 0;
break;
}
return err;
}
int s3c2410sdiFlush(S_DWORD sector, S_BOOL FreeBuffer)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -