⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmc_main.c

📁 给予mx21处理器的嵌入式系统的mmc卡驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
		#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 + -