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

📄 mtdpart.c

📁 基于linux-2.6.28的mtd驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Simple MTD partitioning layer * * (C) 2000 Nicolas Pitre <nico@cam.org> * * This code is GPL * * 	02-21-2002	Thomas Gleixner <gleixner@autronix.de> *			added support for read_oob, write_oob */#include <linux/module.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/list.h>#include <linux/kmod.h>#include <linux/mtd/mtd.h>#include <linux/mtd/partitions.h>#include <linux/mtd/compatmac.h>/* Our partition linked list */static LIST_HEAD(mtd_partitions);/* Our partition node structure */struct mtd_part {	struct mtd_info mtd;	struct mtd_info *master;	u_int32_t offset;	int index;	struct list_head list;	int registered;};/* * Given a pointer to the MTD object in the mtd_part structure, we can retrieve * the pointer to that structure with this macro. */#define PART(x)  ((struct mtd_part *)(x))/* * MTD methods which simply translate the effective address and pass through * to the _real_ device. */static int part_read(struct mtd_info *mtd, loff_t from, size_t len,		size_t *retlen, u_char *buf){	struct mtd_part *part = PART(mtd);	int res;	if (from >= mtd->size)		len = 0;	else if (from + len > mtd->size)		len = mtd->size - from;	res = part->master->read(part->master, from + part->offset,				   len, retlen, buf);	if (unlikely(res)) {		if (res == -EUCLEAN)			mtd->ecc_stats.corrected++;		if (res == -EBADMSG)			mtd->ecc_stats.failed++;	}	return res;}static int part_point(struct mtd_info *mtd, loff_t from, size_t len,		size_t *retlen, void **virt, resource_size_t *phys){	struct mtd_part *part = PART(mtd);	if (from >= mtd->size)		len = 0;	else if (from + len > mtd->size)		len = mtd->size - from;	return part->master->point (part->master, from + part->offset,				    len, retlen, virt, phys);}static void part_unpoint(struct mtd_info *mtd, loff_t from, size_t len){	struct mtd_part *part = PART(mtd);	part->master->unpoint(part->master, from + part->offset, len);}static int part_read_oob(struct mtd_info *mtd, loff_t from,		struct mtd_oob_ops *ops){	struct mtd_part *part = PART(mtd);	int res;	if (from >= mtd->size)		return -EINVAL;	if (ops->datbuf && from + ops->len > mtd->size)		return -EINVAL;	res = part->master->read_oob(part->master, from + part->offset, ops);	if (unlikely(res)) {		if (res == -EUCLEAN)			mtd->ecc_stats.corrected++;		if (res == -EBADMSG)			mtd->ecc_stats.failed++;	}	return res;}static int part_read_user_prot_reg(struct mtd_info *mtd, loff_t from,		size_t len, size_t *retlen, u_char *buf){	struct mtd_part *part = PART(mtd);	return part->master->read_user_prot_reg(part->master, from,					len, retlen, buf);}static int part_get_user_prot_info(struct mtd_info *mtd,		struct otp_info *buf, size_t len){	struct mtd_part *part = PART(mtd);	return part->master->get_user_prot_info(part->master, buf, len);}static int part_read_fact_prot_reg(struct mtd_info *mtd, loff_t from,		size_t len, size_t *retlen, u_char *buf){	struct mtd_part *part = PART(mtd);	return part->master->read_fact_prot_reg(part->master, from,					len, retlen, buf);}static int part_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf,		size_t len){	struct mtd_part *part = PART(mtd);	return part->master->get_fact_prot_info(part->master, buf, len);}static int part_write(struct mtd_info *mtd, loff_t to, size_t len,		size_t *retlen, const u_char *buf){	struct mtd_part *part = PART(mtd);	if (!(mtd->flags & MTD_WRITEABLE))		return -EROFS;	if (to >= mtd->size)		len = 0;	else if (to + len > mtd->size)		len = mtd->size - to;	return part->master->write(part->master, to + part->offset,				    len, retlen, buf);}static int part_panic_write(struct mtd_info *mtd, loff_t to, size_t len,		size_t *retlen, const u_char *buf){	struct mtd_part *part = PART(mtd);	if (!(mtd->flags & MTD_WRITEABLE))		return -EROFS;	if (to >= mtd->size)		len = 0;	else if (to + len > mtd->size)		len = mtd->size - to;	return part->master->panic_write(part->master, to + part->offset,				    len, retlen, buf);}static int part_write_oob(struct mtd_info *mtd, loff_t to,		struct mtd_oob_ops *ops){	struct mtd_part *part = PART(mtd);	if (!(mtd->flags & MTD_WRITEABLE))		return -EROFS;	if (to >= mtd->size)		return -EINVAL;	if (ops->datbuf && to + ops->len > mtd->size)		return -EINVAL;	return part->master->write_oob(part->master, to + part->offset, ops);}static int part_write_user_prot_reg(struct mtd_info *mtd, loff_t from,		size_t len, size_t *retlen, u_char *buf){	struct mtd_part *part = PART(mtd);	return part->master->write_user_prot_reg(part->master, from,					len, retlen, buf);}static int part_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,		size_t len){	struct mtd_part *part = PART(mtd);	return part->master->lock_user_prot_reg(part->master, from, len);}static int part_writev(struct mtd_info *mtd, const struct kvec *vecs,		unsigned long count, loff_t to, size_t *retlen){	struct mtd_part *part = PART(mtd);	if (!(mtd->flags & MTD_WRITEABLE))		return -EROFS;	return part->master->writev(part->master, vecs, count,					to + part->offset, retlen);}static int part_erase(struct mtd_info *mtd, struct erase_info *instr){	struct mtd_part *part = PART(mtd);	int ret;	if (!(mtd->flags & MTD_WRITEABLE))		return -EROFS;	if (instr->addr >= mtd->size)		return -EINVAL;	instr->addr += part->offset;	ret = part->master->erase(part->master, instr);	if (ret) {		if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)			instr->fail_addr -= part->offset;		instr->addr -= part->offset;	}	return ret;}void mtd_erase_callback(struct erase_info *instr){	if (instr->mtd->erase == part_erase) {		struct mtd_part *part = PART(instr->mtd);		if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)			instr->fail_addr -= part->offset;		instr->addr -= part->offset;	}	if (instr->callback)		instr->callback(instr);}EXPORT_SYMBOL_GPL(mtd_erase_callback);static int part_lock(struct mtd_info *mtd, loff_t ofs, size_t len){	struct mtd_part *part = PART(mtd);	if ((len + ofs) > mtd->size)		return -EINVAL;	return part->master->lock(part->master, ofs + part->offset, len);}static int part_unlock(struct mtd_info *mtd, loff_t ofs, size_t len){	struct mtd_part *part = PART(mtd);	if ((len + ofs) > mtd->size)		return -EINVAL;	return part->master->unlock(part->master, ofs + part->offset, len);}static void part_sync(struct mtd_info *mtd){	struct mtd_part *part = PART(mtd);	part->master->sync(part->master);}static int part_suspend(struct mtd_info *mtd){	struct mtd_part *part = PART(mtd);	return part->master->suspend(part->master);}static void part_resume(struct mtd_info *mtd){	struct mtd_part *part = PART(mtd);	part->master->resume(part->master);}static int part_block_isbad(struct mtd_info *mtd, loff_t ofs){	struct mtd_part *part = PART(mtd);	if (ofs >= mtd->size)		return -EINVAL;	ofs += part->offset;	return part->master->block_isbad(part->master, ofs);}static int part_block_markbad(struct mtd_info *mtd, loff_t ofs){	struct mtd_part *part = PART(mtd);	int res;	if (!(mtd->flags & MTD_WRITEABLE))		return -EROFS;	if (ofs >= mtd->size)		return -EINVAL;	ofs += part->offset;	res = part->master->block_markbad(part->master, ofs);	if (!res)

⌨️ 快捷键说明

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