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

📄 mmc_core.c

📁 The sd/mmc driver for s3c2410, it is much better than the one from samsung
💻 C
📖 第 1 页 / 共 2 页
字号:
extern char hotplug_path[];extern int call_usermodehelper(char *path, char **argv, char **envp);static void run_sbin_hotplug(struct mmc_dev *dev, int id, int insert){	int i;	char *argv[3], *envp[8];	char media[64], slotnum[16];	if (!hotplug_path[0])		return;	MMC_DEBUG(0,": hotplug_path=%s id=%d insert=%d", hotplug_path, id, insert);	i = 0;	argv[i++] = hotplug_path;	argv[i++] = "mmc";	argv[i] = 0;	/* minimal command environment */	i = 0;	envp[i++] = "HOME=/";	envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";		/* other stuff we want to pass to /sbin/hotplug */	sprintf(slotnum, "SLOT=%d", id );	if ( dev->slot[id].media_driver && dev->slot[id].media_driver->name )		sprintf(media, "MEDIA=%s", dev->slot[id].media_driver->name );	else		sprintf(media, "MEDIA=unknown");	envp[i++] = slotnum;	envp[i++] = media;	if (insert)		envp[i++] = "ACTION=add";	else		envp[i++] = "ACTION=remove";	envp[i] = 0;	call_usermodehelper (argv [0], argv, envp);}static void mmc_hotplug_task_handler( void *nr ){	int insert = ((int) nr) & 0x01;	int id     = ((int) nr) >> 1;	MMC_DEBUG(2,"id=%d insert=%d", id, insert );	run_sbin_hotplug(&g_mmc_dev, id, insert );}static struct tq_struct mmc_hotplug_task = {	routine:  mmc_hotplug_task_handler};void run_sbin_mmc_hotplug(struct mmc_dev *dev, int id, int insert ){	mmc_hotplug_task.data = (void *) ((id << 1) | insert);	schedule_task( &mmc_hotplug_task );}#elsevoid run_sbin_mmc_hotplug(struct sleeve_dev *sdev, int insert) { }#endif /* CONFIG_HOTPLUG *//****************************************************************** * Common processing tasklet * Everything gets serialized through this ******************************************************************/static void mmc_tasklet_action(unsigned long data){	struct mmc_dev *dev = (struct mmc_dev *)data;	unsigned long   flags;	int             state;	MMC_DEBUG(2,": dev=%p flags=%02x", dev, dev->state);	/* Grab the current working state */	local_irq_save(flags);	state = dev->state;	if ( state & STATE_CMD_DONE )		dev->state = state & ~(STATE_CMD_DONE | STATE_CMD_ACTIVE);	local_irq_restore(flags);	/* If there is an active command, don't do anything */	if ( (state & STATE_CMD_ACTIVE) && !(state & STATE_CMD_DONE) )		return;	if ( dev->protocol )		dev->protocol(dev,state);}/****************************************************************** * Callbacks from low-level driver * These run at interrupt time ******************************************************************/void mmc_cmd_complete(struct mmc_request *request){	MMC_DEBUG(2,"request=%p retval=%d", request, request->result);	g_mmc_dev.state |= STATE_CMD_DONE;	if ( !g_mmc_dev.suspended )		tasklet_schedule(&g_mmc_dev.task);}void mmc_insert(int slot){	MMC_DEBUG(2,"slot=%d", slot);	g_mmc_dev.state |= STATE_INSERT;	g_mmc_dev.slot[slot].flags |= MMC_SLOT_FLAG_INSERT;	if ( !g_mmc_dev.suspended )		tasklet_schedule(&g_mmc_dev.task);}void mmc_eject(int slot){	MMC_DEBUG(2,"slot=%d", slot);	g_mmc_dev.state |= STATE_EJECT;	g_mmc_dev.slot[slot].flags |= MMC_SLOT_FLAG_EJECT;	if ( !g_mmc_dev.suspended )		tasklet_schedule(&g_mmc_dev.task);}EXPORT_SYMBOL(mmc_cmd_complete);EXPORT_SYMBOL(mmc_insert);EXPORT_SYMBOL(mmc_eject);/****************************************************************** * Called from the media handler ******************************************************************/void mmc_handle_io_request( struct mmc_io_request *t ){	MMC_DEBUG(2,"id=%d cmd=%d sector=%ld nr_sectors=%ld block_len=%ld buf=%p",	      t->id, t->cmd, t->sector, t->nr_sectors, t->block_len, t->buffer);		if ( g_mmc_dev.io_request ) {		MMC_DEBUG(0,": error! io_request in progress");		return;	}		g_mmc_dev.io_request = t;	tasklet_schedule(&g_mmc_dev.task);}EXPORT_SYMBOL(mmc_handle_io_request);/****************************************************************** *  Media handlers *  Allow different drivers to register a media handler ******************************************************************/static LIST_HEAD(mmc_media_drivers);int mmc_match_media_driver( struct mmc_slot *slot ){	struct list_head *item;	MMC_DEBUG(2,"slot=%p", slot);	for ( item = mmc_media_drivers.next ; item != &mmc_media_drivers ; item = item->next ) {		struct mmc_media_driver *drv = list_entry(item, struct mmc_media_driver, node );		if ( drv->probe(slot) ) {			slot->media_driver = drv;			drv->load(slot);			return 1;		}	}	return 0;}int mmc_register_media_driver( struct mmc_media_driver *drv ){	list_add_tail( &drv->node, &mmc_media_drivers );	return 0;}void mmc_unregister_media_driver( struct mmc_media_driver *drv ){	list_del(&drv->node);}EXPORT_SYMBOL(mmc_register_media_driver);EXPORT_SYMBOL(mmc_unregister_media_driver);/******************************************************************/int mmc_register_slot_driver( struct mmc_slot_driver *sdrive, int num_slots ){	int i;	int retval;	MMC_DEBUG(2,"max=%d ocr=0x%08x", num_slots, sdrive->ocr);	if ( num_slots > MMC_MAX_SLOTS ) {		printk(KERN_CRIT "%s: illegal num of slots %d\n", __FUNCTION__, num_slots );		return -ENOMEM;	}	if ( g_mmc_dev.sdrive ) {		printk(KERN_ALERT "%s: slot in use\n", __FUNCTION__);		return -EBUSY;	}	g_mmc_dev.sdrive    = sdrive;	g_mmc_dev.num_slots = num_slots;	for ( i = 0 ; i < num_slots ; i++ ) {		struct mmc_slot *slot = &g_mmc_dev.slot[i];		memset(slot,0,sizeof(struct mmc_slot));		slot->id = i;		slot->state = CARD_STATE_EMPTY;	}	retval = sdrive->init();	if ( retval )		return retval;	/* Generate insert events for cards */	for ( i = 0 ; i < num_slots ; i++ )		if ( !sdrive->is_empty(i) )			mmc_insert(i);	return 0;}void mmc_unregister_slot_driver( struct mmc_slot_driver *sdrive ){	int i;	MMC_DEBUG(2,"");	for ( i = 0 ; i < g_mmc_dev.num_slots ; i++ )		mmc_eject(i);	if ( sdrive == g_mmc_dev.sdrive ) {		g_mmc_dev.sdrive->cleanup();		g_mmc_dev.sdrive = NULL;	}}EXPORT_SYMBOL(mmc_register_slot_driver);EXPORT_SYMBOL(mmc_unregister_slot_driver);/******************************************************************/static struct pm_dev *mmc_pm_dev;static int mmc_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data){	int i;	MMC_DEBUG(0,": pm callback %d", req );	switch (req) {	case PM_SUSPEND: /* Enter D1-D3 */		g_mmc_dev.suspended = 1;                break;	case PM_RESUME:  /* Enter D0 */		if ( g_mmc_dev.suspended ) {			g_mmc_dev.suspended = 0;			g_mmc_dev.state = 0;     // Clear the old state			for ( i = 0 ; i < g_mmc_dev.num_slots ; i++ ) {				mmc_eject(i);				if ( !g_mmc_dev.sdrive->is_empty(i) )					mmc_insert(i);			}		}		break;        }        return 0;}/****************************************************************** * TODO: These would be better handled by driverfs * For the moment, we'll just eject and insert everything ******************************************************************/int mmc_do_eject(ctl_table *ctl, int write, struct file * filp, void *buffer, size_t *lenp){	mmc_eject(0);	return 0;}int mmc_do_insert(ctl_table *ctl, int write, struct file * filp, void *buffer, size_t *lenp){	mmc_insert(0);	return 0;}static struct ctl_table mmc_sysctl_table[] ={#ifdef CONFIG_MMC_DEBUG	{ 1, "debug", &g_mmc_debug, sizeof(int), 0666, NULL, &proc_dointvec },#endif	{ 2, "eject", NULL, 0, 0600, NULL, &mmc_do_eject },	{ 3, "insert", NULL, 0, 0600, NULL, &mmc_do_insert },	{0}};static struct ctl_table mmc_dir_table[] ={	{BUS_MMC, "mmc", NULL, 0, 0555, mmc_sysctl_table},	{0}};static struct ctl_table bus_dir_table[] = {	{CTL_BUS, "bus", NULL, 0, 0555, mmc_dir_table},        {0}};static struct ctl_table_header *mmc_sysctl_header;static int mmc_proc_read_device(char *page, char **start, off_t off, int count, int *eof, void *data){	struct mmc_dev *dev = (struct mmc_dev *)data;        char *p = page;        int len = 0;	int i;	if (!dev || !dev->sdrive)		return 0;	for ( i = 0 ; i < dev->num_slots ; i++ ) {		struct mmc_slot *slot = &dev->slot[i];		p += sprintf(p, "Slot #%d\n", i);		p += sprintf(p, "  State %s (%d)\n", card_state_to_string(slot->state), slot->state);		if ( slot->state != CARD_STATE_EMPTY ) {			p += sprintf(p, "  Media %s\n", (slot->media_driver ? slot->media_driver->name : "unknown"));			p += sprintf(p, "  CID mid=%d\n", slot->cid.mid);			p += sprintf(p, "      oid=%d\n", slot->cid.oid);			p += sprintf(p, "      pnm=%s\n", slot->cid.pnm);			p += sprintf(p, "      prv=%d.%d\n", slot->cid.prv>>4, slot->cid.prv&0xf);			p += sprintf(p, "      psn=0x%08x\n", slot->cid.psn);			p += sprintf(p, "      mdt=%d/%d\n", slot->cid.mdt>>4, (slot->cid.mdt&0xf)+1997);			p += sprintf(p, "  CSD csd_structure=%d\n", slot->csd.csd_structure);			p += sprintf(p, "      spec_vers=%d\n", slot->csd.spec_vers);			p += sprintf(p, "      taac=0x%02x\n", slot->csd.taac);			p += sprintf(p, "      nsac=0x%02x\n", slot->csd.nsac);			p += sprintf(p, "      tran_speed=0x%02x\n", slot->csd.tran_speed);			p += sprintf(p, "      ccc=0x%04x\n", slot->csd.ccc);			p += sprintf(p, "      read_bl_len=%d\n", slot->csd.read_bl_len);			p += sprintf(p, "      read_bl_partial=%d\n", slot->csd.read_bl_partial);			p += sprintf(p, "      write_blk_misalign=%d\n", slot->csd.write_blk_misalign);			p += sprintf(p, "      read_blk_misalign=%d\n", slot->csd.read_blk_misalign);			p += sprintf(p, "      dsr_imp=%d\n", slot->csd.dsr_imp);			p += sprintf(p, "      c_size=%d\n", slot->csd.c_size);			p += sprintf(p, "      vdd_r_curr_min=%d\n", slot->csd.vdd_r_curr_min);			p += sprintf(p, "      vdd_r_curr_max=%d\n", slot->csd.vdd_r_curr_max);			p += sprintf(p, "      vdd_w_curr_min=%d\n", slot->csd.vdd_w_curr_min);			p += sprintf(p, "      vdd_w_curr_max=%d\n", slot->csd.vdd_w_curr_max);			p += sprintf(p, "      c_size_mult=%d\n", slot->csd.c_size_mult);			p += sprintf(p, "      wp_grp_size=%d\n", slot->csd.wp_grp_size);			p += sprintf(p, "      wp_grp_enable=%d\n", slot->csd.wp_grp_enable);			p += sprintf(p, "      default_ecc=%d\n", slot->csd.default_ecc);			p += sprintf(p, "      r2w_factor=%d\n", slot->csd.r2w_factor);			p += sprintf(p, "      write_bl_len=%d\n", slot->csd.write_bl_len);			p += sprintf(p, "      write_bl_partial=%d\n", slot->csd.write_bl_partial);			p += sprintf(p, "      file_format_grp=%d\n", slot->csd.file_format_grp);			p += sprintf(p, "      copy=%d\n", slot->csd.copy);			p += sprintf(p, "      perm_write_protect=%d\n", slot->csd.perm_write_protect);			p += sprintf(p, "      tmp_write_protect=%d\n", slot->csd.tmp_write_protect);			p += sprintf(p, "      file_format=%d\n", slot->csd.file_format);			p += sprintf(p, "      ecc=%d\n", slot->csd.ecc);			switch (slot->csd.csd_structure) {			case CSD_STRUCT_VER_1_0:			case CSD_STRUCT_VER_1_1:				p += sprintf(p, "      sector_size=%d\n", slot->csd.erase.v22.sector_size);				p += sprintf(p, "      erase_grp_size=%d\n", slot->csd.erase.v22.erase_grp_size);				break;			case CSD_STRUCT_VER_1_2:			default:				p += sprintf(p, "      erase_grp_size=%d\n", slot->csd.erase.v31.erase_grp_size);				p += sprintf(p, "      erase_grp_mult=%d\n", slot->csd.erase.v31.erase_grp_mult);				break;			}		}	}        len = (p - page) - off;	*start = page + off;        return len;}/******************************************************************/void mmc_protocol_single_card( struct mmc_dev *dev, int state_flags );extern struct mmc_media_module media_module;static int __init mmc_init(void) {	MMC_DEBUG(1,"");		mmc_sysctl_header = register_sysctl_table(bus_dir_table, 0 );	tasklet_init(&g_mmc_dev.task,mmc_tasklet_action,(unsigned long)&g_mmc_dev);	g_mmc_dev.protocol = mmc_protocol_single_card;#ifdef CONFIG_PROC_FS	proc_mmc_dir = proc_mkdir("mmc", proc_bus);	if ( proc_mmc_dir )		create_proc_read_entry("device", 0, proc_mmc_dir, mmc_proc_read_device, &g_mmc_dev);#endif	mmc_pm_dev = pm_register(PM_UNKNOWN_DEV, PM_SYS_UNKNOWN, mmc_pm_callback);	media_module.init();	return 0;}static void __exit mmc_exit(void){	MMC_DEBUG(1,"");	media_module.cleanup();	unregister_sysctl_table(mmc_sysctl_header);	tasklet_kill(&g_mmc_dev.task);#ifdef CONFIG_PROC_FS	if ( proc_mmc_dir ) {		remove_proc_entry("device", proc_mmc_dir);		remove_proc_entry("mmc", proc_bus);	}#endif	pm_unregister(mmc_pm_dev);}module_init(mmc_init);module_exit(mmc_exit);MODULE_AUTHOR("Andrew Christian <andyc@handhelds.org>");MODULE_DESCRIPTION("Multimedia Card (MMC) framework");MODULE_LICENSE("Dual BSD/GPL");

⌨️ 快捷键说明

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