📄 sdd_mem.c
字号:
/* Copyright 2002, ESS Technology, Inc. */
/* SCCSID @(#)sd_mem.c 1.40 08/10/04 */
#ifdef SD_MEMORY
#include "common.h"
#include "ioport.h"
#include "mvd.h"
#include "buffer.h"
#include "custmem.h"
#include "memmap.h"
#include "smfont.h"
#include "util.h"
#include "constvar.h"
#include "sd_mem.h"
#include "sysinfo.h"
#include "mem_dev.h"
#include "debug.h"
/*------------------------------------------------------------------------
* Debugging macros
*------------------------------------------------------------------------*/
#define CPRINTF(a)
#define PRINTF(a)
#define JPRINTF(a)
#define SD_ENABLE_WRITE
#if 0
int bpt;
#define BREAKPOINT(x) {bpt=x;while(bpt) VCX_service();}
#else
#define BREAKPOINT(x)
#endif
/*------------------------------------------------------------------------
* macros
*------------------------------------------------------------------------*/
#define USEC(x) (cpuclk*x/10)
#define get_bigend32(pcbuf, off) ((uchar)pcbuf[off]|((uchar)pcbuf[off+1] << 8)| \
( (uchar)pcbuf[off+2] << 16)|((uchar)pcbuf[off+3] <<24))
/*------------------------------------------------------------------------
* Public variables
*------------------------------------------------------------------------*/
SD_CINFO SD_card_info;
SD_XMIT_STATUS SD_xmit_info;
/*------------------------------------------------------------------------
* Private variables
*------------------------------------------------------------------------*/
static SD_CARD_STATUS *SD_card_status_ptr; /* R1 reply */
static SD_STATUS *SD_status_ptr;
static SD_OCR *SD_ocr_reg_ptr;
static SD_CID *SD_cid_reg_ptr;
static SD_CSD *SD_csd_reg_ptr;
static ushort SD_rca_reg; /* rel card address..ID for multi cards */
static SD_SCR *SD_scr_reg_ptr;
static uint SD_rdata32;
static int sd_is_mmc;
static int sd_io_status = 0;
static SD_CMD_Q SD_acmdq; /* SD command queue or appcmd */
static unsigned short sd_crc16_look_up_table[256];
static uchar sd_crc7_look_up_table[256];
static int sdTotalBlockNo, sdPagePerBlock, sdEraseSecSize;
/* NOTE: move LUT's to rom later */
/* LUT for commands with responses: R1, R1b, R2, R3, R6 */
uchar SD_cmd2resp[64] = {
/* CMD0 - CMD7 */
SD_NR, SD_R3, SD_R2, SD_R6, SD_NR, SD_NR, SD_NR, SD_R1b,
/* CMD8 - CMD15 */
SD_NR, SD_R2, SD_R2, SD_R1_RD, SD_R1b,SD_R1, SD_NR, SD_NR,
/* CMD16 - CMD23 */
SD_R1, SD_R1_RD, SD_R1_RD, SD_NR, SD_NR, SD_NR, SD_NR, SD_R1,
/* CMD24 - CMD31 */
SD_R1_WR, SD_R1_WR, SD_NR, SD_R1, SD_R1b,SD_R1b,SD_R1, SD_NR,
/* CMD32 - CMD39 */
SD_R1, SD_R1, SD_NR, SD_NR, SD_NR, SD_NR, SD_R1b,SD_NR,
/* CMD40 - CMD47 */
SD_NR, SD_NR, SD_R1, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR,
/* CMD48 - CMD55 */
SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_R1,
/* CMD56 - CMD63 */
SD_R1, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR
};
/* LUT for app. commands with responses: R1, R1b, R2, R3, R6 */
uchar SD_acmd2resp[52] = {
/* ACMD0 - ACMD7 */
SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_R1, SD_NR,
/* ACMD8 - ACMD15 */
SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_R1_RD, SD_NR, SD_NR,
/* ACMD16 - ACMD23 */
SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_R1, SD_R1,
/* ACMD24 - ACMD31 */
SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR,
/* ACMD32 - ACMD8 */
SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR,
/* ACMD40 - ACMD47 */
SD_NR, SD_R3, SD_R1, SD_NR, SD_NR, SD_NR, SD_NR, SD_NR,
/* ACMD48 - ACMD51 */
SD_NR, SD_NR, SD_NR, SD_R1_RD
};
/* LUT for SD command classes */
uchar SD_cmd2class[64] = {
/* CMD0 - CMD7 */
SD_CL0,SD_CL0,SD_CL0,SD_CL0,SD_CL0,SD_CL0,SD_CL0,SD_CL0,
/* CMD8 - CMD15 */
SD_CL0,SD_CL0,SD_CL0,SD_CL1,SD_CL0,SD_CL0,SD_CL0,SD_CL0,
/* CMD16 - CMD23 */
SD_CL2,SD_CL2,SD_CL2,SD_CL2,SD_CL2,SD_CL2,SD_CL2,SD_CL2,
/* CMD24 - CMD31 */
SD_CL4,SD_CL4,SD_CL4,SD_CL4,SD_CL6,SD_CL6,SD_CL6,SD_CL6,
/* CMD32 - CMD39 */
SD_CL5,SD_CL5,SD_CL5,SD_CL5,SD_CL5,SD_CL5,SD_CL5,SD_CL5,
/* CMD40 - CMD47 */
SD_CL5,SD_CL5,SD_CL7,SD_CL7,SD_CL7,SD_CL7,SD_CL7,SD_CL7,
/* CMD48 - CMD55 */
SD_CL7,SD_CL7,SD_CL7,SD_CL7,SD_CL7,SD_CL7,SD_CL7,SD_CL8,
/* CMD56 - CMD63 */
SD_CL8,SD_CL8,SD_CL8,SD_CL8,SD_CL8,SD_CL8,SD_CL8,SD_CL8,
};
/* LUT for CSD's TAAC time value */
uchar SD_taac_valx10[16] = {
00, 10, 12, 13, 15, 20, 25, 30,
35, 40, 45, 50, 55, 60, 70, 80
};
#ifdef BANK2SPEEDUP
static unsigned old_wait_state;
#endif
/*------------------------------------------------------------------------
* Private functions
*------------------------------------------------------------------------*/
static int SD_set_cmd(int, uint);
static void SD_update_card_info(void);
static ushort SD_calc_crc16(uchar *, ushort);
static void SD_calc_crc16_table(ushort *);
static uchar SD_calc_crc7(uchar *, ushort);
static void SD_calc_crc7_table(uchar *);
static int SD_write_blk(int, int, int, int *, int);
/*------------------------------------------------------------------------
* Begin SD function listing
*------------------------------------------------------------------------*/
/*
Function: Get partition boot record (PBR) address from master
boot record area.
input:
output: PBR start address as physical lba (physical sector number).
side-effects:
*/
unsigned int SD_boot_setup(void)
{
uchar *buff;
uint PBR_start_psn;
SD_enable_io(1); /* enable SD eaux pins */
buff = (uchar *)dram_cached(SD_DATA_START);
SD_read_sector_lba((short *)buff, 0, 1, 1); /* 512B per block */
if (((buff[0x0] == 0xEB) && (buff[0x2] == 0x90))
|| (buff[0x0] == 0xE9)) {
PBR_start_psn = 0;
}else
PBR_start_psn = get_bigend32(buff, 454);
return(PBR_start_psn);
}
/*********************************************************************
return:
1: MMC
0: SD or else
**********************************************************************/
int SD_is_mmc(void){
if(SD_card_info.type == SD_MMC)
return 1;
else
return 0;
}
/*
Function: Reads from specified lba to designated buffer.
input:
buff: pointer for SD data destination.
lba: physical logical block address.
nblk: number of blocks to read.
output: number of bytes read.
side-effects:
*/
int SD_read_sector_lba(short *buff, int lba, int nblk, int immed)
{
int i, start_lba = lba;
short *pDest = buff;
set_bank2_wait ();
if (nblk == 1) {
SD_read_blk(lba<<9, 9, (unsigned int *)buff, immed);
} else {
PRINTF(("SD_multi_block read: %d-->%x : nblk %d \n",
lba, buff, nblk));
if(SD_card_info.type == SD_MMC){
for(i= 0; i<nblk; i++){
SD_read_blk(start_lba<<9, 9, (unsigned int *)pDest, immed);
pDest += 0x100;
start_lba++;
}
}else
SD_read_nblk(lba<<9, nblk, (unsigned int *)buff, immed);
}
restore_bank2_wait ();
return (nblk*512);
}
static int SD_find_free_block(int start_blk)
{
int blk_no = start_blk, i, lba, cluster, pcluster;
while(blk_no++<sdTotalBlockNo){
pcluster = 0;
for(i=0; i<sdPagePerBlock; i++){
lba = blk_no*sdPagePerBlock +i;
cluster = HD_lba_to_cluster(lba);
if(cluster == -1) continue;
if(cluster == pcluster)
continue;
pcluster = cluster;
if(!HD_cluster_is_free(cluster))
break;
}
if(i<sdPagePerBlock)
continue;
else{
JPRINTF(("found a free block: %d\n", blk_no));
return blk_no;
}
}
return -1;
}
static int SD_erase_block(int start_lba, int nblk)
{
int status, end_lba;
end_lba = start_lba+nblk-1;
status = SD_send_cmd(SD_CMD_ERASE_WR_BLK_START, start_lba<<9,1);
if(status != 1)
return -1;
status = SD_send_cmd(SD_CMD_ERASE_WR_BLK_END, end_lba<<9,1);
if(status != 1)
return -1;
status = SD_send_cmd(SD_CMD_ERASE, 0, 1);
if(status != 1)
return -1;
else if(SD_xmit_info.result == 0)
return 0;
else{
JPRINTF(("card status %x\n", *(int*)SD_card_status_ptr));
return -1;
}
}
int SD_write_sector_lba(short *buff, int lba, int nblk, int immed)
{
int start_lba= lba,i, status;
short *pSrc= buff;
int free_blk;
#ifndef SD_ENABLE_WRITE
return -1;
#endif
if(SD_card_info.type == SD_MMC){
for(i=0; i<nblk; i++){
status = SD_write_blk(start_lba<<9, 9, 1, (int *)pSrc, 1);
if(status){
JPRINTF(("MMC writing error ...\n"));
assert(0);
return 0;
}
pSrc += 0x100;
start_lba++;
}
}else{
status = SD_write_blk(start_lba<<9, 9, nblk, (int *)pSrc, immed);
if(status)
return 0;
if(nblk>1 && immed)
status = SD_send_cmd(SD_CMD_STOP_TRANSMIT, 0, 1);
}
JPRINTF(("SD_write_sector_lba: data_cnt%d nblk %d, status %x\n",
SD_xmit_info.data_cnt, nblk, status));
return (512*nblk);
}
/*
Function: The faster CRC16 calculation procedure
uses 256 x 16-bit Look Up Table (8bit at a time)..
more efficient than generating CRC 1bit at a time.
(adapted from memstick.c version)
input:
data: pointer to data to be protected by CRC.
count: total bytes of data.
output: CRC16
side-effects:
*/
static ushort SD_calc_crc16(uchar *data, ushort count)
{
ushort fcs = 0x0; /* initial FCS value */
ushort i, t, tl, th;
for (i=0; i<count; i++)
{
t = fcs;
fcs = sd_crc16_look_up_table[(t>>8) ^ *data++];
fcs = fcs ^ (t<<8);
}
return(fcs);
}
/* in case of 4-bit mode */
static ushort SD_calc_crc16_4_bit(int *data, ushort count, ushort *crc)
{
ushort fcs0 = 0x0, fcs1=0, fcs2=0, fcs3=0; /* initial FCS value */
ushort i, j ;
int tmp, *pInt;
uint filter;
ushort d0,d1,d2,d3;
ushort tt0,tt1,tt2,tt3;
pInt = data;
for (i=0; i<count; i++)
{
PRINTF(("data is %x\n", *pInt));
tmp = *pInt++;
d3 = ((tmp & 0x80000000) >> 24); /* 0 */
d3 |= ((tmp & 0x08000000) >> 21); /* 1 */
d3 |= ((tmp & 0x00800000) >> 18); /* 2 */
d3 |= ((tmp & 0x00080000) >> 15); /* 3 */
d3 |= ((tmp & 0x00008000) >> 12); /* 4 */
d3 |= ((tmp & 0x00000800) >> 9); /* 5 */
d3 |= ((tmp & 0x00000080) >> 6); /* 6 */
d3 |= ((tmp & 0x00000008) >> 3); /* 7 */
d2 = ((tmp & 0x40000000) >> 23); /* 0 */
d2 |= ((tmp & 0x04000000) >> 20); /* 1 */
d2 |= ((tmp & 0x00400000) >> 17); /* 2 */
d2 |= ((tmp & 0x00040000) >> 14); /* 3 */
d2 |= ((tmp & 0x00004000) >> 11); /* 4 */
d2 |= ((tmp & 0x00000400) >> 8); /* 5 */
d2 |= ((tmp & 0x00000040) >> 5); /* 6 */
d2 |= ((tmp & 0x00000004) >> 2); /* 7 */
d1 = ((tmp & 0x20000000) >> 22); /* 0 */
d1 |= ((tmp & 0x02000000) >> 19); /* 1 */
d1 |= ((tmp & 0x00200000) >> 16); /* 2 */
d1 |= ((tmp & 0x00020000) >> 13); /* 3 */
d1 |= ((tmp & 0x00002000) >> 10); /* 4 */
d1 |= ((tmp & 0x00000200) >> 7); /* 5 */
d1 |= ((tmp & 0x00000020) >> 4); /* 6 */
d1 |= ((tmp & 0x00000002) >> 1); /* 7 */
d0 = ((tmp & 0x10000000) >> 21); /* 0 */
d0 |= ((tmp & 0x01000000) >> 18); /* 1 */
d0 |= ((tmp & 0x00100000) >> 15); /* 2 */
d0 |= ((tmp & 0x00010000) >> 12); /* 3 */
d0 |= ((tmp & 0x00001000) >> 9); /* 4 */
d0 |= ((tmp & 0x00000100) >> 6); /* 5 */
d0 |= ((tmp & 0x00000010) >> 3); /* 6 */
d0 |= ((tmp & 0x00000001) ); /* 7 */
// PRINTF(("wanted : %x tmp %x, filter %x\n",
// data_wanted, tmp, filter));
tt0 = fcs0;
tt1 = fcs1;
tt2 = fcs2;
tt3 = fcs3;
fcs0 = sd_crc16_look_up_table[(tt0>>8) ^ d0];
fcs1 = sd_crc16_look_up_table[(tt1>>8) ^ d1];
fcs2 = sd_crc16_look_up_table[(tt2>>8) ^ d2];
fcs3 = sd_crc16_look_up_table[(tt3>>8) ^ d3];
fcs0 = fcs0 ^ (tt0<<8);
fcs1 = fcs1 ^ (tt1<<8);
fcs2 = fcs2 ^ (tt2<<8);
fcs3 = fcs3 ^ (tt3<<8);
}
crc[0] = fcs0;
crc[1] = fcs1;
crc[2] = fcs2;
crc[3] = fcs3;
return(0);
}
static uchar SD_calc_crc7(uchar *data, ushort count)
{
uchar fcs = 0x0; /* initial FCS value */
ushort i;
uchar g = 0x9;
uchar t;
for (i=0; i<count; i++)
{
t = sd_crc7_look_up_table[fcs];
t <<= 1;
if(t&0x80)
fcs = (t&0x7f)^g;
else
fcs = t;
t = sd_crc7_look_up_table[*data++];
fcs ^= t;
}
return(fcs);
}
/***********************************************************
Function: Generate look up table for CRC16 calculation.
G(x): x16+x12+x5+1
***********************************************************/
static void SD_calc_crc16_table(ushort *table)
{
int d, i, k;
ushort g = 0x1021; /* x16+ x12 +x5+1 */
for (i=0; i<256; i++)
{
d = i<<8;
for (k=0; k<8; k++)
{
d <<= 1;
if(d&0x10000)
d ^= g;
}
table[i] = d&0xffff;
}
}
/***********************************************************
Function: Generate look up table for CRC7 calculation.
G(x): x7+x3+1
***********************************************************/
static void SD_calc_crc7_table(uchar *table)
{
int i, k, d;
uchar g = 0x9; /* x7+ x3 +1 */
PRINTF(("SD_fcs_table_calc_crc7 ...\n"));
for (i=0; i<256; i++){
d = i;
for (k=0; k<7; k++){
if(d&0x80)
d ^= g;
d <<= 1;
}
if(d&0x80)
d ^= g;
table[i] = d&0x7f;
}
}
/*
Function: Update SD_card_info from SD_csd_register..
calculate some card information.
(ref. pp.63-71..SD Physical Layer)
input: (none..but assumes CSD register is updated)
side-effects:
SD_card_info members are updated:
1. card's read access time (n_ac_max)
2. card's write access time (n_wr_max)
3. card's memory capacity.
*/
static void SD_update_card_info(void)
{
int cnt, mmc_ac, sd_ac;
uint data;
int nwrmax;
/* calculate access times */
/* data = taac = ((value*CPUCLK)/4) * 10^cnt */
data = cpuclk*SD_taac_valx10[SD_csd_reg_ptr->taac_value];
data >>= 2; /* WS = 4 */
cnt = SD_csd_reg_ptr->taac_unit - 5; /* n power of 10 */
if (cnt < 0) {
do {
data /= 10;
cnt++;
} while (cnt);
} else {
while (cnt) {
data *= 10;
cnt--;
};
}
/* read access time */
SD_card_info.n_ac_max = SD_NAC_MIN + data +
(100 * SD_csd_reg_ptr->nsac);
mmc_ac = 10*(data+100*SD_csd_reg_ptr->nsac);
if(sd_is_mmc)
SD_card_info.n_ac_max = mmc_ac;
JPRINTF(("n_ac_max: sd: %d, mmc %d \n",
SD_card_info.n_ac_max, mmc_ac));
/* write access time */
nwrmax = (SD_card_info.n_ac_max)<<(SD_csd_reg_ptr->r2w_factor);
/*prevent short var n_wr_max overflow*/
if (nwrmax > 0xffff) nwrmax = 0xffff;
SD_card_info.n_wr_max = nwrmax;
/* calculate card capacity = BLOCKNR * BLOCK_LEN */
data = ((SD_csd_reg_ptr->c_size_11_2<<2) |
SD_csd_reg_ptr->c_size_1_0) + 1;
cnt = 1 << (SD_csd_reg_ptr->c_size_mult + 2);
data = data * cnt; /* BLOCKNR */
sdTotalBlockNo = data;
cnt = 1 << (SD_csd_reg_ptr->rd_blk_len); /* BLOCK_LEN */
sdPagePerBlock = cnt/512;
sdEraseSecSize = SD_csd_reg_ptr->sector_size+1;
SD_card_info.capacity = data * cnt; /* in Bytes */
}
/*
Function: Initialize SD related buffers, structure members and
and IO pins.
input:
output:
side-effects:
*/
void SD_init(void)
{
unsigned sclk_high, sclk_low;
dawei(("SD_init()\n"));
SD_GET_SCLK_VAL(sclk_high, sclk_low);
/* initialization */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -