sd_mem.c
上传用户:hrbsz2007
上传日期:2008-05-11
资源大小:1222k
文件大小:57k
- /* 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: %dn", 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 %xn", *(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 %xn",
- 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 %xn", *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 %xn",
- // 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 */
- SD_card_status_ptr = (SD_CARD_STATUS *)dram_cached(SD_CSTATUS_START);
- SD_status_ptr = (SD_STATUS *)dram_cached(SD_STATUS_START);
- SD_ocr_reg_ptr = (SD_OCR *)dram_cached(SD_OCR_START);
- SD_cid_reg_ptr = (SD_CID *)dram_cached(SD_CID_START);
- SD_csd_reg_ptr = (SD_CSD *)dram_cached(SD_CSD_START);
- SD_scr_reg_ptr = (SD_SCR *)dram_cached(SD_SCR_START);
- /* generate the crc table */
- SD_calc_crc16_table(sd_crc16_look_up_table);
- SD_calc_crc7_table(sd_crc7_look_up_table);
- SD_rca_reg = 0; /* initially '0' */
- SD_card_info.type = SD_UNKNOWN;
- sd_is_mmc = 0;
- SD_card_info.capacity = 0; /* used to check if CSD received */
- SD_xmit_info.com_state = SD_IDLE;
- #if SD_CHECK_RECV_CRC
- SD_xmit_info.crc7_err_cnt = 0;
- SD_xmit_info.crc16_err_cnt = 0;
- #endif
- SD_acmdq.cmd = SD_CMD_EMPTY;
- SET_SD_CMD; /* initially high */
- SD_DETECT_INPUT;
- }
- /*
- Function: Enable/disable SD eaux ports shared with ATAPI. This is
- used to prevent ATAPI initialization problems.
- input:
- enable: 1 - enable SD IO ports.
- 0 - disable SD IO ports.
- output:
- side-effects:
- (refer to sd_mem.h for specific eaux ports affected)
- */
- void SD_enable_io(int enable)
- {
- #if defined(SD_MEMORY)
- /* shared with ATAPI..
- * there is known conflict with ATAPI-D7 (Busy pin) that cause
- * ATAPI initialization problem..tread lightly here.
- */
- if (enable){
- sd_io_status = 1;
- ENABLE_SD_GENERAL;
- ENABLE_SD_IO;
- } else if(sd_io_status){
- DISABLE_SD_GENERAL;
- DISABLE_SD_IO;
- sd_io_status = 0;
- }
- #endif
- }
- /*
- Function: SD-memory/MMC card detection. Gets relative card
- address(RCA) from card if detected.
- input: (none)
- output:
- -2: failed to get CSD register
- -1: not voltage compatible
- 0: no valid SD-mem or MMC card found
- 5: if successful
- */
- int SD_identify_device(void)
- {
- int status, status1, cnt=0;
- SD_enable_io(1);
-
- SD_init();
- SD_card_info.inserted = 1;
- /* Force SD card to idle-state to start initialization */
- SD_clk_restricted_cmd(SD_CMD_GO_IDLE_STATE, 0);
- /* send ACMD41 w/acceptable OCR..
- * and wait until SD card is ready.
- */
- SD_ocr_reg_ptr->card_ready = 0;
- do {
- status = SD_clk_restricted_cmd(SD_CMD_APP_CMD, 0);
- status1 = SD_clk_restricted_cmd(SD_ACMD_SD_SEND_OP_COND,
- SD_ACCEPTABLE_OCR);
- if ((status == -1) && (status1 == -1)) {
- SD_clk_restricted_cmd(SD_CMD_GO_IDLE_STATE, 0);
- cnt++;
- if (cnt > SD_MAX_RETRIES) {
- /* timed out..no response */
- status = -3;
- break;
- }
- }
- } while (!SD_ocr_reg_ptr->card_ready);
- sd_is_mmc = 0;
- /*
- * if no response: 1) SD card not voltage compatible
- * 2) could be Multimedia card..verify
- * by sending CMD1 (MMC's ACMD41)
- */
- if (status == -3){
- /* check if MMC? */
- SD_clk_restricted_cmd(SD_CMD_GO_IDLE_STATE, 0);
- cnt=0;
- SD_ocr_reg_ptr->card_ready = 0;
- do {
- status = SD_clk_restricted_cmd(SD_CMD_MMC_SEND_OP_COND,
- SD_ACCEPTABLE_OCR);
- if (status == -1) {
- /* no response */
- cnt++;
- if (cnt > SD_MAX_RETRIES){
- /* card not voltage compatible */
- return (-1);
- }
- }
- } while (!SD_ocr_reg_ptr->card_ready);
- SD_card_info.type = SD_MMC; /* MultiMedia Card */
- sd_is_mmc = 1;
- } else {
- SD_card_info.type = SD_MEM; /* SD Memory Card */
- }
- if(SD_card_info.type == SD_MMC){
- SD_rca_reg = 0x1;
- }
- else{
- SD_rca_reg = 0xffff;
- }
- /* send CMD2 to get CID number */
- status = SD_clk_restricted_cmd(SD_CMD_ALL_SEND_CID, 0);
-
- /* send CMD3 to get RCA */
- if(SD_card_info.type == SD_MMC){
- status = SD_clk_restricted_cmd(SD_CMD_SEND_REL_ADDR,
- SD_rca_reg<<16);
- }
- else{
- status = SD_clk_restricted_cmd(SD_CMD_SEND_REL_ADDR, 0);
- }
-
- if (status == 1) {
- /* send CMD9 to get Card Specific Data (CSD) */
- status = SD_send_cmd(SD_CMD_SEND_CSD, SD_rca_reg<<16, 1);
- if (status == 1) {
- SD_update_card_info();
- /* send card to tranfer state */
- SD_send_cmd(SD_CMD_SELECT_CARD, SD_rca_reg<<16, 1);
- if (SD_card_info.type > SD_MMC) {
- /* send ACMD51 to get SD configuration register */
- SD_scr_reg_ptr->sd_bus_widths = 0x1; /* default 1bit */
- SD_send_acmd(SD_ACMD_SEND_SCR, 0, 1);
-
- /* set to 4bit data bus if possible */
- SD_set_bus_width(2);
- /* send ACMD13 to get SD Status register */
- SD_send_acmd(SD_ACMD_SD_STATUS, 0, 1);
- }
- /* we have valid SD/MMC card */
- status = 5;
- } else {
- status = -2; /* failed to get CSD */
- }
- } else {
- SD_card_info.type = SD_UNKNOWN;
- status = 0;
- }
- SD_enable_io(0);
-
- return (status);
- }
- /*
- Function: SD-memory/MMC card reset.
- input:
- output:
- side-effects:
- */
- void SD_reset(void)
- {
- unsigned sclk_high, sclk_low;
- SD_GET_SCLK_VAL(sclk_high, sclk_low);
- SD_send_cmd(SD_CMD_GO_IDLE_STATE, 0, 1);
- SD_xmit_info.data_width = 0; /* initially only D0 used */
- SD_card_info.type = SD_UNKNOWN;
- sd_is_mmc = 0;
- SD_card_info.inserted = 0;
- SD_card_info.capacity = 0; /* used to check if CSD received */
- SD_xmit_info.com_state = SD_IDLE;
- #if SD_CHECK_RECV_CRC
- SD_xmit_info.crc7_err_cnt = 0;
- SD_xmit_info.crc16_err_cnt = 0;
- #endif
- SD_acmdq.cmd = SD_CMD_EMPTY;
- SET_SD_CMD; /* initially high */
- }
- /*
- Function: Set data bus width, 4bit or 1bit.
- input:
- 0 - 1bit data bus (narrow bus)
- 2 - 4bit data bus (wide bus)
- output:
- 1: success
- otherwise: failed
- */
- int SD_set_bus_width(int width)
- {
- uint status = 0;
-
- dawei(("SD_set_bus_width( %d )n", width));
- if ((SD_scr_reg_ptr->sd_bus_widths & 0x4)) {
- /* 4bit supported by card */
- if ((width>>1) != SD_xmit_info.data_width) {
- status = SD_send_acmd(SD_ACMD_SET_BUS_WIDTH, width, 1);
- if (status==1) SD_xmit_info.data_width = (width>>1);
- }
- }
- return (status);
- }
- /*
- Function: Read single block from SD. The max block size is card
- specific, in the range of 512 to 2048 bytes. The minimum
- block size is 1 byte if card support "partial block read".
- SD memory card always support PBR.
- (NOTE: currently our code is hardwired to 512B block)
- input:
- addr: location of SD data (lba).
- blk_sz: block size to read. (2^val bytes)
- data_ptr: SD data destination.
- immed: 1 - complete data read in function.
- 0 - initiate data read..let SD_service() finish
- in background.
- output:
- -4: unsupported block size.
- -3: timed out (reached retry limit)
- -2: communication busy
- -1: invalid or unsupported command or no card.
- 0: read initiated.."passed" to SD_service().
- 1: successful
- side-effects:
- */
- int SD_read_blk(int addr, int blk_sz, uint *data_ptr, int immed)
- {
- int status;
- if (blk_sz != SD_xmit_info.cur_blk_size) {
- /* check if card allows block size */
- if ((blk_sz == SD_csd_reg_ptr->rd_blk_len) ||
- (SD_csd_reg_ptr->rd_blk_len_partial &&
- blk_sz < SD_csd_reg_ptr->rd_blk_len)) {
- SD_send_cmd(SD_CMD_SET_BLOCKLEN, (1<<blk_sz), immed);
- } else {
- return (-4); /* invalid block size */
- }
- }
- SD_xmit_info.cur_blk_size = blk_sz;
- SD_xmit_info.rd_dest_ptr = data_ptr;
-
- status=SD_send_cmd(SD_CMD_READ_SINGLE_BLOCK, addr, immed);
- return (status);
- }
- static int SD_write_blk(int addr,int blk_sz,int nblk,int*data_ptr, int immed)
- {
- int status = 1;
- int erase_blk_en, sec_size, wr_bl_len, wr_blk_len_partial;
- if (blk_sz != SD_xmit_info.cur_blk_size) {
- /* check if card allows block size */
- if ((blk_sz == SD_csd_reg_ptr->wr_blk_len) ||
- (SD_csd_reg_ptr->wr_blk_partial &&
- blk_sz < SD_csd_reg_ptr->wr_blk_len)) {
- status = SD_send_cmd(SD_CMD_SET_BLOCKLEN, (1<<blk_sz), immed);
- } else {
- return (-4); /* invalid block size */
- }
- }
- if(status != 1){
- JPRINTF(("SD Set Block_len error. status %dn", status));
- return -1;
- }
- SD_xmit_info.cur_blk_size = blk_sz;
- SD_xmit_info.wr_src_ptr = data_ptr;
- SD_xmit_info.data_len = nblk*(1<<blk_sz);
- if(nblk>1)
- status=SD_send_cmd(SD_CMD_WRITE_MULTI_BLOCK, addr, immed);
- else
- status=SD_send_cmd(SD_CMD_WRITE_BLOCK, addr, immed);
- if(status != 1){
- JPRINTF(("SD Set Write Cmd error.n"));
- return -1;
- }
- else if(SD_xmit_info.result != 0){
- JPRINTF(("SD Writing error.n"));
- return -1;
- }
- return 0;
- }
- /*
- Function: Read multiple blocks from SD. The max block size is card
- specific, in the range of 512 to 2048 bytes.
- (NOTE: currently our code is hardwired to 512B block)
- input:
- addr: location of SD data (lba).
- nblk: number of blocks to read.
- data_ptr: SD data destination.
- immed: 1 - complete data read in function.
- 0 - initiate data read..let SD_service() finish
- in background.
- output:
- -3: timed out (reached retry limit)
- -2: communication busy
- -1: invalid or unsupported command or no card.
- 0: read initiated.."passed" to SD_service().
- 1: successful
- side-effects:
- */
- int SD_read_nblk(int addr, int nblk, uint *data_ptr, int immed)
- {
- int status, limit;
- /* make sure block size is 512B..FAT hardwired */
- if (SD_xmit_info.cur_blk_size != 9) {
- SD_send_cmd(SD_CMD_SET_BLOCKLEN, 512, immed);
- }
- SD_xmit_info.cur_blk_size = 9; /* 512..(2^9) */
- SD_xmit_info.rd_dest_ptr = data_ptr;
- limit = nblk*512;
- #if 0
- status = SD_send_cmd(MMC_CMD_READ_UNTIL_STOP, addr, 0);
- #endif
- status = SD_send_cmd(SD_CMD_READ_MULTI_BLOCK, addr, 0);
- SD_xmit_info.data_len = nblk*512;
- SD_xmit_info.data_cnt = 0;
- /* NOTE: for "non-immediate" case, make sure similar process
- * below is present in background task to complete the read.
- */
- if ((status >= 0) && immed) {
- PRINTF(("com_state %dn",SD_xmit_info.com_state));
- while (SD_xmit_info.com_state) {
- SD_service();
- if (SD_xmit_info.data_cnt >= limit
- && !sd_is_mmc) break;
- }
- status = SD_send_cmd(SD_CMD_STOP_TRANSMIT, 0, immed);
- PRINTF(("xmit bytes %d, required bytes %d, statusn",
- SD_xmit_info.data_cnt, SD_xmit_info.data_len, status));
- }else{
- JPRINTF(("SD_read_nblk... error n"));
-
- }
- return (status);
- }
- /*
- Function: used in SD_service() for post-processing of commands...
- 1) command retry for errors (up to SD_MAX_RETRIES).
- 2) send app-command if CMD55 was previously sent.
- 3) send pending command in queue if any.
- input: no arguments..but app-commands and pending commands are
- stored in "SD_acmdq" structure for processing.
-
- output:
- side-effects:
- */
- int SD_get_next_cmd(void)
- {
- int send=0;
-
- if (SD_xmit_info.response_expected &&
- !SD_xmit_info.response_recv) {
- if (SD_xmit_info.retry_cnt < SD_MAX_RETRIES) {
- /* failed/aborted commands..retry */
- SD_xmit_info.wait_nclk = SD_NCR_MAX;
- send = 1;
- } else {
- /* reach retry limit */
- SD_xmit_info.retry_cnt = 0xff;
- }
- } else {
- /* command specific post-processing */
- switch (SD_xmit_info.cmd) {
- case SD_CMD_APP_CMD:
- /* send app-command */
- SD_set_cmd(SD_acmdq.cmd, SD_acmdq.arg);
- SD_acmdq.cmd = SD_CMD_EMPTY; /* clear cmd-Q */
- send = 1;
- break;
-
- default:
- if (SD_acmdq.cmd != SD_CMD_EMPTY) {
- /* cmd pending */
- send = SD_set_cmd(SD_acmdq.cmd, SD_acmdq.arg);
- SD_acmdq.cmd = SD_CMD_EMPTY; /* clear cmd-Q */
- }
- break;
- }
- }
-
- return (send);
- }
- /*
- Function: send command to SD card.
- input:
- command: command index (0-63).
- arg: command argument.
- immed: 1-complete command immediately
- 0-initiate command..let SD_service() finish
- output:
- -3: timed out (reached retry limit)
- -2: communication busy
- -1: invalid or unsupported command or no card.
- 0: pending..command "passed" to SD_service().
- 1: successful
- */
- int SD_send_cmd(int command, uint arg, int immed)
- {
- int status=0;
- if (!SD_card_info.inserted || command > 63)
- return (-1); /* sanity check */
-
- /* send command w/ CRC7*/
- if ( (SD_xmit_info.com_state == SD_IDLE) ||
- (command == SD_CMD_STOP_TRANSMIT) ) {
- if (!SD_set_cmd(command, arg)) return (-1);
- SD_xmit_info.com_state = HOST2SD_START;
-
- if (immed) {
- while (SD_xmit_info.com_state) SD_service();
- status = (SD_xmit_info.retry_cnt == 0xff) ? -3 : 1;
- }
- } else {
- /* put in cmd-Q..if not app-command */
- if (!(command & ACMD_MARKER) &&
- (command != SD_CMD_APP_CMD)) {
- SD_acmdq.cmd = command;
- SD_acmdq.arg = arg;
- } else {
- status = -2; /* Bus is busy..lost app-command */
- }
- }
- return (status);
- }
- /*
- Function: send application specific command to SD card.
- App-commands needs to send pre-command(0x55).
- input:
- command: app-command index.
- arg: app-command argument.
- immed: 1-complete command immediately
- 0-initiate command..let SD_service() finish
- output:
- -2: communication busy
- -1: invalid command.
- 0: pending..command "passed" to SD_service().
- 1: successful
- */
- int SD_send_acmd(int acmd, uint arg, int immed)
- {
- int status;
-
- /* set app-command */
- SD_acmdq.cmd = acmd;
- SD_acmdq.arg = arg;
- status = SD_send_cmd(SD_CMD_APP_CMD, SD_rca_reg<<16, immed);
-
- return (status);
- }
- /*
- Function: Initializes xmit data structure for new command.
- Checks card(CSD reg) for command class support.
- input:
- command: command index.
- arg: command argument.
- output:
- 0: command not supported by card.
- 1: successful
- */
- static int SD_set_cmd(int command, uint arg)
- {
- uint is_acmd, cmd, tmp;
- uchar *sd_resp_ptr;
-
- cmd = command & 0x3f;
- is_acmd = command & ACMD_MARKER;
- if (SD_card_info.capacity) {
- /* card has been initialized..check class support */
- tmp = (is_acmd) ? SD_CL8 : SD_cmd2class[cmd]; /* class */
- if (!(SD_csd_reg_ptr->ccc & (1<<tmp))) {
- return(0); /* card does not support command class */
- }
- }
- sd_resp_ptr = (is_acmd) ? SD_acmd2resp : SD_cmd2resp;
- SD_xmit_info.cmd = command;
- SD_xmit_info.arg = arg;
- SD_xmit_info.response_expected = (sd_resp_ptr[cmd] & 0xf);
- SD_xmit_info.response_recv = 0;
- SD_xmit_info.use_data = (sd_resp_ptr[cmd]>>4);
- SD_xmit_info.wait_nclk = SD_NCR_MAX;
- SD_xmit_info.cmd_sent = 0;
- SD_xmit_info.retry_cnt = 0;
- if (SD_xmit_info.use_data == 2) { /* data read */
- /* data destination */
- if (SD_xmit_info.cmd == SD_ACMD_SD_STATUS) {
- SD_xmit_info.cur_blk_size = 6; /* 64Bytes */
- SD_xmit_info.rd_dest_ptr = (uint *)SD_status_ptr;
- } else if (SD_xmit_info.cmd == SD_ACMD_SEND_SCR) {
- SD_xmit_info.cur_blk_size = 3; /* 8Bytes */
- SD_xmit_info.rd_dest_ptr = (uint *)SD_scr_reg_ptr;
- }
- } else if (!SD_xmit_info.use_data
- || SD_xmit_info.response_expected) {
- /* response data destination */
- if (SD_xmit_info.response_expected == SD_R2) {
- SD_xmit_info.rd_dest_ptr =
- (SD_xmit_info.cmd == SD_CMD_SEND_CSD) ?
- (uint *)SD_csd_reg_ptr : (uint *)SD_cid_reg_ptr;
- } else {
- if (SD_xmit_info.response_expected == SD_R3){
- SD_xmit_info.rd_dest_ptr = (uint *)SD_ocr_reg_ptr;
- } else if (SD_xmit_info.response_expected == SD_R6){
- /* R6 is special..*/
- SD_xmit_info.rd_dest_ptr = &SD_rdata32;
- } else { /* R1 or R1b */
- SD_xmit_info.rd_dest_ptr = (uint *)SD_card_status_ptr;
- }
- }
- }
- return(1);
- }
- static int SD_slow_clk_data_out(uchar out_data)
- {
- int i;
- unsigned sclk_high, sclk_low;
- SD_GET_SCLK_VAL(sclk_high, sclk_low);
- for(i=0; i<8; i++){
- if (out_data & 0x80) {
- SET_SD_CMD;
- } else {
- CLEAR_SD_CMD;
- }
- out_data <<= 1;
- CLEAR_SD_CLK;
- risc_sleep_a_bit(USEC(2));
- SET_SD_CLK;
- risc_sleep_a_bit(USEC(2));
- }
- }
- /***********************************************
- up to 1 DWORD
- ************************************************/
- static int SD_slow_clk_data_in(int bit_cnt)
- {
- int data_in = 0, i;
- unsigned sclk_high, sclk_low;
- SD_GET_SCLK_VAL(sclk_high, sclk_low);
- for (i=0; i<bit_cnt; i++) {
- CLEAR_SD_CLK;
- risc_sleep_a_bit(USEC(2));
- SET_SD_CLK;
- risc_sleep_a_bit(USEC(1));
- data_in <<= 1;
- data_in |= (SD_CMD_HIGH != 0);
- risc_sleep_a_bit(USEC(1));
- }
- return data_in;
- }
- static void SD_slow_clk_pulse_l2h(void)
- {
- unsigned sclk_high, sclk_low;
- SD_GET_SCLK_VAL(sclk_high, sclk_low);
- CLEAR_SD_CLK;
- risc_sleep_a_bit(USEC(2));
- SET_SD_CLK;
- risc_sleep_a_bit(USEC(2));
- }
- /*
- Function: For init commands during SD card initialization,
- under clock restriction (100KHz < clk < 400KHz).
- (Also for MMC's CMD1)
- input:
- command: command index (CMD1,CMD2,CMD3,CMD55,ACMD41).
- arg: command argument.
- output:
- -1: timed out (reached retry limit).
- 0: crc error.
- 1: successful
- side-effects:
- updates SD_card_status for CMD55 if success.
- updates SD_ocr_reg for ACMD41/CMD1 if success.
- updates SD_cid_reg for CMD2 if success.
- updates SD_rca_reg for CMD3 if success.
- */
- int SD_clk_restricted_cmd(int command, uint arg)
- {
- int i, j,cnt, sd_timeout, rcv_cnt, crc_check;
- ushort sd_crc;
- uint sd_mask, tmp, data_in, *sd_rdata_ptr;
- char cmd_buf[8], rcv_buf[8], *pChar, *rdata_pchar;
- unsigned sclk_high, sclk_low;
- PRINTF(("SD_clk_restricted_cmd ...command %x, arg %xn", command, arg));
- SD_GET_SCLK_VAL(sclk_high, sclk_low);
-
- pChar = cmd_buf;
- data_in = 0x40|(command & 0x3f);
- *pChar++ = data_in;
- *pChar++ = (arg>>24) & 0xff;
- *pChar++ = (arg>>16)& 0xff;
- *pChar++ = (arg>>8) &0xff;
- *pChar++ = arg & 0xff;
- sd_crc = SD_calc_crc7(cmd_buf, 5);
- for (i=0; i<5; i++)
- SD_slow_clk_data_out(cmd_buf[i]);
- tmp = (sd_crc<<1) | 1;
- /* crc7 + end bit */
- SD_slow_clk_data_out(tmp);
- SD_CMD_INPUT; /* get ready for response */
- if(SD_card_info.type == SD_MMC
- && command == SD_CMD_SEND_REL_ADDR)
- sd_timeout = SD_NCR_MAX;
- else
- sd_timeout = SD_NID_MAX;
-
- for (i = 0; (i < sd_timeout); i++) {
- SD_slow_clk_pulse_l2h();
-
- if (SD_CMD_LOW) { /* response start bit */
- /* xmit bit */
- SD_slow_clk_pulse_l2h();
- /* get SD response */
- sd_crc = 0;
- break;
- }
- }
- if (i >= sd_timeout){
- /* timed out..*/
- JPRINTF(("clk_res: timed outn"));
- return (-1);
- } else {
- cnt = 0;
- crc_check = 0;
- if (command == SD_CMD_ALL_SEND_CID
- ||command == SD_CMD_SEND_CID ) {
- cnt = 3; /* extra data for R2 response */
- sd_rdata_ptr = (uint *)SD_cid_reg_ptr;
- } else if ((command == SD_ACMD_SD_SEND_OP_COND) ||
- (command == SD_CMD_MMC_SEND_OP_COND)) {
- sd_rdata_ptr = (uint *)SD_ocr_reg_ptr;
- /* R3 */
- } else if (command == SD_CMD_SEND_REL_ADDR
- && SD_card_info.type == SD_MEM) {
- sd_rdata_ptr = &SD_rdata32;
- /* R6 */
- crc_check = 1;
- } else { /* R1 (SD_CMD_APP_CMD)*/
- sd_rdata_ptr = (uint *)SD_card_status_ptr;
- crc_check = 1;
- }
- }
-
- /* clock in cmd and arg (38bits)..save only arg (last 32bits) */
- pChar = rcv_buf;
- data_in = SD_slow_clk_data_in(6);
- *pChar++ = data_in;
- rcv_cnt = 1;
- rdata_pchar = (char*)sd_rdata_ptr;
- for(j=0; j<4; j++){
- data_in = SD_slow_clk_data_in(8);
- *pChar++ = data_in;
- rcv_cnt++;
- *rdata_pchar++ = data_in;
- }
-
- cnt <<= 2;
- while (cnt){
- *rdata_pchar++ = SD_slow_clk_data_in(8) ;
- cnt--;
- if (!cnt) goto sd_exit;
- }
- /* crc7 + end bit */
- data_in = SD_slow_clk_data_in(8) ;
-
- #if CHECK_RECV_CRC
- if (!crc_check) {
- sd_crc = 0x7f; /* no CRC for R3 response */
- }else
- sd_crc = SD_calc_crc7(rcv_buf, rcv_cnt);
- data_in >>= 1; /* remove end bit */
- PRINTF(("Received crc: %x, Computed crc: %xn", data_in, sd_crc));
- if (data_in != sd_crc) {
- /* crc error */
- CPRINTF(("CRC error in SD_clk_restricted_cmd()n"));
- CPRINTF(("cmd: %d, arg: %n", command, arg));
- CPRINTF(("xmit crc: 0x%x, gen crc: 0x%xn", data_in, sd_crc));
- BREAKPOINT(0);
- return (0);
- }
- #endif
- if (command == SD_CMD_SEND_REL_ADDR
- && SD_card_info.type == SD_MEM) {
- sd_rdata_ptr = (uint *)SD_card_status_ptr;
- *sd_rdata_ptr &= (~0x1fff); /* bit 0-12 */
- *sd_rdata_ptr |= (SD_rdata32 & 0x1fff);
- SD_card_status_ptr->error =
- (SD_rdata32>>13) & 1;
- SD_card_status_ptr->illegal_cmd =
- (SD_rdata32>>14) & 1;
- SD_card_status_ptr->com_crc_error =
- (SD_rdata32>>15) & 1;
-
- SD_rca_reg = SD_rdata32>>16; /* new RCA */
- }
- sd_exit:
- /* extra 8 Clocks for SD card post-processing */
- for (i = 0; i < 8; i++) {
- SD_slow_clk_pulse_l2h();
- }
- return (1);
- }
- static void SD_cmd_output(uchar out_cmd)
- {
- int i;
- unsigned sclk_high, sclk_low;
- SD_GET_SCLK_VAL(sclk_high, sclk_low);
- for (i=0; i<8; i++) {
- if (out_cmd &0x80) {
- SET_SD_CMD;
- } else {
- CLEAR_SD_CMD;
- }
- PULSE_SD_CLK_HL;
- out_cmd <<= 1;
- }
- }
- static void SD_1_bit_data_out(uchar out_data)
- {
- int i;
- unsigned sclk_high, sclk_low;
- SD_GET_SCLK_VAL(sclk_high, sclk_low);
- for (i=0; i<8; i++) {
- CLEAR_SD_CLK;
- if (out_data & 0x80) {
- SET_SD_DAT0;
- } else {
- CLEAR_SD_DAT0;
- }
- SET_SD_CLK;
- out_data <<= 1;
- }
- }
- static void SD_4_bit_data_out(char *pOutData, int cnt)
- {
- int i;
- char out_data;
- unsigned sclk_high, sclk_low;
- SD_GET_SCLK_VAL(sclk_high, sclk_low);
- for(i= 0; i<cnt; i++){
- out_data = *pOutData++;
- CLEAR_SD_CLK;
- SET_SD_DAT3_0( ((out_data>>4) & 0xf));
- SET_SD_CLK;
- CLEAR_SD_CLK;
- SET_SD_DAT3_0( (out_data&0xf));
- SET_SD_CLK;
- }
- }
- /*****************************************************************
- up to 1 DWORD
- ******************************************************************/
- static int SD_1_bit_data_in(int bit_cnt)
- {
- int i, data_in;
- unsigned sclk_high, sclk_low;
- SD_GET_SCLK_VAL(sclk_high, sclk_low);
- data_in = 0;
- for (i=0; i<bit_cnt; i++){
- data_in <<= 1;
- CLEAR_SD_CLK;
- if(sd_is_mmc){
- asm("nop"); asm("nop");asm("nop");
- data_in |= SD_DAT0;
- SET_SD_CLK;
- }else{
- SET_SD_CLK;
- data_in |= SD_DAT0;
- }
- }
- return data_in;
- }
- /*
- Function: The main SD transmission state machine..processes
- all SD/MMC related commands.
- (ref. SD bus protocol, pp.10-83,
- SD-mem Physical layer specifications)
- input: no arguments, but relies on "SD_xmit_info" structure for
- state transitions and transmission info.
- output:
- side-effects:
- "SD_xmit_info" members are updated according to
- transmission progress.
- */
- void SD_service(void)
- {
- static uint sd_mask, sd_cmd_info, *sd_rdata_ptr, sd_cnt;
- static ushort sd_crc[4];
- int i,j, sd_cmd_high, sd_dat0_high, arg;
- uint tmp, data_in;
- int wr_feedback_crc;
- char cmd_buf[8], *pChar;
- unsigned sclk_high, sclk_low;
- SD_GET_SCLK_VAL(sclk_high, sclk_low);
- switch (SD_xmit_info.com_state) {
- case HOST2SD_START:
- SET_SD_CMD;
- CLEAR_SD_CLK; /* prepare */
- sd_cmd_info = (SD_xmit_info.cmd&0x3f)|0x40;
- sd_cnt = 0;
- pChar = cmd_buf;
- *pChar++ = sd_cmd_info;
- arg = SD_xmit_info.arg;
- *pChar++ =(arg>>24)&0xff;
- *pChar++ =(arg>>16)&0xff;
- *pChar++ =(arg>>8)&0xff;
- *pChar = arg & 0xff;
- sd_crc[0] = SD_calc_crc7(cmd_buf, 5);
- SD_xmit_info.com_state = HOST2SD_CMD;
- SD_xmit_info.result = -1; /* need to set to be 0 when succeed,
- currently only used in case of Erase */
- /*break; save time..let it drop*/
- case HOST2SD_CMD:
- sd_cnt++; /* for timeout/mode check */
- /* command index/argument..8bits at a time */
- for(i=0; i<5; i++)
- SD_cmd_output(cmd_buf[i]);
-
- SD_xmit_info.com_state = HOST2SD_CRC7;
- break;
-
- case HOST2SD_CRC7:
- /* send crc7 */
- tmp = (sd_crc[0]<<1) | 1; /* crc7 + end bit */
- SD_cmd_output(tmp);
- CLEAR_SD_CLK;
- if (SD_xmit_info.response_expected) {
- SD_CMD_INPUT; /* tristate cmd */
- if (SD_xmit_info.use_data == 2) {
- /* data read */
- if (SD_xmit_info.data_width) {
- /* all four data lines used */
- SD_DAT3_0_INPUT;
- } else {
- SD_DAT0_INPUT;
- }
- sd_cmd_info = 0; /* bytes received */
- SD_xmit_info.wait_nclk = SD_card_info.n_ac_max;
- }
- else if(SD_xmit_info.response_expected == SD_R1b){
- SD_DAT0_INPUT; /* busy check */
- }
- sd_rdata_ptr = SD_xmit_info.rd_dest_ptr;
- SD_xmit_info.com_state = HOST2SD_WAIT;
- } else {
- SD_xmit_info.com_state = HOST2SD_8CYCLES;
- }
- break;
-
- case HOST2SD_WAIT:
- /* check 8 cycles at a time */
-
- for (i = 0; SD_xmit_info.wait_nclk; i++) {
- SD_LOCK15;
- SET_SD_CLK;
- if(sd_is_mmc){
- CLEAR_SD_CLK;
- sd_cmd_high = SD_CMD_HIGH? 1:0;
- sd_dat0_high = SD_DAT0_HIGH? 1:0;
- }else{
- sd_cmd_high = SD_CMD_HIGH? 1:0;
- sd_dat0_high = SD_DAT0_HIGH? 1:0;
- CLEAR_SD_CLK;
- }
- if (SD_xmit_info.use_data != 2
- && !SD_xmit_info.response_recv
- && !sd_cmd_high){ /* response start bit */
-
- SD_LOCK15;
- SET_SD_CLK;
- if(sd_is_mmc){
- CLEAR_SD_CLK;
- sd_cmd_high = SD_CMD_HIGH? 1:0;
- }else{
- sd_cmd_high = SD_CMD_HIGH? 1:0;
- CLEAR_SD_CLK;
- }
-
- /* get SD response */
- sd_crc[0] = 0;
- sd_mask = 6; /* bit count */
- sd_cmd_info = 0; /* clear received bits */
- sd_cnt = 0; /* for timeout/mode check */
- SD_xmit_info.com_state = SD2HOST_NODATA;
- break;
- } else if ((SD_xmit_info.use_data==2)
- && !sd_dat0_high) { /* data start bit? */
- sd_crc[0] = 0; /* clear crc */
- /* current block size (bytes) */
- if(SD_xmit_info.cmd == MMC_CMD_READ_UNTIL_STOP)
- sd_mask = SD_xmit_info.data_len;
- else
- sd_mask = 1 << (SD_xmit_info.cur_blk_size);
- if(SD_xmit_info.data_width){
- SD_xmit_info.com_state = SD2HOST_DATA4;
- }
- else{
- SD_xmit_info.com_state = SD2HOST_DATA1;
- }
- break;
- }
- /* btan: After received response, we actually don't need wait n_wr_max clk. *
- * 4 clk is ok for my SD. I did not test other SD. If you meet problem in *
- * SD writing function, please increase it or let me know. */
- else if (SD_xmit_info.use_data != 2 && SD_xmit_info.response_recv
- && sd_cmd_high && SD_xmit_info.wait_nclk > 4) {
- SD_xmit_info.wait_nclk = 4;
- }
- SD_xmit_info.wait_nclk--;
- }
- if (!SD_xmit_info.wait_nclk) {
- #ifdef SD_ENABLE_WRITE
- if (SD_xmit_info.use_data == 1
- && SD_xmit_info.response_recv) {
- /* prepare to write.. */
-
- /* current block size (bytes) */
- sd_cmd_info = 1 << (SD_xmit_info.cur_blk_size);
- if (SD_xmit_info.data_width) {
- /* write wide bus */
- CLEAR_SD_DAT3_0;
- SD_xmit_info.com_state = HOST2SD_DATA4;
- } else {
- CLEAR_SD_DAT0;
- SD_xmit_info.com_state = HOST2SD_DATA1;
- }
- break;
- } else
- #endif /* SD_ENABLE_WRITE */
- {
- /* timed out..send again?? */
- JPRINTF(("SD res:time out. xmit_len %d, xmit_cnt %d cmd %dn",
- SD_xmit_info.data_len, SD_xmit_info.data_cnt,
- SD_xmit_info.cmd));
- SD_xmit_info.retry_cnt++;
- SD_xmit_info.com_state = HOST2SD_8CYCLES;
- }
- }
- break;
- #ifdef SD_ENABLE_WRITE
- case HOST2SD_DATA1:
- /* write data, one byte at a time */
- sd_cmd_info = 1 << (SD_xmit_info.cur_blk_size);
- pChar = (char*)SD_xmit_info.wr_src_ptr + SD_xmit_info.data_cnt;
- /* crc16 calculation for narrow bus */
- sd_crc[0] = SD_calc_crc16((uchar *)pChar,sd_cmd_info);
- JPRINTF(("Xmit src %x, len %dn", pChar, sd_cmd_info));
- /* send start bit */
- CLEAR_SD_DAT0;
- CLEAR_SD_CLK;
- SET_SD_CLK;
- for(i=0; i<sd_cmd_info; i++)
- SD_1_bit_data_out(*pChar++);
-
- SD_xmit_info.data_cnt += sd_cmd_info; /* monitor total bytes */
-
- /* set wait timeout cycles..in case multi-block */
- SD_xmit_info.wait_nclk = SD_card_info.n_wr_max;
- /* finished data..send CRC */
- SD_xmit_info.com_state = HOST2SD_CRC16_DATA;
- break;
- case HOST2SD_DATA4:
- /* wide bus write, 32bits at a time */
- sd_cmd_info = 1 << (SD_xmit_info.cur_blk_size);
- pChar = (char*)SD_xmit_info.wr_src_ptr + SD_xmit_info.data_cnt;
- PRINTF(("wr_src_ptr %x, data_cnt %x pChar %xn",
- SD_xmit_info.wr_src_ptr, SD_xmit_info.data_cnt, pChar));
- /* crc16 calculation for 4-bit bus */
- SD_calc_crc16_4_bit((int*)pChar, sd_cmd_info>>2, sd_crc);
- /* send start bit */
- CLEAR_SD_DAT3_0;
- CLEAR_SD_CLK;
- SET_SD_CLK;
- SD_4_bit_data_out(pChar, sd_cmd_info);
- SD_xmit_info.data_cnt += sd_cmd_info; /* monitor total bytes */
- /* set wait timeout cycles..in case multi-block */
- SD_xmit_info.wait_nclk = SD_card_info.n_wr_max;
- /* finished data "block"..get CRC */
- SD_xmit_info.com_state = HOST2SD_CRC16_DATA;
- break;
- case HOST2SD_CRC16_DATA:
- /* send crc16 */
- if (SD_xmit_info.data_width){
- /* wide bus */
- uint filter = 0x8000;
- for (i=0; i<16; i++){
- CLEAR_SD_CLK;
- tmp = 0;
- for(j=0; j<4; j++){
- tmp |= ( (sd_crc[j]&filter?1:0)<<j);
- }
- SET_SD_DAT3_0(tmp);
- SET_SD_CLK;
- filter >>= 1;
- }
- /* send end bit */
- CLEAR_SD_CLK;
- SET_SD_DAT3_0(0xf); /* set dat[3:0] high */
- SET_SD_CLK;
- SD_DAT0_INPUT;
- } else {
- /* narrow bus */
- SD_1_bit_data_out(sd_crc[0]>>8);
- SD_1_bit_data_out(sd_crc[0]&0xff);
- /* send end bit */
- CLEAR_SD_CLK;
- SET_SD_DAT0;
- SET_SD_CLK;
- SD_DAT0_INPUT;
- }
- PRINTF(("wait to get crc back n"));
- /* 2 clks..then there should be CRC check start bit */
- PULSE_SD_CLK;
- PULSE_SD_CLK;
- /* crc status: 010: Ok
- 101: Transimission error
- 111: Error */
- wr_feedback_crc = SD_1_bit_data_in(5);
-
- sd_cnt = 0;
- if(wr_feedback_crc != 0x5){
- JPRINTF(("crc after xmit CRC16: %xn",wr_feedback_crc));
- SD_xmit_info.com_state = HOST2SD_8CYCLES;
- }
- else{
- SD_xmit_info.wait_nclk = 100*SD_card_info.n_wr_max;
- SD_xmit_info.com_state = HOST2SD_CHECK_BUSY;
- }
- break;
- #endif /* SD_ENABLE_WRITE */
- case HOST2SD_CHECK_BUSY:
-
- #if 0
- /* Reading performance will be impacted */
- RISC_sleep_nsec(3000000);
- #endif
- sd_cnt++; /* for timeout/mode check */
- for (i=0; i<8; i++) {
- PULSE_SD_CLKZ;
- if (SD_DAT0_HIGH) { /* Busy bit */
- /* SD not Busy..continue */
- /* set next_state..
- * - for single-block write, prepare to go idle
- * - for multi-block write, write another block
- */
- PRINTF((" Not busy ... xmit_cnt %dn",
- SD_xmit_info.data_cnt));
-
- if(SD_xmit_info.cmd == SD_CMD_WRITE_MULTI_BLOCK
- && SD_xmit_info.data_cnt < SD_xmit_info.data_len){
- SD_xmit_info.wait_nclk = SD_card_info.n_wr_max;
- SD_xmit_info.com_state = HOST2SD_WAIT;
- }
- else{
- SD_xmit_info.com_state = HOST2SD_8CYCLES;
- SD_xmit_info.result = 0;
- }
- /* single block write or erase*/
- break;
- }
- }
- /*consider a timeout mechanism for this state */
-
- if (sd_cnt > SD_xmit_info.wait_nclk){
- JPRINTF(("Check Bus Busy: Time outn"));
- SD_xmit_info.com_state = HOST2SD_8CYCLES;
- }
- break;
- case SD2HOST_NODATA:
- sd_cnt++; /* for timeout/mode check */
- /* response: command index/arg..8bits at a time */
- data_in = 0;
-
- for (i=0; (i<8) && sd_mask; i++) {
- SD_LOCK15;
- SET_SD_CLK;
- if(sd_is_mmc){
- CLEAR_SD_CLK;
- sd_cmd_high = SD_CMD_HIGH? 1:0;
- }else{
- sd_cmd_high = SD_CMD_HIGH? 1:0;
- CLEAR_SD_CLK;
- }
- data_in <<= 1;
- data_in |= sd_cmd_high;
- sd_mask--; /* bit count remain */
- }
-
- if (i==8) { /* one arg byte in..cmd index only has 6 bits */
- SD_rdata32 <<= 8;
- SD_rdata32 |= data_in;
- sd_cmd_info += 8; /* received bits */
- if (sd_cmd_info == 32) { /* received 32 bits */
- *sd_rdata_ptr++ = SD_rdata32;
- /* for 32 bit data we won't get anymore */
- sd_cmd_info = 0; /* reset */
- }
- }
-
- if (!sd_mask) {
- if (sd_cnt == 1) {
- /* finished cmd..get arg */
- if (SD_xmit_info.response_expected == SD_R2) {
- sd_mask = 120; /* CID/CSD bit count */
- sd_crc[0] = 0; /* CRC7 on arg data only */
- } else {
- sd_mask = 32; /* bit count */
- }
- sd_cmd_info = 0; /* clear received bits */
-
- /* no state change..SD_xmit_info.com_state */
- } else if ((sd_cnt == 16) &&
- (SD_xmit_info.response_expected == SD_R2)) {
- /* finished CID/CSD register..next CRC7 */
- sd_crc[1] = sd_crc[0]; /* save current crc */
- sd_mask = 8; /* internal CRC7 + end bit */
- /* no state change..SD_xmit_info.com_state */
- } else {
- /* finished arg.. */
- if (SD_xmit_info.response_expected == SD_R2) {
- /* internal crc */
- #if SD_CHECK_RECV_CRC
- data_in =
- (SD_xmit_info.cmd == SD_CMD_SEND_CSD) ?
- (uint)SD_csd_reg_ptr->crc :
- (uint)SD_cid_reg_ptr->crc;
-
- data_in &= 0x7f; /* 7bit crc */
- sd_crc[1] &= 0x7f; /* 7bit crc */
- if (data_in != sd_crc[1]) {
- /* crc error */
- SD_xmit_info.crc7_err_cnt++;
- CPRINTF(("R2 CRC7 error in SD_service()n"));
- CPRINTF(("xmit crc: 0x%x, gen crc: 0x%xn",
- data_in, sd_crc[1]));
- BREAKPOINT(0);
- }
- #endif /* SD_CHECK_RECV_CRC */
- SD_xmit_info.response_recv = 1;
- SD_xmit_info.com_state = HOST2SD_8CYCLES;
- } else {
- /* R6 response data */
- if (SD_xmit_info.response_expected == SD_R6) {
- sd_rdata_ptr = (uint *)SD_card_status_ptr;
- *sd_rdata_ptr &= (~0x1fff);
- *sd_rdata_ptr |= (SD_rdata32 & 0x1fff);
- SD_card_status_ptr->error =
- (SD_rdata32>>12) & 1;
- SD_card_status_ptr->illegal_cmd =
- (SD_rdata32>>13) & 1;
- SD_card_status_ptr->com_crc_error =
- (SD_rdata32>>14) & 1;
- SD_rca_reg = SD_rdata32>>16;
- }
- if (SD_xmit_info.response_expected == SD_R3) {
- /* R3 response has no CRC7 */
- sd_crc[0] = 0x7f;
- }
- /* finished arg..get CRC */
- SD_xmit_info.com_state = SD2HOST_CRC7_NODATA;
- }
- }
- }
- break;
- case SD2HOST_DATA1:
- /* just get data, 32*sd_maskbits at a time..ignore response */
-
- PRINTF(("SD2HOST_DATA1: xmit_len %d, xmit_data %d sd_mask %dn",
- SD_xmit_info.data_len, SD_xmit_info.data_cnt, sd_mask));
-
- sd_cmd_info = sd_mask;
- j = (sd_mask+3)/4;
- if(sd_is_mmc){
- do{
- data_in = 0;
- for (i=0; (i<32); i++){
- data_in <<= 1;
- SD_LOCK15;
- SET_SD_CLK;
- CLEAR_SD_CLK;
- asm("nop"); asm("nop");asm("nop");
- data_in |= SD_DAT0;
- }
- *sd_rdata_ptr++ = data_in;
- }while(--j>0);
-
- }else{
- do{
- data_in = 0;
- for (i=0; (i<32); i++){
- data_in <<= 1;
- SD_LOCK15;
- SET_SD_CLK;
- data_in |= SD_DAT0;
- CLEAR_SD_CLK;
- }
- *sd_rdata_ptr++ = data_in;
- }while(--j>0);
- }
- PRINTF(("SD_xmit_cmd %dn", SD_xmit_info.cmd));
- if(SD_xmit_info.cmd == SD_CMD_READ_MULTI_BLOCK){
- SD_xmit_info.data_cnt += sd_cmd_info;
- PRINTF(("SD_xmit_cmd %dn", SD_xmit_info.cmd));
- }
- else{
- SD_xmit_info.data_cnt = sd_cmd_info;
- }
-
- /* set wait timeout cycles..in case multi-block */
- SD_xmit_info.wait_nclk = SD_card_info.n_ac_max;
-
- /* finished arg..get CRC */
- if(SD_xmit_info.cmd == MMC_CMD_READ_UNTIL_STOP){
- SD_xmit_info.com_state = SD_IDLE;
- }else{
- SD_xmit_info.com_state = SD2HOST_CRC16_DATA;
- PRINTF(("go to get CRC16n"));
- }
- break;
- case SD2HOST_DATA4:
- /* just get data, 32bits at a time..ignore response */
- sd_cmd_info += sd_mask;
- sd_mask >>= 2;
- do{
- data_in = 0;
- for (i=0; (i<8); i++){
- SD_LOCK15;
- SET_SD_CLK;
- data_in <<= 4;
- data_in |= SD_DAT3_0;
- CLEAR_SD_CLK;
- }
- *sd_rdata_ptr++ = data_in;
- sd_mask--; /* bytes remain */
- }while(sd_mask>0);
- SD_xmit_info.data_cnt = sd_cmd_info; /* monitor total bytes */
-
- /* set wait timeout cycles..in case multi-block */
- SD_xmit_info.wait_nclk = SD_card_info.n_ac_max;
- /* finished data block..get CRC */
- SD_xmit_info.com_state = SD2HOST_CRC16_DATA;
- break;
- case SD2HOST_CRC7_NODATA:
- /* get crc7 */
- data_in = 0;
- /* clock in crc7 + end bit */
-
- for (i=0; (i < 8); i++) {
- SD_LOCK15;
- SET_SD_CLK;
- if(sd_is_mmc){
- CLEAR_SD_CLK;
- sd_cmd_high = SD_CMD_HIGH ?1:0;
- }else{
- sd_cmd_high = SD_CMD_HIGH ?1:0;
- CLEAR_SD_CLK;
- }
- #if SD_CHECK_RECV_CRC
- data_in <<= 1;
- data_in |= sd_cmd_high;
- #endif
- }
- SD_xmit_info.response_recv = 1;
- if(SD_xmit_info.response_expected == SD_R1b){
- if(SD_xmit_info.cmd == SD_CMD_ERASE
- && (SD_card_status_ptr->erase_seq_error
- || SD_card_status_ptr->erase_param)
- ){
- JPRINTF(("Erase error...n"));
- SD_xmit_info.com_state = HOST2SD_8CYCLES;
- }else{
- SD_xmit_info.wait_nclk = 100*SD_card_info.n_wr_max;
- SD_xmit_info.com_state = HOST2SD_CHECK_BUSY;
- JPRINTF(("R1b: to check busy state: card_status %x, cmd %d n",
- *(int*)SD_card_status_ptr, SD_xmit_info.cmd));
- }
- }else{
- #ifdef SD_ENABLE_WRITE
- if (SD_xmit_info.cmd == SD_CMD_WRITE_BLOCK
- ||SD_xmit_info.cmd == SD_CMD_WRITE_MULTI_BLOCK ) {
- /* data write */
- if (SD_xmit_info.data_width) {
- SET_SD_DAT3_0(0xf); /* set dat[3:0] high */
- } else {
- SET_SD_DAT0;
- }
- SD_xmit_info.wait_nclk = SD_card_info.n_wr_max;
- SD_xmit_info.com_state = HOST2SD_WAIT;
- SD_xmit_info.data_cnt = 0;
- JPRINTF(("Wait to write data, status %xn",
- *(int*)SD_card_status_ptr));
- }else
- #endif /* SD_ENABLE_WRITE */
- SD_xmit_info.com_state = HOST2SD_8CYCLES;
- }
- break;
- case SD2HOST_CRC16_DATA:
- /* get crc16 */
- data_in = 0;
- /* clock in crc16 + end bit */
- PRINTF(("SD2HOST_CRC16_DATA:n"));
- for (i=0; (i < 17); i++) {
- data_in <<= 1;
- SD_LOCK15;
- SET_SD_CLK;
- if(sd_is_mmc){
- CLEAR_SD_CLK;
- data_in |= SD_DAT0;
- }else{
- data_in |= SD_DAT0;
- CLEAR_SD_CLK;
- }
- }
- if(data_in &1 == 0)
- JPRINTF(("End bit not found.n"));
- /*
- * - for single-block read, prepare to go idle
- * - for multi-block read, get another block
- */
- if (SD_xmit_info.cmd == SD_CMD_READ_MULTI_BLOCK) {
- PRINTF(("end of sector, xmit_cnt %d xmit_len %dn",
- SD_xmit_info.data_cnt,SD_xmit_info.data_len));
- if(sd_is_mmc
- && SD_xmit_info.data_cnt>= SD_xmit_info.data_len){
- SD_xmit_info.com_state = HOST2SD_8CYCLES;
- SD_xmit_info.response_recv = 1;
- PRINTF(("command->HOST2SD_8CYCLES n"));
- }
- else{
- SD_xmit_info.com_state = HOST2SD_WAIT;
- }
- } else {
- SD_xmit_info.response_recv = 1; /* prevent resend */
- SD_xmit_info.com_state = HOST2SD_8CYCLES;
- }
- break;
- case HOST2SD_8CYCLES:
- /* extra 8 Clocks for SD card's post-processing */
- for (i = 0; i < 8; i++){
- SD_LOCK15;
- SET_SD_CLK;
- CLEAR_SD_CLK;
- }
- /* check for next command..or resend */
- if (SD_get_next_cmd()){
- JPRINTF(("next cmd not emptyn"));
- SD_xmit_info.com_state = HOST2SD_START;
- } else {
- SD_xmit_info.cmd_sent = 1; /* cmd completed */
- SD_xmit_info.com_state = SD_IDLE;
- }
- break;
- case SD_IDLE:
- default:
- break;
- }
- VCX_service();
- }
- int SD_get_status(void)
- {
- int status = 0;
-
- status = SD_send_cmd(SD_CMD_SEND_STATUS, SD_rca_reg<<16, 1);
- if(status != 1)
- return -1;
- else
- return (*(int*)SD_card_status_ptr);
- }
- #ifdef MD_ASYNC_RW
- void SD_clear_state()
- {
- SD_xmit_info.com_state = SD_IDLE;
- SD_xmit_info.cmd = SD_CMD_EMPTY;
- SD_acmdq.cmd = SD_CMD_EMPTY; /* clear cmd-Q */
- return;
- }
- /* return: 0: not finish; 1: finish; 2:read single finish; *
- * 3:write single finish; 4: read multi finish; 5: write multi finish*/
- int SD_cmd_service()
- {
- int ret = 0, status = 1;
- if (!SD_card_info.inserted) {
- SD_clear_state();
- return 1;
- }
- if (SD_xmit_info.com_state != SD_IDLE) SD_service();
- if (SD_xmit_info.com_state == SD_IDLE) {
- if (SD_xmit_info.cmd == SD_CMD_READ_SINGLE_BLOCK) {
- ret = 2;
- }
- else if (SD_xmit_info.cmd == SD_CMD_WRITE_BLOCK) {
- ret = 3;
- }
- else if (SD_xmit_info.cmd == SD_CMD_READ_MULTI_BLOCK) {
- ret = 4;
- }
- else if (SD_xmit_info.cmd == SD_CMD_WRITE_MULTI_BLOCK) {
- ret = 5;
- }
- if (SD_xmit_info.cmd == SD_CMD_WRITE_MULTI_BLOCK ||
- SD_xmit_info.cmd == SD_CMD_READ_MULTI_BLOCK) {
- SD_xmit_info.cmd = SD_CMD_EMPTY;
- status = SD_send_cmd(SD_CMD_STOP_TRANSMIT, 0, 0);
- }
- else {
- SD_xmit_info.cmd = SD_CMD_EMPTY;
- if (!SD_get_next_cmd() && !ret) ret = 1;
- }
- }
- else if (SD_xmit_info.cmd == SD_CMD_READ_MULTI_BLOCK &&
- SD_xmit_info.data_cnt >= SD_xmit_info.data_len && !sd_is_mmc) {
- status = SD_send_cmd(SD_CMD_STOP_TRANSMIT, 0, 0);
- ret = 4;
- }
- return ret;
- }
- #endif /*MD_ASYNC_RW*/
- #if NOT_USED
- /*
- Function:
- input:
- output:
- side-effects:
- */
- int SD_get_status(void)
- {
- uint status = 0;
-
- if (SD_card_info.type > SD_MMC) {
- SD_send_acmd(SD_ACMD_SD_STATUS, 0, 1);
- }
- return (status);
- }
- /*
- Function: SD lock card (password protect)
- input:
- output:
- side-effects:
- */
- int SD_lock_card(int action, char *passwd)
- {
- int status;
-
- /* lock/unlock card */
- return (status);
- }
- /*
- Function: SD set password
- input:
- output:
- side-effects:
- */
- int SD_set_password(char *passwd)
- {
- int status;
-
- /* set password */
- return (status);
- }
- /*
- Function: SD reset password
- input:
- output:
- side-effects:
- */
- int SD_reset_password(char *passwd)
- {
- int status;
-
- /* reset password w/ and w/o password */
- return (status);
- }
- /*
- Function:
- input:
- output:
- side-effects:
- */
- int SD_write_data(uint data)
- {
- int status;
- /* send data w/ CRC16 */
- return (status);
- }
- #endif
- #endif /* SD_MEMORY */