📄 mmc_main.c
字号:
* sector: first sector number; * nr_sector: number of the sectos * * Value Returned: * 0: success. * 1: failure. * * Description: * this routine will write data into indicated sectors. * * Modification History: * 30 DEC,2001, Initial version. Yiwei Zhao *****************************************************************************/static int mmcsd_write( MMCSD_Dev *device, char * buffer, u32 sector, u32 nr_sector){ int ret; u32 i; TRACE(" write to 0x%lx, number:0x%lx", (unsigned long)sector, (unsigned long)nr_sector); for(i = 0; i < nr_sector; i++) { if(sector == (device->cur_sec+1)) { /* device->buff_pool[device->cur_num]=kmalloc(sizeof(UINT8)*device->blksize, GFP_KERNEL); if(device->buff_pool[device->cur_num] == NULL) { FAILED("No Kernel Space"); return MMCSD_ERROR; } */// TRACE("add into buffer pool");#ifdef MMCSD_DMA_ENDIAN_ERR _mmcsd_cp_16_little_2_big(buffer, //src device->tmp_pool[device->cur_num], // target device->blksize);#else memcpy(device->buff_pool[device->cur_num], buffer, device->blksize);#endif if(device->cur_num == 0) { device->addr = sector*(device->blksize); } device->cur_num++; device->cur_sec++; sector++; if(device->cur_num == MMCSD_MAX_MULTI_BLK) { // If the pool is full // TRACE("The Pool is Full...");#ifdef MMCSD_WRITE_DMA ret = mmcsd_dma_write_blks(device);#else ret = mmcsd_write_blks(device);#endif if(ret != MMCSD_OK) { FAILED("mmcsd_write_blk failed"); return ret; } // cur_num should be zero } } else { if(i!=0) { FAILED("Error!"); return MMCSD_ERROR; } //TRACE("Another Blk");#ifdef MMCSD_WRITE_DMA ret = mmcsd_dma_write_blks(device); // if the blk is not continous.#else ret = mmcsd_write_blks(device); // if the blk is not continous.#endif if(ret != MMCSD_OK) { FAILED("mmcsd_write_blk failed"); return ret; } i--; // i == 0 device->cur_sec = sector-1; } } if( i == nr_sector) { return MMCSD_OK; } return MMCSD_ERROR;}MMCSD_STATUS mmcsd_write_blks(MMCSD_Dev *device){ int i,t,j,counter; u32 state,ret,ret2,int_mask, temp32; u16 temp16,*p16; u32 addr; u32 burst_len=8; if(device->cur_num == 0) { mmcsd_free_buffer(device); return MMCSD_OK; } ret=ret2=MMCSD_OK; TRACE("enter mmcsd_write_blks....."); g_selected_lock[device->port].device = device; /************************************************************** * Check the Card Status **************************************************************/ state =MMCSD_TRANSFER; ret = mmcsd_check_status(device,&state); if(ret) { mmcsd_free_buffer(device); return ret; } /************************************************************** * Mask Interrupt **************************************************************/ TRACE("Disable Interrupt.."); _MMCSD_Mask_interrupt(0x7F,&int_mask,device->port); /** * End of Testing */ /************************************************************** * Set Block Length **************************************************************/ i = 5; while(i--) { ret = _MMCSD_SetBlockLen(MMCSD_MINIMUM_BLK_SIZE,device->cur_num,device->port); if(ret) { TRACE("3)Set Block Len, ret = 0x%lx,state=%lx",(unsigned long)ret,(unsigned long)state); TRACE("4)Try again...%d",i); state = MMCSD_TRANSFER; mmcsd_check_status(device,&state); } else //ret == SUCCESS! { break; } } if(ret) { mmcsd_free_buffer(device); FAILED("5)Set Blocked Len Failed!"); return ret; } /******************************************************************** * Begin to write *******************************************************************/ addr = device->addr; TRACE("6)address is 0x%lx (sector 0x%lx),blk number is %ld", (unsigned long)addr,(unsigned long)(addr/512),(unsigned long)(device->cur_num)); _MMCSD_StopClk(device->port); if(device->cur_num == 1) { if(device->bit_width == 0) { _MMCSD_SetCmd(MMCSD_CMD24,addr,MMCSDB_DATEN|MMCSDB_R1|MMCSDB_WRRD,device->port); burst_len = 8; } else { _MMCSD_SetCmd(MMCSD_CMD24,addr,MMCSD_BUS_4BIT|MMCSDB_DATEN|MMCSDB_R1|MMCSDB_WRRD,device->port); burst_len = 32; } g_mmcsd_cmd[device->port] = MMCSD_CMD24; } else { if(device->bit_width == 0) { _MMCSD_SetCmd(MMCSD_CMD25,addr,MMCSDB_DATEN|MMCSDB_R1|MMCSDB_WRRD,device->port); burst_len = 8; } else { _MMCSD_SetCmd(MMCSD_CMD25,addr,MMCSD_BUS_4BIT|MMCSDB_DATEN|MMCSDB_R1|MMCSDB_WRRD,device->port); burst_len = 32; } g_mmcsd_cmd[device->port] = MMCSD_CMD25; } _MMCSD_StartClk(device->port); ret = MMCSD_OK; for( t=0; t<device->cur_num; t++) { counter = 0;#ifdef MMCSD_DMA_ENDIAN_ERR p16 = (u16 *)device->tmp_pool[t];#else p16 = (u16 *)device->buff_pool[t];#endif while(ret == MMCSD_OK) { if(device->port == 1) g_mmcsd_status = (mmcsdr_status_2); else g_mmcsd_status = (mmcsdr_status); if((g_mmcsd_status&0x1043)==0) { continue; } j = 0xFF; while(j--);// TRACE("g_mmcsd_status = 0x%x",g_mmcsd_status);// if(g_mmcsd_status&0x0003) { TRACE("7)ERROR!--, g_mmcsd_status = %lx",(unsigned long)g_mmcsd_status); ret = MMCSD_ERROR; } else if((g_mmcsd_status&0x0040)!=0) // Buffer is empty {// TRACE("FIFO is empty!"); for(i = 0; i < burst_len; i++) { temp16 = (*p16); temp32 = temp16; if(device->port == 1) mmcsdr_buffer_access_2 = temp32; else mmcsdr_buffer_access = temp32; p16++; } counter += burst_len*2; } if(counter == device->blksize) { break; } } if(ret!=MMCSD_OK) break; } /******************************************************* * Write Done *******************************************************/ if(ret==MMCSD_OK) { while(1) { if(device->port == 1) g_mmcsd_status = mmcsdr_status_2; else g_mmcsd_status = mmcsdr_status; if(g_mmcsd_status&0x0007) { TRACE("8)ERROR! status = 0x%lx",(unsigned long)g_mmcsd_status); ret = MMCSD_ERROR; break; } else if((g_mmcsd_status&0x1000)!=0) { TRACE("9)Write Done! g_mmcsd_status = 0x%lx",(unsigned long)g_mmcsd_status); ret = MMCSD_OK; break; } TRACE("10)g_mmcsd_status = %lx",(unsigned long)g_mmcsd_status); } } TRACE("Enable Intr..."); _MMCSD_Restore_Mask(int_mask,device->port); g_mmcsd_cmd[device->port] = 0; if(device->cur_num>1) { ret2=_MMCSD_NoDataCommand(MMCSD_CMD12,device->card_rca<<16,MMCSDB_R1,device->port); }// state =MMCSD_TRANSFER;// mmcsd_check_status(device,&state); mmcsd_free_buffer(device); TRACE("15)return with ret = %lx,ret2 = %lx",(unsigned long)ret,(unsigned long)ret2); return(ret|ret2);}MMCSD_STATUS mmcsd_dma_write_blks(MMCSD_Dev *device){ int i,timeleft; u32 state,ret,ret2,int_mask = 0xFFFFFFFF; u32 addr; u32 status,counter; if(device->cur_num == 0) { mmcsd_free_buffer(device); return MMCSD_OK; } ret=ret2=MMCSD_OK; g_selected_lock[device->port].device = device; /************************************************************** * Check the Card Status **************************************************************/ //TRACE("Check Status"); state =MMCSD_TRANSFER; ret = mmcsd_check_status(device,&state); if(ret) { mmcsd_free_buffer(device); FAILED("2)Check Error!"); return ret; } /** * End of Testing****************************************************************** */ /************************************************************** * Set Block Length **************************************************************/ i = 5; while(i--) { // TRACE("Set Block Length"); ret = _MMCSD_SetBlockLen(MMCSD_MINIMUM_BLK_SIZE,device->cur_num,device->port); if(ret) { TRACE("3)Set Block Len, ret = 0x%lx,state=%lx",(unsigned long)ret,(unsigned long)state); TRACE("4)Try again...%d",i); state = MMCSD_TRANSFER; mmcsd_check_status(device,&state); } else //ret == SUCCESS! { break; } } if(ret) { mmcsd_free_buffer(device); FAILED("5)Set Blocked Len Failed!"); goto dma_write_end; } state = MMCSD_TRANSFER; ret = mmcsd_check_status(device,&state); if(ret) { mmcsd_free_buffer(device); FAILED("Check Status failed."); goto dma_write_end; } i = 10; while(i--) { } if(ret) { mmcsd_free_buffer(device); FAILED("Set Bus Width Failed!"); goto dma_write_end; } /******************************************************************** * Begin to write *******************************************************************/ addr = device->addr; //TRACE("6)address is 0x%lx(sector 0x%lx, %ld),blk number is %ld", // addr,addr/512,addr/512,device->cur_num); /************************************************************** * Mask Interrupt **************************************************************/ //TRACE("Disable Interrupt"); _MMCSD_Mask_interrupt(0x78,&int_mask,device->port); /* * DMA Preparation */ /************************************************************** * Config DMA **************************************************************/// TRACE("DMA Configuration"); ret = mmcsd_DmaStartTransfer(device,#ifdef MMCSD_DMA_ENDIAN_ERR device->tmp_pool[0],#else device->buff_pool[0],#endif MMCSD_MINIMUM_BLK_SIZE*(device->cur_num), MMCSD_WRITE, device->bit_width); if(ret != MMCSD_OK) { FAILED("mmcsd_DmaStartTransfer failed"); goto dma_write_end; } /************************************************************** * Set Command **************************************************************/ state =MMCSD_TRANSFER; ret = mmcsd_check_status(device,&state); if(ret) { FAILED("Check Status failed."); } // TRACE("Set Command (24/25)"); _MMCSD_StopClk(device->port); if(device->cur_num == 1) { if(device->bit_width == 0) { _MMCSD_SetCmd(MMCSD_CMD24,addr,MMCSDB_DATEN|MMCSDB_R1|MMCSDB_WRRD,device->port); } else { _MMCSD_SetCmd(MMCSD_CMD24,addr,MMCSD_BUS_4BIT|MMCSDB_DATEN|MMCSDB_R1|MMCSDB_WRRD,device->port); } } else { if(device->bit_width == 0) { _MMCSD_SetCmd(MMCSD_CMD25,addr,MMCSDB_DATEN|MMCSDB_R1|MMCSDB_WRRD,device->port); } else { _MMCSD_SetCmd(MMCSD_CMD25,addr,MMCSD_BUS_4BIT|MMCSDB_DATEN|MMCSDB_R1|MMCSDB_WRRD,device->port); } }// TRACE("Start Clk... Wait CMD Done."); ret = MMCSD_OK; _MMCSD_StartClk(device->port); //if((ret=_MMCSD_irq_WaitUntil(MMCSD_CMD_DONE,MMCSD_CMD25,100))!=0) if((ret=_MMCSD_WaitUntil(MMCSD_CMD_DONE,device->port))!=MMCSD_OK) { FAILED("WaitCMDDone ret 0x%lx",(unsigned long)ret); goto dma_write_end; } if(device->port == 1) g_mmcsd_status = mmcsdr_status_2; else g_mmcsd_status = mmcsdr_status; if((g_mmcsd_status&0x40)==0) { FAILED("FIFO is not empty 0x%lx",(unsigned long)ret); goto dma_write_end; } /************************************************************** * Enable DMA **************************************************************/// TRACE("Enable DMA..");// _MMCSD_StartClk(); g_mmcsd_cmd[device->port] = 0xFF;#ifdef CONFIG_ARCH_MX1ADS enable_dma(device->dma_channel);#endif#ifdef CONFIG_ARCH_MX2ADS mx_dma_start(device->dma_channel);#endif timeleft = interruptible_sleep_on_timeout(&(device->select_wait),100); if(!timeleft) { FAILED("write failed, Timeout!"); #ifdef CONFIG_ARCH_MX1ADS disable_dma(device->dma_channel); #endif #ifdef CONFIG_ARCH_MX2ADS _reg_DMA_CCR(device->dma_channel) &= 0xFFFFFFFE; #endif g_mmcsd_cmd[device->port] = 0x0; ret = MMCSD_ERROR; goto dma_write_end; }#ifdef CONFIG_ARCH_MX1ADS disable_dma(device->dma_channel);#endif#ifdef CONFIG_ARCH_MX2ADS _reg_DMA_CCR(device->dma_channel) &= 0xFFFFFFFE; #endif g_mmcsd_cmd[device->port] = 0x0;// TRACE("Waked up "); status = device->result;// TRACE("waked up! status = %lx",status); counter = 0xFFFF; while(counter--) { if(device->port == 1) g_mmcsd_status = mmcsdr_status_2; else g_mmcsd_status = mmcsdr_status; TRACE("g_mmcsd_status is 0x%0lX (for TRANS-DONE)",(unsigned long)g_mmcsd_status); if((g_mmcsd_status&0x1007)==0) { mmcsd_delay(0xFFFF); continue; } if(g_mmcsd_status&0x0007) { ret = MMCSD_ERROR; FAILED("status is 0x%lx",(unsigned long)g_mmcsd_status); goto dma_write_end; } ret = MMCSD_OK; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -