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

📄 mtd_blkdevs-24.c

📁 linux下的MTD设备驱动源代码,配合jffs2 yaffss2文件系统.
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	down(&mtd_table_mutex);	tr = get_tr(MAJOR(inode->i_rdev));	if (!tr) {		up(&mtd_table_mutex);		return -ENODEV;	}	devnum = MINOR(inode->i_rdev) >> tr->part_bits;	dev = tr_get_dev(tr, devnum);	up(&mtd_table_mutex);	if (!dev)		return -ENODEV;	switch(cmd) {	case BLKRRPART:		return mtd_blktrans_rrpart(inode->i_rdev, tr, dev);		        case BLKFLSBUF:		blk_ioctl(inode->i_rdev, cmd, arg);		if (tr->flush)			return tr->flush(dev);		/* The core code did the work, we had nothing to do. */		return 0;	case HDIO_GETGEO:		if (tr->getgeo) {			struct hd_geometry g;			struct gendisk *gd = &(tr->blkcore_priv->gd);			int ret;			memset(&g, 0, sizeof(g));			ret = tr->getgeo(dev, &g);			if (ret)				return ret;			g.start = gd->part[MINOR(inode->i_rdev)].start_sect;			if (copy_to_user((void *)arg, &g, sizeof(g)))				return -EFAULT;			return 0;		} /* else */	default:		return -ENOTTY;	}}struct block_device_operations mtd_blktrans_ops = {	.owner		= THIS_MODULE,	.open		= blktrans_open,	.release	= blktrans_release,	.ioctl		= blktrans_ioctl,};int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new){	struct mtd_blktrans_ops *tr = new->tr;	struct list_head *this;	int last_devnum = -1;	int i;	if (!down_trylock(&mtd_table_mutex)) {		up(&mtd_table_mutex);		BUG();	}	spin_lock(&tr->blkcore_priv->devs_lock);	list_for_each(this, &tr->devs) {		struct mtd_blktrans_dev *d = list_entry(this, struct mtd_blktrans_dev, list);		if (new->devnum == -1) {			/* Use first free number */			if (d->devnum != last_devnum+1) {				/* Found a free devnum. Plug it in here */				new->devnum = last_devnum+1;				list_add_tail(&new->list, &d->list);				goto added;			}		} else if (d->devnum == new->devnum) {			/* Required number taken */			spin_unlock(&tr->blkcore_priv->devs_lock);			return -EBUSY;		} else if (d->devnum > new->devnum) {			/* Required number was free */			list_add_tail(&new->list, &d->list);			goto added;		} 		last_devnum = d->devnum;	}	if (new->devnum == -1)		new->devnum = last_devnum+1;	if ((new->devnum << tr->part_bits) > 256) {		spin_unlock(&tr->blkcore_priv->devs_lock);		return -EBUSY;	}	init_MUTEX(&new->sem);	list_add_tail(&new->list, &tr->devs); added:	spin_unlock(&tr->blkcore_priv->devs_lock);	if (!tr->writesect)		new->readonly = 1;	for (i = new->devnum << tr->part_bits;	     i < (new->devnum+1) << tr->part_bits; 	     i++) {		set_device_ro(MKDEV(tr->major, i), new->readonly);		tr->blkcore_priv->blksizes[i] = new->blksize;		tr->blkcore_priv->sizes[i] = 0;		tr->blkcore_priv->part_table[i].nr_sects = 0;		tr->blkcore_priv->part_table[i].start_sect = 0;	}	/*	  <viro_zzz> dwmw2: BLOCK_SIZE_BITS has nothing to do with block devices	  <viro> dwmw2: any code which sets blk_size[][] should be 			size >> 10 /+ 2.4 and its dumb units */	tr->blkcore_priv->sizes[new->devnum << tr->part_bits] = 		(new->size * new->blksize) >> 10; /* 2.4 and its dumb units */	/* But this is still in device's sectors? $DEITY knows */	tr->blkcore_priv->part_table[new->devnum << tr->part_bits].nr_sects = new->size;	if (tr->part_bits) {		grok_partitions(&tr->blkcore_priv->gd, new->devnum,				1 << tr->part_bits, new->size);	}#ifdef CONFIG_DEVFS_FS	if (!tr->part_bits) {		char name[2];		name[0] = '0' + new->devnum;		name[1] = 0;		new->blkcore_priv = 			devfs_register(tr->blkcore_priv->devfs_dir_handle,				       name, DEVFS_FL_DEFAULT, tr->major,				       new->devnum, S_IFBLK|S_IRUGO|S_IWUGO,				       &mtd_blktrans_ops, NULL);	}#endif	return 0;}int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old){	struct mtd_blktrans_ops *tr = old->tr;	int i;	if (!down_trylock(&mtd_table_mutex)) {		up(&mtd_table_mutex);		BUG();	}#ifdef CONFIG_DEVFS_FS	if (!tr->part_bits) {		devfs_unregister(old->blkcore_priv);		old->blkcore_priv = NULL;	} else {		devfs_register_partitions(&tr->blkcore_priv->gd,					  old->devnum << tr->part_bits, 1);	}#endif	spin_lock(&tr->blkcore_priv->devs_lock);	list_del(&old->list);	spin_unlock(&tr->blkcore_priv->devs_lock);	for (i = (old->devnum << tr->part_bits); 	     i < ((old->devnum+1) << tr->part_bits); i++) {		tr->blkcore_priv->sizes[i] = 0;		tr->blkcore_priv->part_table[i].nr_sects = 0;		tr->blkcore_priv->part_table[i].start_sect = 0;	}	return 0;}void blktrans_notify_remove(struct mtd_info *mtd){	struct list_head *this, *this2, *next;	list_for_each(this, &blktrans_majors) {		struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list);		list_for_each_safe(this2, next, &tr->devs) {			struct mtd_blktrans_dev *dev = list_entry(this2, struct mtd_blktrans_dev, list);			if (dev->mtd == mtd)				tr->remove_dev(dev);		}	}}void blktrans_notify_add(struct mtd_info *mtd){	struct list_head *this;	if (mtd->type == MTD_ABSENT)		return;	list_for_each(this, &blktrans_majors) {		struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list);		tr->add_mtd(tr, mtd);	}}static struct mtd_notifier blktrans_notifier = {	.add = blktrans_notify_add,	.remove = blktrans_notify_remove,};      int register_mtd_blktrans(struct mtd_blktrans_ops *tr){	int ret, i;	/* Register the notifier if/when the first device type is 	   registered, to prevent the link/init ordering from fucking	   us over. */	if (!blktrans_notifier.list.next)		register_mtd_user(&blktrans_notifier);	tr->blkcore_priv = kmalloc(sizeof(*tr->blkcore_priv), GFP_KERNEL);	if (!tr->blkcore_priv)		return -ENOMEM;	memset(tr->blkcore_priv, 0, sizeof(*tr->blkcore_priv));	down(&mtd_table_mutex);	ret = devfs_register_blkdev(tr->major, tr->name, &mtd_blktrans_ops);	if (ret) {		printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n",		       tr->name, tr->major, ret);		kfree(tr->blkcore_priv);		up(&mtd_table_mutex);		return ret;	}	blk_init_queue(BLK_DEFAULT_QUEUE(tr->major), &mtd_blktrans_request);	(BLK_DEFAULT_QUEUE(tr->major))->queuedata = tr;		init_completion(&tr->blkcore_priv->thread_dead);	init_waitqueue_head(&tr->blkcore_priv->thread_wq);	ret = kernel_thread(mtd_blktrans_thread, tr, 			  CLONE_FS|CLONE_FILES|CLONE_SIGHAND);	if (ret < 0) {		blk_cleanup_queue(BLK_DEFAULT_QUEUE(tr->major));		devfs_unregister_blkdev(tr->major, tr->name);		kfree(tr->blkcore_priv);		up(&mtd_table_mutex);		return ret;	} 	tr->blkcore_priv->devfs_dir_handle = 			devfs_mk_dir(NULL, tr->name, NULL);	blksize_size[tr->major] = tr->blkcore_priv->blksizes;	blk_size[tr->major] = tr->blkcore_priv->sizes;	tr->blkcore_priv->gd.major = tr->major;	tr->blkcore_priv->gd.major_name = tr->name;	tr->blkcore_priv->gd.minor_shift = tr->part_bits;	tr->blkcore_priv->gd.max_p = (1<<tr->part_bits) - 1;	tr->blkcore_priv->gd.part = tr->blkcore_priv->part_table;	tr->blkcore_priv->gd.sizes = tr->blkcore_priv->sizes;	tr->blkcore_priv->gd.nr_real = 256 >> tr->part_bits;	spin_lock_init(&tr->blkcore_priv->devs_lock);	add_gendisk(&tr->blkcore_priv->gd);	INIT_LIST_HEAD(&tr->devs);	list_add(&tr->list, &blktrans_majors);	for (i=0; i<MAX_MTD_DEVICES; i++) {		if (mtd_table[i] && mtd_table[i]->type != MTD_ABSENT)			tr->add_mtd(tr, mtd_table[i]);	}	up(&mtd_table_mutex);	return 0;}int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr){	struct list_head *this, *next;	down(&mtd_table_mutex);	/* Clean up the kernel thread */	tr->blkcore_priv->exiting = 1;	wake_up(&tr->blkcore_priv->thread_wq);	wait_for_completion(&tr->blkcore_priv->thread_dead);		/* Remove it from the list of active majors */	list_del(&tr->list);	/* Remove each of its devices */	list_for_each_safe(this, next, &tr->devs) {		struct mtd_blktrans_dev *dev = list_entry(this, struct mtd_blktrans_dev, list);		tr->remove_dev(dev);	}	blksize_size[tr->major] = NULL;	blk_size[tr->major] = NULL;	del_gendisk(&tr->blkcore_priv->gd);	blk_cleanup_queue(BLK_DEFAULT_QUEUE(tr->major));	devfs_unregister_blkdev(tr->major, tr->name);	devfs_unregister(tr->blkcore_priv->devfs_dir_handle);	up(&mtd_table_mutex);	kfree(tr->blkcore_priv);	if (!list_empty(&tr->devs))		BUG();	return 0;}static void __exit mtd_blktrans_exit(void){	/* No race here -- if someone's currently in register_mtd_blktrans	   we're screwed anyway. */	if (blktrans_notifier.list.next)		unregister_mtd_user(&blktrans_notifier);}module_exit(mtd_blktrans_exit);EXPORT_SYMBOL_GPL(register_mtd_blktrans);EXPORT_SYMBOL_GPL(deregister_mtd_blktrans);EXPORT_SYMBOL_GPL(add_mtd_blktrans_dev);EXPORT_SYMBOL_GPL(del_mtd_blktrans_dev);MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");MODULE_LICENSE("GPL");MODULE_DESCRIPTION("Common interface to block layer for MTD 'translation layers'");

⌨️ 快捷键说明

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