📄 mmc_main.c
字号:
#endif if(!filp) { TRACE(" called without filp"); return -EIO; } if(num > g_mmcsd_num) { return -ENODEV; } device = &g_mmcsd_devices[num];//Karen add for MX21 device->port = num; /***************************************************************** * Initialize the device *****************************************************************/ spin_lock(&device->lock); down_interruptible(&(device->sema)); ret = 0; if(device->usage == 0) { /****************************************************** * Initialize Cards ******************************************************/ _MMCSD_64M_MMC_PinConfig(); _MMCSD_InitSDHC(num); ret = _MMCSD_InitMMC(num); if(ret) { FAILED("_MMC_Init error"); goto fail_malloc;// return -1; } ret = _MMCSD_GetInfo(device); // Implement if(ret) { FAILED("_MMCSD_GetInfo error!"); spin_unlock(&device->lock); up(&(device->sema)); goto fail_malloc;// return -1; } ret = _MMCSD_SetSectLen(device); // Implement if(ret) { FAILED(" _MMCSD_SetSectLen error!"); spin_unlock(&device->lock); up(&(device->sema)); goto fail_malloc;// return -1; } device->blksize = MMCSD_MINIMUM_BLK_SIZE; blk_size[major] = kmalloc(sizeof(int), GFP_KERNEL); if (!blk_size[major]) goto fail_malloc; blk_size[major][num] = device->dev_size/1024;/* in KB */ blksize_size[major]= kmalloc(sizeof(int), GFP_KERNEL); if (!blksize_size[major]) goto fail_malloc; blksize_size[major][num] = device->blksize;/* in B*/ hardsect_size[major]=kmalloc(sizeof(int), GFP_KERNEL); if (!hardsect_size[major]) goto fail_malloc; hardsect_size[major][num] = device->blksize;/* in B*/ ret = _MMCSD_SelectDeselectCard(device->card_rca,device->port); if(ret) { FAILED("Select error"); device->card_state = MMCSD_NOTREADY; goto fail_malloc; } /*********************************************************** * Initialize DMA ***********************************************************/#ifdef CONFIG_ARCH_MX1ADS for(channel = 2; channel < 11; channel++) { if((ret = request_dma(channel, "mmc"))==0) { //TRACE("Get Channel %ld",channel); break; } } if(channel >10) goto fail_malloc; device->dma_channel = channel; request_dma_intr(channel,(void *)mmcsd_dma_isr,(void *)mmcsd_dma_err_isr);#endif#ifdef CONFIG_ARCH_MX2ADS if(num == 1) { mx_request_dma(&channel,"mmc1"); (device->dma).callback = (void *)mmcsd_dma_isr_1; } else { mx_request_dma(&channel,"mmc"); (device->dma).callback = (void *)mmcsd_dma_isr; } device->dma_channel = channel;#endif /*********************************************************** * Initialize buff_pool for write operations. **********************************************************/ device->buff_pool[0]=kmalloc(sizeof(u8)*(device->blksize)*MMCSD_MAX_MULTI_BLK, GFP_KERNEL|GFP_DMA);#ifdef MMCSD_DMA_ENDIAN_ERR device->tmp_pool[0]=kmalloc(sizeof(u8)*(device->blksize)*MMCSD_MAX_MULTI_BLK, GFP_KERNEL|GFP_DMA);#endif if(device->buff_pool[0]==NULL) { FAILED("Allocate Buffer failed"); goto fail_malloc; } for(i = 0; i< MMCSD_MAX_MULTI_BLK;i++) { device->buff_pool[i] = device->buff_pool[0]+(device->blksize)*i;#ifdef MMCSD_DMA_ENDIAN_ERR device->tmp_pool[i] = device->tmp_pool[0]+(device->blksize)*i;#endif } device->cur_sec = 0xFFFFFFFF; device->cur_num = 0; device->busy = 0; device->bit_width = 0; _MMCSD_SetClk(MMCSD_HIGH_SPEED,num); /*********************************************************** * Get MBR ***********************************************************/ ret = mmcsd_getMBR(device); if(ret) { FAILED("mmcsd_getMBR error!"); goto fail_malloc; } /*********************************************************** * Detect wether it's read only ***********************************************************/ ret = 0; } (device->usage)++; spin_unlock(&device->lock); up(&(device->sema)); MOD_INC_USE_COUNT; return ret;fail_malloc: if (blk_size[major]) kfree(blk_size[major]); blk_size[major] = NULL; if (blksize_size[major]) kfree(blksize_size[major]); blksize_size[major] = NULL; if (hardsect_size[major]) kfree(hardsect_size[major]); hardsect_size[major] = NULL;#ifdef CONFIG_ARCH_MX1ADS if(device->dma_channel!= 0xFFFFFFFF) free_dma(device->dma_channel);#endif#ifdef CONFIG_ARCH_MX2ADS if(device->dma_channel!= 0xFFFFFFFF) mx_free_dma(device->dma_channel);#endif if(device->buff_pool[0]!=NULL) kfree(device->buff_pool[0]); spin_unlock(&device->lock); up(&(device->sema)); return MMCSD_ERROR;}/****************************************************************************** * Function Name: mmcsd_release * * Input: None. * Value Returned: 0: success; * others failure; * * Description: This routine will release the device. * * Modification History: * 30 DEC,2001, Initial version. Yiwei Zhao *****************************************************************************/static int mmcsd_release(struct inode *inode, struct file *filp){ MMCSD_Dev * device; int num; u32 state; MMCSD_STATUS ret; TRACE("mmcsd_release is called"); /********************************************************************* * Check the device numer *********************************************************************/ num = MINOR(inode->i_rdev); if(num > g_mmcsd_num) { return -ENODEV; } device = &g_mmcsd_devices[num]; /***************************************************************** * Initialize the device *****************************************************************/ spin_lock(&device->lock); down_interruptible(&(device->sema)); (device->usage)--; if(device->usage == 0) { fsync_dev(inode->i_rdev);#ifdef MMCSD_WRITE_DMA mmcsd_dma_write_blks(device);#else mmcsd_write_blks(device);#endif state =MMCSD_TRANSFER; mmcsd_check_status(device,&state); ret = _MMCSD_SelectDeselectCard(0,device->port); if(ret) { TRACE("Select error"); device->card_state = MMCSD_NOTREADY; // g_selected_lock.device = NULL; // spin_unlock(g_selected_lock.lock); }// _MMCSD_StopClk();// Start_Stop_Clk(1); g_selected_lock[0].device = NULL; g_selected_lock[1].device = NULL; #ifdef CONFIG_ARCH_MX1ADS if(device->dma_channel!= 0xFFFFFFFF) free_dma(device->dma_channel);#endif#ifdef CONFIG_ARCH_MX2ADS if(device->dma_channel!= 0xFFFFFFFF) mx_free_dma(device->dma_channel);#endif if(device->buff_pool[0]!=NULL) kfree(device->buff_pool[0]);#ifdef MMCSD_DMA_ENDIAN_ERR if(device->buff_pool[0]!=NULL) kfree(device->buff_pool[0]);#endif } MOD_DEC_USE_COUNT; spin_unlock(&device->lock); up(&(device->sema)); return 0;}/****************************************************************************** * Function Name: mmcsd_locate_device * * Input: * q: the pointer to request structure. * * Value Returned: * NULL: no device structure found; * pointer: to MMCSD_Device structure. * * Description: * this routine will return corresponding MMCSD device structure of the * request. * * Modification History: * 30 DEC,2001, Initial version. Yiwei Zhao *****************************************************************************/static MMCSD_Dev *mmcsd_locate_device(const struct request *req){ int devno; devno = DEVICE_NR(req->rq_dev); if(devno >= g_mmcsd_num) { TRACE("\nmmcsd_locate_device: devno = %d", devno); return NULL; } return(&g_mmcsd_devices[devno]);}/****************************************************************************** * Function Name: mmcsd_request_handler * * Input: * q: the request queue the handler will process * * Value Returned: * NO. * * Description: * This is the request handler for read/write operations. * * Modification History: * 30 DEC,2001, Initial version. Yiwei Zhao *****************************************************************************/void mmcsd_request_handler(request_queue_t * q){ MMCSD_Dev * device; struct request *req; int ret; /*********************************************************************** * Locate the device ***********************************************************************/ device = mmcsd_locate_device(blkdev_entry_next_request(&(q->queue_head))); if(!device) { TRACE(" mmcsd_locate_device error"); return ; } device->busy = 1; /********************************************************************** * process the request quueue. **********************************************************************/ while(!list_empty(&q->queue_head)) { req = blkdev_entry_next_request(&(q->queue_head)); blkdev_dequeue_request(req); spin_unlock_irq(&io_request_lock); down_interruptible(&(device->sema)); do { //TRACE("New Request coming"); ret = mmcsd_data_transfer(device, req); }while(end_that_request_first(req,ret,DEVICE_NAME)); up(&(device->sema)); spin_lock_irq(&io_request_lock); end_that_request_last(req); } device->busy = 0; return ;}/****************************************************************************** * Function Name: mmcsd_data_transfer * * Input: * device: the device that the transfer will take place. * req: the request that will be processed. * * Value Returned: * 1: success. * 0: failure. * * Description: * this routine will be start the read/write transfer. * * Modification History: * 30 DEC,2001, Initial version. Yiwei Zhao *****************************************************************************/static int mmcsd_data_transfer(MMCSD_Dev *device,struct request *req){ int ret; /* Looks good, do the transfer. */ switch(req->cmd) { case READ: ret = mmcsd_read(device, req->buffer, req->sector+device->lba_sec_offset, req->current_nr_sectors); /* if(req->sector ==1) { // For Testing TRACE("Reading TESTING:"); _mmcsd_test_reading_pages(device); } */ if(ret) return 0; else return 1; case WRITE: ret = mmcsd_write(device, req->buffer, (req->sector+device->lba_sec_offset), req->current_nr_sectors); if(ret) return 0; else return 1; default: return 0; }}/****************************************************************************** * Function Name: mmcsd_read * * Input: * device: the device read from * buffer: memory area for I/O transfer. * sector: first sector number; * nr_sector: number of the sectos * * Value Returned: * 0: success. * 1: failure. * * Description: * this routine will read indicated sectors into memory * * Modification History: * 30 DEC,2001, Initial version. Yiwei Zhao *****************************************************************************/static int mmcsd_check_status(MMCSD_Dev *device,u32 *pstate){ MMCSD_STATUS ret = MMCSD_OK; u32 state; int i; state = *pstate; g_mmcsd_cmd[device->port]=MMCSD_CMD13; i = 0xFFFFFFFF; while(i--) { //TRACE("SendStatus... 0x%lx",*mmcsdr_status); ret = _MMCSD_SendStatus(device->card_rca,pstate,device->port); if(ret) // the command failed. { mmcsd_delay(0xFF); //TRACE("Card Status = 0x%08X", *pstate); } else { if(((*pstate)&MMCSD_STATUS_STATE) != state) { mmcsd_delay(0xFF); } else { if(state==MMCSD_TRANSFER) { if(((*pstate)&0x100)==0) continue; } break; } TRACE("state = 0x%lx,request is 0x%lx",(unsigned long)*pstate,(unsigned long)state); } //TRACE("try again..(SendStatus... 0x%lx) %d",*mmcsdr_status,i); } //TRACE("return with %d",ret); return ret;}static int mmcsd_read( MMCSD_Dev *device, char * buffer, u32 sector, u32 nr_sector){ int ret; u32 start_addr,state; start_addr = sector * MMCSD_FS_SECTOR_SIZE; g_selected_lock[device->port].device = device; //TRACE("read from 0x%0lX, number:0x%0lX", sector, nr_sector); state = MMCSD_TRANSFER; ret = mmcsd_check_status(device,&state); if(ret) { FAILED("Check Status failed!"); return 1; } /******************************************************************** * Get the Lock for seclected device *******************************************************************/ ret = _MMCSD_SetBlockLen(MMCSD_MINIMUM_BLK_SIZE,1,device->port); if(ret) { FAILED("Set Block Len failed, ret = 0x%x",ret); return 1; } state = MMCSD_TRANSFER; ret = mmcsd_check_status(device,&state); /******************************************************************** * Begin to Read *******************************************************************/ if((ret=(mmcsd_ReadBlock(device,start_addr, nr_sector, buffer)))!=MMCSD_OK) { TRACE(" ReadBlock error"); device->card_state = MMCSD_NOTREADY; //g_selected_lock.device = NULL; //spin_unlock(g_selected_lock.lock); return 1; } device->card_state = MMCSD_STANDBY; return 0;}/****************************************************************************** * Function Name: mmcsd_write * * Input: * device: the device write to * buffer: memory area for I/O transfer.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -