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

📄 mmc_media.c

📁 spi driver for sd /mmc card
💻 C
📖 第 1 页 / 共 2 页
字号:
				dev = mmc_media_locate_device(CURRENT);		if ( !dev ) {			end_request(0);			continue;		}		DEBUG(2," (%p): cmd %i sec %li (nr. %li)\n", CURRENT,		      CURRENT->cmd, CURRENT->sector, CURRENT->current_nr_sectors);		if ( mmc_media_transfer(dev,CURRENT) ) {			g_busy = 1;			return;		}		end_request(0);  /* There was a problem with the request */	}}void mmc_media_transfer_done( struct mmc_io_request *trans, int result ){	unsigned long flags;	int nsect,nr_sectors;	struct request *req = CURRENT;	struct buffer_head *bh = req->bh, *next;	unsigned char *data = (unsigned char *)bh_pages;			DEBUG(3,": result=%d\n", result);	spin_lock_irqsave(&io_request_lock, flags);	nr_sectors = trans->nr_sectors;	for (;;)	{	    if ((req->cmd == READ) && data)	    {		memcpy(bh->b_data,data,bh->b_size);		data += bh->b_size;            }	    if (!(next = bh->b_reqnext)) break;	    if (!(nr_sectors - (next->b_size >> 9))) break;	    nsect = bh->b_size >> 9;	    blk_finished_io(nsect);	    bh->b_reqnext = NULL;	    bh->b_end_io(bh,result);	    req->bh = bh = next;	    next = bh->b_reqnext;	    req->hard_sector += nsect;	    req->hard_nr_sectors -= nsect;	    req->sector = req->hard_sector;	    req->nr_sectors = req->hard_nr_sectors;	    req->current_nr_sectors = bh->b_size >> 9;	    req->hard_cur_sectors = req->current_nr_sectors;	    if (req->nr_sectors < req->current_nr_sectors) {		    req->nr_sectors = req->current_nr_sectors;		    printk("end_request:buffer-list destroyed\n");	    }	    req->buffer = bh->b_data;	    nr_sectors -= nsect;	}//#ifdef CONFIG_ARCH_EZX_E680	/* add by w20598 */	if (!mmc_slot_enable)	    if (MMC_IO_READ == trans->cmd)	        end_request(0);	    else	        end_request(1);	else	/* add end */ //#endif	    end_request(result);	g_busy = 0;	if (!QUEUE_EMPTY)		mmc_media_request(NULL);  // Start the next transfer	spin_unlock_irqrestore(&io_request_lock, flags);}static struct block_device_operations mmc_bdops = {	open:               mmc_media_open,	release:            mmc_media_release,	ioctl:              mmc_media_ioctl,	check_media_change: mmc_media_check_change,	revalidate:         mmc_media_revalidate};//#ifdef CONFIG_ARCH_EZX_E680/*********************************************************************//* add by w20598 for hotplug support                                 *//* if user unplugs the card, driver will prevent from flushing datas *//* create a new inferface to set driver enable                       *//*********************************************************************//*******************************************************************************  * Function name:	mmcsysif_open  * Arguments:		struct inode *  *			struct file *  * Return:		int : 0  for successful,  *			      negative number signaling a error  * Comments:	open operation  *******************************************************************************/static int mmcsysif_open(struct inode * inode, struct file * file){         DEBUG(2,": mmcsysif_usage=%d\n", mmcsysif_usage);	 	 if (mmcsysif_usage > 2)	     return -1;	     	 mmcsysif_usage++;	          return 0;}/*******************************************************************************  * Function name:	mmcsysif_release  * Arguments:		struct inode *  *			struct file *  * Return:		int  : 0  for successful,  *			       negative number signaling a error  * Comments:	release operation  *******************************************************************************/static int mmcsysif_release(struct inode * inode, struct file * file){        if (mmcsysif_usage > 2)	    return -1;	    	mmcsysif_usage--;		DEBUG(2,": mmcsysif_usage=%d\n", mmcsysif_usage);        return 0;}/* ioctl for tcmd. ap_tcmd can run as ezx user */static int mmcsysif_ioctl_ext(unsigned int cmd, unsigned long arg){        int num = 0;        struct mmc_media_dev *dev;        struct mmc_slot *slot;        unsigned long status;	dev     = &g_media_dev[num];	if (dev->slot == NULL)		return -ENODEV;	slot    = g_media_dev[num].slot;	switch(cmd) {	case IOCMMCGETSIZE:	    if (!access_ok(VERIFY_WRITE, arg, sizeof(long)))                return -EFAULT;            return put_user(dev->nr_sects * dev->read_block_len, (long *)arg);	    	case IOCMMCGETCARDCID:	    if (!access_ok(VERIFY_WRITE, arg, sizeof(struct mmc_cid)))                return -EFAULT;            if (copy_to_user ((void *) arg, &(slot->cid), sizeof(struct mmc_cid)))                return -EFAULT;            return 0;			case IOCMMCGETCARDCSD:	    if (!access_ok(VERIFY_WRITE, arg, sizeof(struct mmc_csd)))                return -EFAULT;            if (copy_to_user ((void *) arg, &(slot->csd), sizeof(struct mmc_csd)))                return -EFAULT;            return 0;			case IOCMMCGETCARDSTATUS:            if (!access_ok(VERIFY_WRITE, arg, sizeof(int)))                return -EFAULT;            status = 0;            if (slot->dev->sdrive->is_wp && slot->dev->sdrive->is_wp(num))                status |= 0x1;            if (copy_to_user((void*) arg, & status, sizeof(unsigned long)))                return -EFAULT;            return 0;     			case IOCMMCGETCARDTYPE:	    if (!access_ok(VERIFY_WRITE, arg, sizeof(long)))                        return -EFAULT;            return put_user(g_media_dev[num].slot->sd,(long *)arg);			default:	      break;	}        return -ENOTTY; }static int mmcsysif_ioctl(struct inode *inode, struct file *filp,                 unsigned int cmd, unsigned long arg){	DEBUG(2," ioctl 0x%x 0x%lx\n", cmd, arg);	switch(cmd) {	case IOCMMCSETENABLE:		if (!access_ok(VERIFY_WRITE, arg, sizeof(long)))			return -EFAULT;                if (mmc_slot_enable)		{		    DEBUG(3, "slot%d is already enable.\n",arg);		    return 0;		}					DEBUG(3, "set slot%d enable\n",arg);		mmc_slot_enable = 1;		return 0;	case IOCSETERROR:		panicdev = (unsigned short)MKDEV(mmc_major,1);		complete(&fatpanic_completion);		return 0;	case IOCMMCEXIST:		if (!access_ok(VERIFY_WRITE, arg, sizeof(long)))			return -EFAULT;		#ifdef CONFIG_ARCH_EZX_A780		return put_user(( GPLR(GPIO_MMC_DATA3) & GPIO_bit(GPIO_MMC_DATA3)),(long *)arg);#else        return put_user(( GPLR(GPIO_MMC_DETECT) & GPIO_bit(GPIO_MMC_DETECT)),(long *)arg);#endif	case IOCMMCGETSIZE:	case IOCMMCGETCARDCID:	case IOCMMCGETCARDCSD:	case IOCMMCGETCARDSTATUS:	case IOCMMCGETCARDTYPE:	     return mmcsysif_ioctl_ext(cmd,arg);	default:	      break;	}	return -ENOTTY; /* should never get here */}static ssize_t mmcsysif_read(struct file * filp, char * buf, size_t count, loff_t *ppos){    panicdev = 0;    init_completion(&fatpanic_completion);    wait_for_completion(&fatpanic_completion);    if (!copy_to_user(buf,kdevname((kdev_t) panicdev),5))	return 0;    return -1; /* error */	}static struct file_operations mmcsysif_bdops = {       ioctl:      mmcsysif_ioctl,       open:       mmcsysif_open,       read:      mmcsysif_read,       release:    mmcsysif_release};//#endif/******************************************************************//* TODO:   We have a race condition if two slots need to be revalidated at the same   time.  Perhaps we should walk the list of devices and look for change   flags?*/static void mmc_media_load_task_handler( void *nr ){	int slot_id = (int) nr;	DEBUG(2," slot_id=%d\n", slot_id );	mmc_media_revalidate(MKDEV(mmc_major,(slot_id<<MMC_SHIFT)));}static struct tq_struct mmc_media_load_task = {	routine:  mmc_media_load_task_handler};static void mmc_media_load( struct mmc_slot *slot ){	unsigned long flags;	struct mmc_media_dev *dev  = &g_media_dev[slot->id];	int i;	long nr_sects;	int  write_block_len;	int  read_block_len;	spin_lock_irqsave(&dev->lock, flags);	nr_sects        = (1 + slot->csd.c_size) * (1 << (slot->csd.c_size_mult + 2));	write_block_len = 1 << slot->csd.write_bl_len;	read_block_len  = 1 << slot->csd.read_bl_len;	MOD_INC_USE_COUNT;	DEBUG(1, " slot=%p nr_sect=%ld write_block_length=%d read_block_len=%d\n", 	      slot, nr_sects, write_block_len, read_block_len );	dev->slot            = slot;	dev->nr_sects        = nr_sects;	dev->read_block_len  = read_block_len;	dev->write_block_len = write_block_len;	dev->changed         = 1;	mmc_gendisk.nr_real++;	/* Fix up the block size to match read_block_len */	/* TODO: can we really do this?  Right now we're affecting blksize_size and hardsect_size */	for ( i = 0 ; i < (1 << MMC_SHIFT) ; i++ )		mmc_blk[(slot->id << MMC_SHIFT) + i] = read_block_len;	mmc_media_load_task.data = (void *) slot->id;	schedule_task( &mmc_media_load_task );	spin_unlock_irqrestore(&dev->lock, flags);}/* TODO: This is a problem area.  We've lost our card, so we'd like   to flush all outstanding buffers and requests, remove the partitions from   the file system, and generally shut everything down.*/static void mmc_media_unload( struct mmc_slot *slot ){	unsigned long flags;	struct mmc_media_dev *dev = &g_media_dev[slot->id];	spin_lock_irqsave(&dev->lock, flags);//	for ( i = 0 ; i < MMC_SHIFT ; i++ )//		fsync_dev(MKDEV(mmc_major,slot->id,i));	MOD_DEC_USE_COUNT;	DEBUG(1," slot=%p id=%d\n", slot, slot->id);	dev->slot            = NULL;	dev->nr_sects        = 0;	dev->changed         = 1;	mmc_gendisk.nr_real--;	mmc_media_load_task.data = (void *) slot->id;	schedule_task( &mmc_media_load_task );	spin_unlock_irqrestore(&dev->lock, flags);}/*    Called once the device has a valid CSD structure   In the future this should determine what type of card we have   For the moment, everything is a memory card */static int mmc_media_probe( struct mmc_slot *slot ){	return 1;}static struct mmc_media_driver mmc_driver = {	name:            "flash",	load:            mmc_media_load,	unload:          mmc_media_unload,	probe:           mmc_media_probe,	io_request_done: mmc_media_transfer_done,};/******************************************************************/static int __init mmc_media_init( void ){	int i, result,order;	DEBUG(0,"Init MMC media\n");	#ifdef CONFIG_DEVFS_FS	mmc_devfs_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL);	if (!mmc_devfs_handle) return -EBUSY;	result = devfs_register_blkdev(mmc_major, DEVICE_NAME, &mmc_bdops);#else        result = register_blkdev(mmc_major, DEVICE_NAME, &mmc_bdops);	#endif		if (result < 0) {		printk(KERN_WARNING "Unable to get major %d for MMC media\n", mmc_major);		return result;	}	if ( !mmc_major ) mmc_major = result;	DEBUG(3, "register block device /dev/%s* layer with major %d\n",	      DEVICE_NAME, mmc_major);//#ifdef CONFIG_ARCH_EZX_E680/* add by w20598 for mmcsysif */#ifdef CONFIG_DEVFS_FS	mmcsysif_de = devfs_register(NULL,"midicomm",DEVFS_FL_AUTO_DEVNUM,								0, 0, S_IFCHR | S_IRUGO | S_IWUGO,								&mmcsysif_bdops,NULL);	if( NULL == mmcsysif_de)		DEBUG(0,":devfs_register mmcsysif failed");#else	result = register_chrdev(mmcsysif_major, "mmcsysif", &mmcsysif_bdops);	if (result < 0)	{		DEBUG(0," :mmcsysif can not get major %d",mmcsysif_major);		return result;	}	if( 0 == mmcsysif_major)	{		mmcsysif_major = result;		DEBUG(2," :mmcsysif:mmcsysif_major = %d",mmcsysif_major);	}	DEBUG(2,": register mmcsysif success. major = %d",mmcsysif_major);#endif/* add end *///#endif	/* Set up global block arrays */	read_ahead[mmc_major]    = rahead;	for(i=0 ; i < MMC_NDISK; i++)		mmc_blk[i] = 512;	hardsect_size[mmc_major] = mmc_blk;	for(i=0; i < MMC_NDISK; i++)		mmc_max[i] = maxsectors;	max_sectors[mmc_major]   = mmc_max;	/* Start with zero-sized partitions : we'll fix this later */	memset(mmc_sizes, 0, sizeof(int) * MMC_NDISK);	blk_size[mmc_major] = mmc_sizes;	/* Fix up the gendisk structure */	mmc_gendisk.part    = mmc_partitions;	mmc_gendisk.sizes   = mmc_sizes;	mmc_gendisk.nr_real = 0;	#ifdef CONFIG_DEVFS_FS	mmc_gendisk.de_arr  = &mmc_devfs_handle;#endif		mmc_gendisk.flags   = &mmc_gendisk_flags;	mmc_gendisk.fops    = &mmc_bdops;	/* Add ourselves to the global list */	mmc_gendisk.major = mmc_major;	add_gendisk(&mmc_gendisk);	order = 0;	while (maxsectors > (1<< (order + 2))) order++;	bh_pages = __get_free_pages(GFP_KERNEL,order);		blk_init_queue(BLK_DEFAULT_QUEUE(mmc_major), DEVICE_REQUEST);	return mmc_register_media_driver(&mmc_driver);}static void mmc_media_cleanup( void ){	int i,order;	DEBUG(0,"\n");	flush_scheduled_tasks();	unregister_blkdev(mmc_major, DEVICE_NAME);	for ( i = 0 ; i < MMC_NDISK; i++ )		fsync_dev(MKDEV(mmc_major,i));	mmc_unregister_media_driver(&mmc_driver);	blk_cleanup_queue(BLK_DEFAULT_QUEUE(mmc_major));	blk_size[mmc_major]      = NULL;	hardsect_size[mmc_major] = NULL;	max_sectors[mmc_major]   = NULL;	del_gendisk(&mmc_gendisk);	order = 0;	while (maxsectors > (1<< (order + 2))) order++;	if (bh_pages) free_pages(bh_pages,order);//#ifdef CONFIG_ARCH_EZX_E680	/* add by w20598 */#ifdef CONFIG_DEVFS_FS	devfs_unregister(mmcsysif_de);#else	unregister_chrdev(mmcsysif_major,"mmcsysif");#endif        DEBUG(3,":mmcsysif quit");/* add end *///#endif#ifdef CONFIG_DEVFS_FS	devfs_unregister(mmc_devfs_handle);#endif	}struct mmc_media_module media_module = {	init:    mmc_media_init,	cleanup: mmc_media_cleanup};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -