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

📄 mmc_block.c

📁 linux下mmc_sd卡的驱动.rar
💻 C
📖 第 1 页 / 共 2 页
字号:
		goto out;			} else {		card = mmc_get_card( host, slot );		if ( !card ) {			MMC_DEBUG( MMC_DEBUG_LEVEL2, "failed to get card: "					"host=%d, slot=%d\n", host, slot );			__mmc_block_wrunlock_devices();			goto error;		}		dev->card = card;	}	__mmc_block_wrunlock_devices(); 	/* FIXME */	__mmc_block_rdlock_devices(); /* handle the request for sector 0 */	grok_partitions( &mmc_block_gendisk, MINOR( start ),			 mmc_block_gendisk.max_p,			 card->info.capacity>>9 /* sectors */		       );	__mmc_block_rdunlock_devices();	/* FIXME */	__mmc_block_wrlock_devices();	for ( i = start + mmc_block_gendisk.max_p - 1; i >= 0; --i ) {		int minor = MINOR( i );				dev = &mmc_block_device[minor];		if ( mmc_block_gendisk.part[minor].nr_sects > 0 )			dev->card = card;	}	__mmc_block_wrunlock_devices();out:error:	__LEAVE( "ret=%d", ret );	return ret;}static void mmc_block_handle_request( void ){	struct request *request;	mmc_block_device_t dev;	mmc_card_t card;	char *buf;	loff_t pos;	unsigned int result = 0;	for (;;) {		int minor;				INIT_REQUEST;		request = CURRENT;		spin_unlock_irq( &io_request_lock );				minor = MINOR( request->rq_dev );		dev = __mmc_block_get_device( request->rq_dev );		if ( !dev ) {			MMC_DEBUG( MMC_DEBUG_LEVEL2, "invalid device (%x:%x)\n",					MAJOR( request->rq_dev ), minor );							goto end_req;		}				card = dev->card;		(void)__mmc_block_put_device( dev );				MMC_DEBUG( MMC_DEBUG_LEVEL2, //		printk( KERN_INFO __FUNCTION__"(): "				"request %p: cmd %i sec %li (nr. %li)\n", 				CURRENT, CURRENT->cmd, CURRENT->sector, 				CURRENT->current_nr_sectors );				if ( request->current_nr_sectors >				mmc_block_gendisk.part[minor].nr_sects )			goto end_req;				// Handle the request		// TODO: handle clusterred requests in multiple block transfer mode 		buf = request->buffer;		pos = (mmc_block_gendisk.part[minor].start_sect +			request->sector) * MMC_BLOCK_SECT_SIZE;				switch ( request->cmd )		{			int i, ret;						case READ:#if 0				ret = mmc_read( card, 					(request->current_nr_sectors > 1) ?					MMC_TRANSFER_MODE_BLOCK_MULTIPLE :					MMC_TRANSFER_MODE_BLOCK_SINGLE,					buf, 					request->current_nr_sectors 					     * MMC_BLOCK_SECT_SIZE, /* FIXME */					&pos );				if ( ret < 0 ) 					goto end_req;				#else				for ( i = 0;				      i < request->current_nr_sectors;				      i++ ) {					ret = mmc_read( card,						MMC_TRANSFER_MODE_BLOCK_SINGLE,						buf,						MMC_BLOCK_SECT_SIZE, /* FIXME */						&pos );					if ( ret < 0 )						goto end_req;					else						buf += ret;				}#endif				result = 1;				break;			case WRITE:			// TODO: Read only device#if 0				ret = mmc_write( card, 					(request->current_nr_sectors > 1) ?					MMC_TRANSFER_MODE_BLOCK_MULTIPLE :					MMC_TRANSFER_MODE_BLOCK_SINGLE,					buf, 					request->current_nr_sectors 					    * MMC_BLOCK_SECT_SIZE, /* FIXME */					&pos );				if ( ret < 0 ) 					goto end_req;				#else				for ( i = 0;				      i < request->current_nr_sectors;				      i++ ) {					ret = mmc_write( card,						MMC_TRANSFER_MODE_BLOCK_SINGLE,						buf,						MMC_BLOCK_SECT_SIZE, /* FIXME */						&pos ); 					if ( ret < 0 )						goto end_req;					else						buf += ret;				}#endif				result = 1;				break;		}end_req:		__LEAVE( "result=%d", result );		spin_lock_irq( &io_request_lock );		end_request( result );	}}static volatile int leaving = 0;static DECLARE_MUTEX_LOCKED( thread_sem );static DECLARE_WAIT_QUEUE_HEAD( thr_wq );static pid_t thr_id = -1;int mmc_block_thread( void *arg ){	struct task_struct *task = current;	DECLARE_WAITQUEUE(wait, task);	__ENTER0();		task->session = 1;	task->pgrp = 1;	task->flags |= PF_MEMALLOC;	strcpy( task->comm, "mmcblockd" );	task->tty = NULL;	spin_lock_irq( &task->sigmask_lock );	sigfillset( &task->blocked );	recalc_sigpending( task );	spin_unlock_irq( &task->sigmask_lock );	exit_mm( task );	exit_files( task );	exit_sighand( task );	exit_fs( task );	while ( !leaving ) {		add_wait_queue( &thr_wq, &wait);		set_current_state( TASK_INTERRUPTIBLE );		spin_lock_irq( &io_request_lock );		if ( QUEUE_EMPTY || QUEUE_PLUGGED ) {			spin_unlock_irq( &io_request_lock );			schedule();			remove_wait_queue( &thr_wq, &wait ); 		} else {			remove_wait_queue( &thr_wq, &wait ); 			set_current_state( TASK_RUNNING );			mmc_block_handle_request(); /* handle the request */			spin_unlock_irq( &io_request_lock );		}	}	up( &thread_sem );		__LEAVE0();	return 0;}#if LINUX_VERSION_CODE < 0x20300#define RQFUNC_ARG void#else#define RQFUNC_ARG request_queue_t *q#endifstatic void mmc_block_request( RQFUNC_ARG ){	wake_up( &thr_wq );}static int mmc_block_ioctl( struct inode * inode, struct file * file,		      unsigned int cmd, unsigned long arg ){	int ret = -ENODEV;	mmc_block_device_t dev;	mmc_card_t card;	int minor;	__ENTER0();		if ( !inode || !file ) {		ret = -EINVAL;		goto error;	}	minor = MINOR( inode->i_rdev );		dev = __mmc_block_get_device( inode->i_rdev );	if ( !dev ) {		MMC_DEBUG( MMC_DEBUG_LEVEL0, "invalid device\n" );		goto error;	}		card = dev->card; 	__mmc_block_put_device( dev );		switch ( cmd ) {	case BLKGETSIZE:   /* Return device size */		{			unsigned long value;						__mmc_block_rdlock_devices();			value = mmc_block_gendisk.part[minor].nr_sects;			__mmc_block_rdunlock_devices();						if ( put_user( value, (unsigned long *) arg) ) {				ret = -EFAULT;				goto error;			}		}		break;#ifdef BLKGETSIZE64	case BLKGETSIZE64:		{			unsigned long value;						__mmc_block_rdlock_devices();			value = mmc_block_gendisk.part[minor].nr_sects;			__mmc_block_rdunlock_devices();						if ( put_user( (u64)value, (u64 *) arg) ) {				ret = -EFAULT;				goto error;			}		}		break;#endif	case HDIO_GETGEO:		{			struct hd_geometry geo;						ret = !access_ok( VERIFY_WRITE, arg, sizeof( geo ) );			if ( ret ) {				ret = -EFAULT;				goto error;			}			geo.heads = 1;			geo.sectors = 1;			__mmc_block_rdlock_devices();			geo.cylinders = mmc_block_gendisk.part[minor].nr_sects;			geo.start = mmc_block_gendisk.part[minor].start_sect;			__mmc_block_rdunlock_devices();			if ( copy_to_user( (int *)arg, &geo, sizeof( geo ) ) ) {				ret = -EFAULT;				goto error;			}		}		break;			case BLKRRPART:		if ( !capable( CAP_SYS_ADMIN ) ) {			ret = -EACCES;			goto error;		}		(void)mmc_block_revalidate( inode->i_rdev );		break;			default:		ret = blk_ioctl( inode->i_rdev, cmd, arg );		goto out;	}	ret = 0;error:	out:	__LEAVE( "ret=%d", ret );	return ret;}#if LINUX_VERSION_CODE < 0x20326static struct file_operations mmc_block_fops ={	open: 			mmc_block_open,	ioctl:			mmc_block_ioctl,	release:		mmc_block_release,	check_media_change:	mmc_block_check_disk_change,	revalidate:		mmc_block_revalidate,	read:			block_read,	write:			block_write};#elsestatic struct block_device_operations mmc_block_fops = {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,14)	owner:			THIS_MODULE,#endif	open:			mmc_block_open,	release:		mmc_block_release,	ioctl:			mmc_block_ioctl,	check_media_change:	mmc_block_check_disk_change,	revalidate:		mmc_block_revalidate};#endifstatic int mmc_block_notify_add( mmc_card_t card ){	int ret = -1;	mmc_block_device_t dev;	kdev_t start;	int minor;	__ENTER0();      //  printk("%s::%s",__FILE__, __FUNCTION__);		if ( !card || !card->ctrlr ) 		goto error;		start = MMC_BLOCK_MKDEV( card->ctrlr->slot, card->slot );	dev = &mmc_block_device[MINOR( start )];			__mmc_block_wrlock_devices();	if ( !dev->card ) {		dev->card = card;		ret = 0;	}	__mmc_block_wrunlock_devices();	if ( !ret ) {		int i;		/* allow to read partition table */		__mmc_block_rdlock_devices(); 		grok_partitions( &mmc_block_gendisk, MINOR( start ),			 mmc_block_gendisk.max_p,			 card->info.capacity>>9 /* sectors */		);		__mmc_block_rdunlock_devices();				__mmc_block_wrlock_devices();		for ( i = start + mmc_block_gendisk.max_p - 1; i >= 0; --i ) {			minor = MINOR( i );			dev = &mmc_block_device[minor];			if ( mmc_block_gendisk.part[minor].nr_sects > 0 )				dev->card = card;		}		__mmc_block_wrunlock_devices();	}error:		__LEAVE( "ret=%d", ret );	return ret;}static int mmc_block_notify_remove( mmc_card_t card ){	int ret = -1;		__ENTER( "card=0x%p", card );		if ( card && card->ctrlr )		ret = __mmc_block_invalidate_card( card, FALSE );		__LEAVE( "ret=%d", ret );	return ret;}static mmc_notifier_rec_t mmc_block_notifier = {	add: mmc_block_notify_add,	remove: mmc_block_notify_remove};static int __init mmc_block_module_init( void ){	int ret = -ENODEV;	int i;	__ENTER0();		init_rwsem( &mmc_block_device_sem );		if ( devfs_register_blkdev( MAJOR_NR, MAJOR_NAME, &mmc_block_fops ) ) {		MMC_ERROR( "Can't allocate major number %d for MMC block devices.\n", MMC_BLOCK_MAJOR );		ret = -EAGAIN;		goto error;	}		for ( i = 0; i < (1<<MINORBITS); i++ ) {		__mmc_block_device_init( i );		init_MUTEX( &mmc_block_device[i].sem );		/* We fill it in at open() time. */		mmc_block_blk_sizes[i] = 0;		mmc_block_blk_blksizes[i] = BLOCK_SIZE;		mmc_block_hardsect_sizes[i] = 0;	}		init_waitqueue_head( &thr_wq );	/* Allow the block size to default to BLOCK_SIZE. */	blksize_size[MAJOR_NR] = mmc_block_blk_blksizes;	hardsect_size[MAJOR_NR] = mmc_block_hardsect_sizes;	/* Gendisk stuff */	memset( mmc_block_partitions, 0, sizeof( mmc_block_partitions ) );	add_gendisk( &mmc_block_gendisk );/* FIXME: per controller request queue, I/O and card stack update threads */		blk_init_queue( BLK_DEFAULT_QUEUE( MAJOR_NR ), &mmc_block_request );	thr_id = kernel_thread( mmc_block_thread, NULL, 			CLONE_FS|CLONE_FILES|CLONE_SIGHAND );	if ( !mmc_register( MMC_REG_TYPE_USER, &mmc_block_notifier, 0 ) ) {		MMC_DEBUG( MMC_DEBUG_LEVEL0, "failed to register with MMC core\n" );		goto error;	}	ret = 0;	goto out;error:	if ( thr_id != -1 ) {/* quit the thread */		leaving = 1;		wake_up(&thr_wq);			down(&thread_sem);	}	blksize_size[MAJOR_NR] = NULL;	blk_size[MAJOR_NR] = NULL;	hardsect_size[MAJOR_NR] = NULL;out:		__LEAVE0();	return ret;}static void __exit mmc_block_module_cleanup( void ){/* quit the thread */	leaving = 1;	wake_up(&thr_wq);		down(&thread_sem);		mmc_unregister( MMC_REG_TYPE_USER, &mmc_block_notifier );	del_gendisk( &mmc_block_gendisk );	devfs_unregister_blkdev( MAJOR_NR, MAJOR_NAME );		blk_cleanup_queue( BLK_DEFAULT_QUEUE( MAJOR_NR ) );	blksize_size[MAJOR_NR] = NULL;	blk_size[MAJOR_NR] = NULL;	hardsect_size[MAJOR_NR] = NULL;}EXPORT_NO_SYMBOLS;module_init( mmc_block_module_init );module_exit( mmc_block_module_cleanup );MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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