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

📄 mmc_core.c

📁 linux下mmc_sd卡的驱动.rar
💻 C
📖 第 1 页 / 共 2 页
字号:
	}err_mmc:	ret = __mmc_check_error( card, ret ); /* FIXME */	if ( ret >= 0 ) {		ret = size - transfer.cnt;		*paddr += ret;	}err_down:	mmc_release_io( ctrlr, card );error:	__LEAVE( "ret=%d", ret );	return ret;}EXPORT_SYMBOL( mmc_write );int mmc_ioctl( mmc_card_t card, unsigned int cmd, unsigned long arg ){	int ret = -EINVAL;	mmc_controller_t ctrlr;		if ( !card ) {		MMC_DEBUG( MMC_DEBUG_LEVEL0, "bad card reference\n" )		goto error;	}			ctrlr = card->ctrlr;	if ( mmc_acquire_io( ctrlr, card ) ) {  		ret = -ENXIO;		goto error;	}	switch ( cmd ) {		case IOCMMCGCARDESC:			if ( copy_to_user( (void *)arg, &card->info, sizeof( mmc_card_info_rec_t ) ) )				ret = -EFAULT;			break;/*	 * 1. TODO: erase region * 2. TODO: set/unset write protection, lock/password  */		default:			ret = -ENOIOCTLCMD;	}		mmc_release_io( ctrlr, card );error:	return ret;}EXPORT_SYMBOL( mmc_ioctl );/*  * registry stuff  */mmc_card_t mmc_get_card( int host, int slot ){	mmc_card_t ret = NULL;	mmc_controller_t ctrlr = NULL;	int found;	__ENTER( "host=%d, card=%d", host, slot );		if ( ((host < 0) || (host >= MMC_CONTROLLERS_MAX)) 	     && ((slot < 0) || (slot >= MMC_CARDS_MAX)) )		goto error;	 	down_read( &mmc_controller_sem );		if ( (ctrlr = mmc_controller[host]) ) {		down_write( &ctrlr->update_sem );		if ( ctrlr->stack.ncards > 0 ) {			ret = ctrlr->stack.first;			found = FALSE;			while ( ret ) {				if ( (ret->slot == slot) && (ret->state != 				     MMC_CARD_STATE_UNPLUGGED) ) {					found = TRUE;					break;				}				ret = ret->next;			}			if ( found ) {				if ( ctrlr->tmpl->owner ) {					++ctrlr->usage;					MMC_DEBUG( MMC_DEBUG_LEVEL2, 					    "'%s' use count increased (%d)\n", 					    ctrlr->tmpl->name, ctrlr->usage );					__MOD_INC_USE_COUNT( ctrlr->tmpl->owner );				}				++ret->usage;			} else				ret = NULL;		}		up_write( &ctrlr->update_sem );		}	up_read( &mmc_controller_sem );error:	__LEAVE("ret=0x%p usage=%d", ret, ret ? ret->usage : -1 );	return ret;}EXPORT_SYMBOL( mmc_get_card );void mmc_put_card( mmc_card_t card ){	mmc_card_t tmp = NULL;	mmc_controller_t ctrlr;	int found;		__ENTER( "card=0x%p", card );	if ( !card )	     	goto error;		ctrlr = card->ctrlr;	 	down_read( &mmc_controller_sem );	if ( !ctrlr || (ctrlr != mmc_controller[ctrlr->slot]) ) {		MMC_ERROR( "bad controller reference: ctrlr=0x%p\n", ctrlr );		goto err_down;	}		down_write( &ctrlr->update_sem );	if ( ctrlr->stack.ncards > 0 ) {		tmp = ctrlr->stack.first;		found = FALSE;		while ( tmp ) {			if ( tmp == card ) {				found = TRUE;				break;			}			tmp = tmp->next;		}		if ( found ) {			if ( tmp->usage > 0 ) {				--tmp->usage;				MMC_DEBUG( MMC_DEBUG_LEVEL2, "usage=%d"					"owner=0x%p\n", tmp->usage, 					ctrlr->tmpl->owner );				if ( !tmp->usage && (ctrlr->usage > 0) 	  			     && ctrlr->tmpl->owner ) {					--ctrlr->usage;					MMC_DEBUG( MMC_DEBUG_LEVEL2, 						"'%s' use count "						"decreased (%d)\n", 						ctrlr->tmpl->name, 						ctrlr->usage );					__MOD_DEC_USE_COUNT( 							ctrlr->tmpl->owner );				}			}		} else			MMC_DEBUG( MMC_DEBUG_LEVEL0, "bad card reference\n" );				}	up_write( &ctrlr->update_sem );	err_down: 	up_read( &mmc_controller_sem );error:	__LEAVE( "found=%d", found );	return;}EXPORT_SYMBOL( mmc_put_card );static inline void *mmc_register_user( mmc_notifier_t notifier ){	mmc_notifier_t ret = NULL, last = mmc_notifier;		MOD_INC_USE_COUNT;	if ( notifier ) {		down_write( &mmc_notifier_sem );				notifier->next = NULL;		if ( !last ) {			mmc_notifier = notifier;			ret = notifier;			} else {			while ( last->next ) {				if ( last == notifier ) {					MOD_DEC_USE_COUNT;					break;				}				last = last->next;			}			if ( last != notifier ) {				last->next = notifier;				ret = notifier;			}		}		up_write( &mmc_notifier_sem );	}/* notify new user about the cards present in the system */	if ( ret && ret->add ) {		int i;				down_read( &mmc_controller_sem );		for ( i = 0; i < mmc_ncontrollers; i++ ) {			mmc_controller_t ctrlr = mmc_controller[i];						down_read( &ctrlr->update_sem ); /* FIXME */			__mmc_card_stack_foreach( &ctrlr->stack, 					ret->add, FALSE );			up_read( &ctrlr->update_sem ); /* FIXME */		}		up_read( &mmc_controller_sem );	}/* error: */	__LEAVE( "mmc_notifier=0x%p, mmc_notifier->next=0x%p",			mmc_notifier, mmc_notifier ? mmc_notifier->next : NULL );	return ret;}static inline mmc_controller_t mmc_register_controller( mmc_controller_tmpl_t tmpl, size_t extra ){	mmc_controller_t ret = NULL;	int found;	int i;		MOD_INC_USE_COUNT;		down_write( &mmc_controller_sem );		if ( mmc_ncontrollers >= MMC_CONTROLLERS_MAX ) {		MMC_DEBUG( MMC_DEBUG_LEVEL0, "there're too many controllers\n" );		goto error;	}		found = FALSE;	for ( i = 0; i < MMC_CONTROLLERS_MAX; i++ )		if ( !mmc_controller[i] ) {			found = TRUE;			break;		}		if ( !found ) {		MMC_DEBUG( MMC_DEBUG_LEVEL0, "there're no empty slots\n" );		goto error;	}	if ( !tmpl->init ) {		MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'init()'\n" );		goto error;	}		if ( !tmpl->probe ) {		MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'probe()'\n" );		goto error;	}		if ( !tmpl->init_card_stack ) {		MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'init_card_stack()'\n" );		goto error;	}		if ( !tmpl->update_acq ) {		MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'update_acq()'\n" );		goto error;	}		if ( !tmpl->check_card_stack ) {		MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'check_card_stack()'\n" );		goto error;	}		if ( !tmpl->setup_card ) {		MMC_DEBUG( MMC_DEBUG_LEVEL0, "host template lacks 'setup_card()'\n" );		goto error;	}		ret = kmalloc( sizeof( mmc_controller_rec_t ) + extra, GFP_ATOMIC ); /* FIXME: ISA + GFP_DMA */	if ( !ret ) {		MMC_DEBUG( MMC_DEBUG_LEVEL0, "out of memory\n" );		goto error;	}	memset( ret, 0, sizeof( mmc_controller_rec_t ) + extra );		if ( (tmpl->probe( ret ) != 1) ) {		MMC_DEBUG( MMC_DEBUG_LEVEL0, "controller probe failed\n" );		goto err_free;	}		if ( tmpl->init( ret ) ) {		MMC_DEBUG( MMC_DEBUG_LEVEL0, "controller initialization failure\n" );		goto err_free;	}		ret->state = MMC_CONTROLLER_FOUND;	ret->slot = i;	ret->tmpl = tmpl;	init_MUTEX( &ret->io_sem );	init_rwsem( &ret->update_sem );#ifdef CONFIG_PROC_FS	if ( mmc_proc_dir ) {		snprintf( ret->proc_name, sizeof( ret->proc_name ),				"host%d", ret->slot );		ret->proc = proc_mkdir( ret->proc_name, mmc_proc_dir );	}#endif	/* initialize card stack */	if ( ret->tmpl->init_card_stack( ret ) ) {		MMC_DEBUG( MMC_DEBUG_LEVEL0, "card stack initialization failure\n" );		if ( ret->tmpl->remove )			ret->tmpl->remove( ret ); /* FIXME */		goto err_free;	}		mmc_controller[ret->slot] = ret;	++mmc_ncontrollers;/* notify users */	if ( ret->stack.ncards > 0 ) {		down_read( &mmc_notifier_sem );		if ( (i = __mmc_card_stack_foreach( &ret->stack, mmc_notify_add, FALSE ) ) < 0 )			MMC_ERROR( "device add notification failed at slot %d\n", -i );		up_read( &mmc_notifier_sem );	}	goto out;	err_free:#ifdef CONFIG_PROC_FS	if ( ret->proc )		remove_proc_entry( ret->proc_name, mmc_proc_dir );#endif	kfree( ret );error:	ret = NULL;	MOD_DEC_USE_COUNT;out:		up_write( &mmc_controller_sem );	return ret;}static inline mmc_card_t mmc_register_card( mmc_card_t card ){	mmc_card_t ret = NULL;	mmc_controller_t ctrlr;		if ( !card || !card->ctrlr )		goto error;		ctrlr = card->ctrlr;#ifdef CONFIG_PROC_FS	if ( ctrlr->proc ) {		snprintf( card->proc_name, sizeof( card->proc_name ),					"card%d", card->slot );		card->proc = create_proc_read_entry( card->proc_name,					0444, ctrlr->proc,					mmc_proc_read_card_info, card );	}#endif	mmc_notify_add( card );error:	return ret;}void *mmc_register( mmc_reg_type_t reg_type, void *tmpl, size_t extra ){	void *ret = NULL;	switch ( reg_type ) {		case MMC_REG_TYPE_CARD:			ret = mmc_register_card( (mmc_card_t)tmpl );			break;		case MMC_REG_TYPE_USER:			ret = mmc_register_user( (mmc_notifier_t)tmpl );			break;		case MMC_REG_TYPE_HOST:			ret = mmc_register_controller( (mmc_controller_tmpl_t)tmpl, extra );			break;				default:			MMC_DEBUG( MMC_DEBUG_LEVEL0, "register request for unknown type\n" );	}		return ret;}EXPORT_SYMBOL( mmc_register );static inline void mmc_unregister_user( mmc_notifier_t notifier ){	mmc_notifier_t prev = mmc_notifier;	int found = FALSE;		if ( notifier ) {		down_write( &mmc_notifier_sem );				if ( mmc_notifier == notifier) {			mmc_notifier = prev->next;			found = TRUE;					} else if ( mmc_notifier ) {			while( prev ) {				if ( prev->next == notifier ) {					found = TRUE;					prev->next = prev->next->next;					break;				}				prev = prev->next;			}		}				if ( found ) {			if ( notifier->remove ) {				int i;						down_read( &mmc_controller_sem );				for ( i = 0; i < mmc_ncontrollers; i++ ) {					mmc_controller_t ctrlr = 						mmc_controller[i];						down_read( &ctrlr->update_sem );					__mmc_card_stack_foreach( &ctrlr->stack, notifier->remove, FALSE );					up_read( &ctrlr->update_sem );				}				up_read( &mmc_controller_sem );			}		}				up_write( &mmc_notifier_sem );	}		MOD_DEC_USE_COUNT;}static inline void mmc_unregister_controller( mmc_controller_t ctrlr ){	if ( !ctrlr || (mmc_controller[ctrlr->slot] != ctrlr ) ) {		MMC_DEBUG( MMC_DEBUG_LEVEL0, "bad unregister request\n" );		goto error;	}	down_write( &mmc_controller_sem );/* notify users */	if ( ctrlr->stack.ncards > 0 ) {		int slot;				down_read( &mmc_notifier_sem );		if ( (slot = __mmc_card_stack_foreach( &ctrlr->stack, mmc_notify_remove, FALSE ) ) )			MMC_ERROR( "device remove notification failed at slot %d\n", -slot );		up_read( &mmc_notifier_sem );	}#ifdef CONFIG_PROC_FS	if ( ctrlr->proc ) 		remove_proc_entry( ctrlr->proc_name, mmc_proc_dir );#endif	if ( ctrlr->tmpl && ctrlr->tmpl->remove )			ctrlr->tmpl->remove( ctrlr );	mmc_controller[ctrlr->slot] = NULL;	--mmc_ncontrollers;	__mmc_free_controller( ctrlr ); 	up_write( &mmc_controller_sem );	MOD_DEC_USE_COUNT;error:	return;}void mmc_unregister( mmc_reg_type_t reg_type, void *tmpl ){	switch ( reg_type ) {		case MMC_REG_TYPE_USER:			mmc_unregister_user( (mmc_notifier_t)tmpl );			break;		case MMC_REG_TYPE_HOST:			mmc_unregister_controller( (mmc_controller_t)tmpl );			break;				default:			MMC_DEBUG( MMC_DEBUG_LEVEL0, "unregister request for unknown type\n" );	}}EXPORT_SYMBOL( mmc_unregister );#ifdef CONFIG_PM/* power management support */static int mmc_pm_callback( struct pm_dev *pmdev, pm_request_t pmreq, void *pmdata ){	int ret = -EINVAL;	mmc_controller_t ctrlr;	int i;		__ENTER( "pmreq=%d", pmreq );		down_read( &mmc_controller_sem );		switch ( pmreq ) {	case PM_SUSPEND:		for ( ret = 0, i = 0; !ret && (i < mmc_ncontrollers); i++ ) {			ctrlr = mmc_controller[i];			if ( ctrlr->tmpl->suspend )				ret = ctrlr->tmpl->suspend( ctrlr );		}		if ( !ret )			break;			case PM_RESUME:		for ( i = mmc_ncontrollers - 1; i >= 0; i-- ) {			ctrlr = mmc_controller[i];			if ( ctrlr->tmpl->resume )				ctrlr->tmpl->resume( ctrlr );		}		ret = 0;		break;	default:		MMC_DEBUG( MMC_DEBUG_LEVEL0, "unsupported PM request %d\n", 					pmreq );	}	up_read( &mmc_controller_sem );/* error: */		__LEAVE( "ret=%d", ret );	return ret;}#endif/* kernel module stuff */static int __init mmc_core_module_init( void ){	int ret = -ENODEV;		memset( &mmc_controller, 0, sizeof( mmc_controller ) );		init_rwsem( &mmc_controller_sem );	init_rwsem( &mmc_notifier_sem );#ifdef CONFIG_PM	if ( !(mmc_pm_dev = pm_register( PM_UNKNOWN_DEV, 0, mmc_pm_callback )) ) 		MMC_DEBUG( MMC_DEBUG_LEVEL0, "failed to register PM callback\n" );#endif#ifdef CONFIG_PROC_FS	mmc_proc_dir = proc_mkdir( "mmc", NULL );#endif	ret = 0;/* error: */	return ret;}static void __exit mmc_core_module_cleanup( void ){#ifdef CONFIG_PROC_FS	if ( mmc_proc_dir )		remove_proc_entry( "mmc", NULL );#endif#ifdef CONFIG_PM	pm_unregister( mmc_pm_dev );#endif}module_init( mmc_core_module_init );module_exit( mmc_core_module_cleanup );MODULE_LICENSE( "GPL" );

⌨️ 快捷键说明

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