📄 sd_data.c
字号:
{ ch_r = ver_request_dma(0, "dma_sd", 0, 0); ch_w = ver_request_dma(0, "dma_sd", 0, 0); if(ch_r < 0 || ch_w < 0){ printk("<1> alloc sd dma error\n"); return -1; }else{ printk("<1> sd dma chan: r(%d), w(%d)\n", ch_r, ch_w); } memset(&pa, 0, sizeof (pa)); pa.SWidth = DMAC_TSIZE_WORD; pa.DWidth = DMAC_TSIZE_WORD; //init read dma params pa.FlowCntrl = FLOW_PER_MEM_DMAC; pa.SBsize = BURST_SIZE_8; pa.DBsize = BURST_SIZE_1; pa.SIncr = 0; pa.DIncr = 1; if (ver_set_dma(ch_r, &pa) != 0) { printk("<1>sd read:set dma fail:\n"); return -1; } //init write dma params pa.FlowCntrl = FLOW_MEM_PER_DMAC; pa.SBsize = BURST_SIZE_1; pa.DBsize = BURST_SIZE_8; pa.SIncr = 1; pa.DIncr = 0; if (ver_set_dma(ch_w, &pa) != 0) { printk("<1>sd write:set dma fail:\n"); return -1; } return 0;}static int sd_free_dma(void){ if ((ver_free_dma(ch_r) != 0) && (ver_free_dma(ch_w) != 0)) { printk("<1>free sd dma error\n"); return -1; } return 0;}static int sd_start_dma(int read, void *buffer, u32 size, void *p_comp){ pa.sg_len = 0; pa.tsize = size; if(read){ pa.sbuf = (void *) (PHYS_SD0_BASE+0x80); pa.dbuf = buffer; }else{ pa.sbuf = buffer; pa.dbuf = (void *) (PHYS_SD0_BASE+0x80); } pa.trans_done = sd_dma_done; pa.done_data = p_comp; if (read) { if (ver_start_dma(ch_r, &pa) != 0) { printk("<1>sd:start dma fail:%d\n", size); return -1; } } else { if (ver_start_dma(ch_w, &pa) != 0) { printk("<1>sd:start dma fail:%d\n", size); return -1; } } return 0;}#endifstatic void SDI_Print_Sector(unsigned long SectorNum, unsigned long SectorCnt, unsigned char* buffer){ int i, j; for (i=0; i<SectorCnt; i++) { printk("%lX:\n", (SectorNum + i) * BYTES_PER_SECTOR); for (j=0; j<8; j++) { printk("%x ", buffer[i * BYTES_PER_SECTOR + j]); } printk("\n"); }}#define SD_READ_DMA_TIMEOUT 100#define SD_WRITE_DMA_TIMEOUT 250//------------------------------------------------------------------------------//// Read data from SD FIFO register by DMA//// Arguments:// controller - instance created in SDI_InitInterface// SectorNum - the number of first sector to be read// SectorCnt - how many sectors to be write// buffer - buffer to receive data// errorcode - record error. //// Functions:// Send command to card, then call functions SDI_InitDMA// and SDI_StartDMA finished the transfer. ////------------------------------------------------------------------------------//2007-07-31: modified some sd read steps to stronger read actionBOOL SDI_BatchRead_DMA( SD_controller* controller, unsigned long SectorNum, unsigned long SectorCnt, unsigned char* buffer, unsigned long* errorcode ){ unsigned long error = 0; unsigned long timeout; unsigned long DataCtrl = 0; SD_REG *regs;#if (SD_DATA_DEBUG_LEVEL == 1) printk("SDI_BatchRead_DMA: sector at %ld, offset = %lX, len = %ld\n", SectorNum, SectorNum * BYTES_PER_SECTOR, SectorCnt);#endif DECLARE_COMPLETION(comp); regs = controller->Registers; if (!controller || !buffer) { error = 1; goto read_error_handle; } if (SectorNum >= controller->CardCSD.CardSize / BYTES_PER_SECTOR) { error = 2; goto read_error_handle; } if(sd_start_dma(1, buffer, SectorCnt * BYTES_PER_SECTOR, &comp) < 0){ printk("<1>sd start dma error\n"); error = 3; goto read_error_handle; } if (!SDI_SendCmd(controller, &CommandParameters[SET_BLOCKLEN], BYTES_PER_SECTOR, 0, &error)) { error = 0; if (!SDI_SendCmd(controller, &CommandParameters[SET_BLOCKLEN], BYTES_PER_SECTOR, 0, &error)) { printk("<1>r: cmd--SET_BLOCKLEN, error--%ld\n", error); error = 4; goto read_error_handle; } } DataCtrl = 0; apBIT_SET(DataCtrl, MCI_DATA_ENABLE,1); apBIT_SET(DataCtrl, MCI_DATA_DIRECTION, apMCI_DATA_RECEIVE); apBIT_SET(DataCtrl, MCI_DATA_MODE, apMCI_DATA_BLOCKING); apBIT_SET(DataCtrl, MCI_DATA_DMA_ENABLE, 1); apBIT_SET(DataCtrl, MCI_DATA_BLOCKSIZE, BYTES_PER_SECTOR_SH); regs->sd_MASK0 = 0; regs->sd_CLEAR = MCI_STATUS_STATIC_MASK; regs->sd_DATATMR = 0xFFFFFFFF; regs->sd_DATALEN = 0xFFFF; regs->sd_DATACTRL = DataCtrl; if (!SDI_SendCmd(controller, &CommandParameters[READ_MULTIPLE_BLOCK], SectorNum * BYTES_PER_SECTOR, 0, &error)) { printk("<1>cmd--READ_MULTIPLE_BLOCK, error--%ld\n", error); error = 5; goto read_error_handle; } {#if 0 if (regs->sd_STATUS & regs->sd_MASK0 & (MCI_STATUS_DATACRCFAIL|MCI_STATUS_DATATIMEOUT|MCI_STATUS_TXUNDERRUN|MCI_STATUS_RXOVERRUN)) { printk("<1>read: status reg error\n"); error = 6; goto stop_r_trans_handle; }#endif //wait_for_completion(&comp); timeout = wait_for_completion_timeout(&comp, SD_READ_DMA_TIMEOUT); if(!timeout){ printk("<1>sd read dma timeout,%ld, reset, status:%x\n", SectorNum, regs->sd_STATUS); error = 6; } #if 0 int i= 0; while (regs->sd_STATUS & MCI_STATUS_RXDATAAVLBL) { {volatile int a; for(a=0; a<50000; a++); } if (i++ > 100) { printk("<1>Can not wait rx data empty, quit while"); break; } } current->state = TASK_INTERRUPTIBLE; while (!(regs->sd_STATUS & MCI_STATUS_RXFIFOEMPTY)) { //{volatile int a; for(a=0; a<50000; a++); } schedule_timeout(msecs_to_jiffies(100)); }#endifstop_r_trans_handle: if (!SDI_SendCmd(controller, &CommandParameters[STOP_TRANSMISSION], 0, 0, &error)) { printk("<1>cmd--STOP_TRANSMISSION, error--%ld\n", error); error = 7; goto read_error_handle; } } #if 0 if (!error) { apMCI_sResponse response; int i; response.ShortResponse = 0; for (i=0; i<100; i++) { unsigned char resp; SDI_SendCmd(controller, &CommandParameters[SEND_STATUS], RCA, &response, 0) ; resp = (response.ShortResponse >> 9) & 0x0F; if (resp == ST_TRAN) break; {volatile int a; for(a=0; a<50000; a++); } } //printk("<1>delay:%d\n", i); }#endifread_error_handle: regs->sd_DATACTRL = 0; regs->sd_CLEAR = MCI_STATUS_STATIC_MASK; if (error) { printk("<1>read start (%ld) length (%ld) error (%ld)\n", SectorNum, SectorCnt, error); if (errorcode) *errorcode = error; return FALSE; } return TRUE;}//------------------------------------------------------------------------------//// Write data to SD FIFO register by DMA//// Arguments:// controller - instance created in SDI_InitInterface// SectorNum - the number of first sector to be write// SectorCnt - how many sectors to be write// buffer - buffer to send data// errorcode - record error. //// Functions:// Send command to card, then call functions SDI_InitDMA// and SDI_StartDMA finished the transfer. ////------------------------------------------------------------------------------//2007-07-31: modified some sd write steps to stronger write actionBOOL SDI_BatchWrite_DMA( SD_controller* controller, unsigned long SectorNum, unsigned long SectorCnt, unsigned char* buffer, unsigned long* errorcode ){ unsigned long error = 0; unsigned long timeout; unsigned long DataCtrl = 0; SD_REG *regs;#if (SD_DATA_DEBUG_LEVEL == 1) printk("SDI_BatchWrite_DMA: sector at %ld, len = %ld\n", SectorNum, SectorCnt); printk("%lX------%lX\n", SectorNum * BYTES_PER_SECTOR, (SectorNum + SectorCnt) * BYTES_PER_SECTOR); {}#endif DECLARE_COMPLETION(comp); #if (SD_DATA_DEBUG_LEVEL == 1) SDI_Print_Sector(SectorNum, SectorCnt, buffer);#endif regs = controller->Registers; if (!controller || !buffer) { error = 1; goto write_error_handle; } if (SectorNum >= controller->CardCSD.CardSize / BYTES_PER_SECTOR) { error = 2; goto write_error_handle; } if (!SDI_SendCmd(controller, &CommandParameters[SET_BLOCKLEN], BYTES_PER_SECTOR, 0, &error)) { error = 0; if (!SDI_SendCmd(controller, &CommandParameters[SET_BLOCKLEN], BYTES_PER_SECTOR, 0, &error)) { printk("<1>w: cmd--SET_BLOCKLEN, error--%ld\n", error); error = 3; goto write_error_handle; } } DataCtrl = 0; apBIT_SET(DataCtrl, MCI_DATA_ENABLE,1); apBIT_SET(DataCtrl, MCI_DATA_DIRECTION, apMCI_DATA_TRANSMIT); apBIT_SET(DataCtrl, MCI_DATA_MODE, apMCI_DATA_BLOCKING); apBIT_SET(DataCtrl, MCI_DATA_DMA_ENABLE, 1); apBIT_SET(DataCtrl, MCI_DATA_BLOCKSIZE, BYTES_PER_SECTOR_SH); regs->sd_MASK0 = 0; regs->sd_CLEAR = MCI_STATUS_STATIC_MASK; regs->sd_DATATMR = 0xFFFFFFFF; regs->sd_DATALEN = 0xFFFF; regs->sd_DATACTRL = DataCtrl; if (!SDI_SendCmd(controller, &CommandParameters[WRITE_MULTIPLE_BLOCK], SectorNum * BYTES_PER_SECTOR, 0, &error)) { printk("<1>w1: cmd--WRITE_MULTIPLE_BLOCK, error--%ld\n", error); error = 4; goto write_error_handle; } regs->sd_MASK0 = 0; if (sd_start_dma(0, buffer, SectorCnt * BYTES_PER_SECTOR, &comp) < 0) { printk("<1>sd start dma error\n"); error = 5; goto stop_w_trans_handle; } timeout = wait_for_completion_timeout(&comp, SD_WRITE_DMA_TIMEOUT); if(!timeout){ u32 status; printk("<1>sd write dma timeout,%ld, reset\n", SectorNum); error = 6; set_current_state(TASK_INTERRUPTIBLE); do { status = regs->sd_STATUS; printk("<1>status:%x\n", status); regs->sd_CLEAR = status; if (status & MCI_STATUS_DATAEND) { error = 0; set_current_state(TASK_RUNNING); break; } if (status & (MCI_STATUS_DATACRCFAIL|MCI_STATUS_DATATIMEOUT|MCI_STATUS_TXUNDERRUN|MCI_STATUS_RXOVERRUN)) { set_current_state(TASK_RUNNING); goto stop_w_trans_handle; } schedule_timeout(msecs_to_jiffies(10)); } while (status); } do{ apMCI_sResponse response; response.ShortResponse = 0; if (!SDI_SendCmd(controller, &CommandParameters[SEND_STATUS], RCA, &response, &error)) { printk("<1>w1: cmd--SEND_STATUS, error--%ld\n", error); error = 7; break; } //printk("write resp = %x\n", response.ShortResponse); if (response.ShortResponse & READY_FOR_DATA) break; } while (1); if ((SectorCnt * BYTES_PER_SECTOR) != (0xffff - regs->sd_DATACNT)) { //note: may not be wrong here! //printk("sector at %ld, len = %ld\n", SectorNum, SectorCnt); }stop_w_trans_handle: if (!SDI_SendCmd(controller, &CommandParameters[STOP_TRANSMISSION], SectorNum * BYTES_PER_SECTOR, 0, &error)) { printk("<1>w1: cmd--STOP_TRANSMISSION, error--%ld\n", error); error = 8; }write_error_handle: regs->sd_MASK0 = 0; regs->sd_DATACTRL = 0; regs->sd_CLEAR = MCI_STATUS_STATIC_MASK; if (error) { printk("<1>write error:%ld\n", error); if (errorcode) *errorcode = error; return FALSE; } return TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -