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

📄 build.c

📁 基于linux-2.6.28的mtd驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
	err = cdev_add(&ubi->cdev, dev, 1);	if (err) {		ubi_err("cannot add character device");		goto out_unreg;	}	err = ubi_sysfs_init(ubi);	if (err)		goto out_sysfs;	for (i = 0; i < ubi->vtbl_slots; i++)		if (ubi->volumes[i]) {			err = ubi_add_volume(ubi, ubi->volumes[i]);			if (err) {				ubi_err("cannot add volume %d", i);				goto out_volumes;			}		}	return 0;out_volumes:	kill_volumes(ubi);	do_free = 0;out_sysfs:	ubi_sysfs_close(ubi);	cdev_del(&ubi->cdev);out_unreg:	if (do_free)		free_user_volumes(ubi);	unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1);	ubi_err("cannot initialize UBI %s, error %d", ubi->ubi_name, err);	return err;}/** * uif_close - close user interfaces for an UBI device. * @ubi: UBI device description object * * Note, since this function un-registers UBI volume device objects (@vol->dev), * the memory allocated voe the volumes is freed as well (in the release * function). */static void uif_close(struct ubi_device *ubi){	kill_volumes(ubi);	ubi_sysfs_close(ubi);	cdev_del(&ubi->cdev);	unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1);}/** * free_internal_volumes - free internal volumes. * @ubi: UBI device description object */static void free_internal_volumes(struct ubi_device *ubi){	int i;	for (i = ubi->vtbl_slots;	     i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {		kfree(ubi->volumes[i]->eba_tbl);		kfree(ubi->volumes[i]);	}}/** * attach_by_scanning - attach an MTD device using scanning method. * @ubi: UBI device descriptor * * This function returns zero in case of success and a negative error code in * case of failure. * * Note, currently this is the only method to attach UBI devices. Hopefully in * the future we'll have more scalable attaching methods and avoid full media * scanning. But even in this case scanning will be needed as a fall-back * attaching method if there are some on-flash table corruptions. */static int attach_by_scanning(struct ubi_device *ubi){	int err;	struct ubi_scan_info *si;	si = ubi_scan(ubi);	if (IS_ERR(si))		return PTR_ERR(si);	ubi->bad_peb_count = si->bad_peb_count;	ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count;	ubi->max_ec = si->max_ec;	ubi->mean_ec = si->mean_ec;	err = ubi_read_volume_table(ubi, si);	if (err)		goto out_si;	err = ubi_wl_init_scan(ubi, si);	if (err)		goto out_vtbl;	err = ubi_eba_init_scan(ubi, si);	if (err)		goto out_wl;	ubi_scan_destroy_si(si);	return 0;out_wl:	ubi_wl_close(ubi);out_vtbl:	free_internal_volumes(ubi);	vfree(ubi->vtbl);out_si:	ubi_scan_destroy_si(si);	return err;}/** * io_init - initialize I/O sub-system for a given UBI device. * @ubi: UBI device description object * * If @ubi->vid_hdr_offset or @ubi->leb_start is zero, default offsets are * assumed: *   o EC header is always at offset zero - this cannot be changed; *   o VID header starts just after the EC header at the closest address *     aligned to @io->hdrs_min_io_size; *   o data starts just after the VID header at the closest address aligned to *     @io->min_io_size * * This function returns zero in case of success and a negative error code in * case of failure. */static int io_init(struct ubi_device *ubi){	if (ubi->mtd->numeraseregions != 0) {		/*		 * Some flashes have several erase regions. Different regions		 * may have different eraseblock size and other		 * characteristics. It looks like mostly multi-region flashes		 * have one "main" region and one or more small regions to		 * store boot loader code or boot parameters or whatever. I		 * guess we should just pick the largest region. But this is		 * not implemented.		 */		ubi_err("multiple regions, not implemented");		return -EINVAL;	}	if (ubi->vid_hdr_offset < 0)		return -EINVAL;	/*	 * Note, in this implementation we support MTD devices with 0x7FFFFFFF	 * physical eraseblocks maximum.	 */	ubi->peb_size   = ubi->mtd->erasesize;	ubi->peb_count  = ubi->mtd->size / ubi->mtd->erasesize;	ubi->flash_size = ubi->mtd->size;	if (ubi->mtd->block_isbad && ubi->mtd->block_markbad)		ubi->bad_allowed = 1;	ubi->min_io_size = ubi->mtd->writesize;	ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft;	/*	 * Make sure minimal I/O unit is power of 2. Note, there is no	 * fundamental reason for this assumption. It is just an optimization	 * which allows us to avoid costly division operations.	 */	if (!is_power_of_2(ubi->min_io_size)) {		ubi_err("min. I/O unit (%d) is not power of 2",			ubi->min_io_size);		return -EINVAL;	}	ubi_assert(ubi->hdrs_min_io_size > 0);	ubi_assert(ubi->hdrs_min_io_size <= ubi->min_io_size);	ubi_assert(ubi->min_io_size % ubi->hdrs_min_io_size == 0);	/* Calculate default aligned sizes of EC and VID headers */	ubi->ec_hdr_alsize = ALIGN(UBI_EC_HDR_SIZE, ubi->hdrs_min_io_size);	ubi->vid_hdr_alsize = ALIGN(UBI_VID_HDR_SIZE, ubi->hdrs_min_io_size);	dbg_msg("min_io_size      %d", ubi->min_io_size);	dbg_msg("hdrs_min_io_size %d", ubi->hdrs_min_io_size);	dbg_msg("ec_hdr_alsize    %d", ubi->ec_hdr_alsize);	dbg_msg("vid_hdr_alsize   %d", ubi->vid_hdr_alsize);	if (ubi->vid_hdr_offset == 0)		/* Default offset */		ubi->vid_hdr_offset = ubi->vid_hdr_aloffset =				      ubi->ec_hdr_alsize;	else {		ubi->vid_hdr_aloffset = ubi->vid_hdr_offset &						~(ubi->hdrs_min_io_size - 1);		ubi->vid_hdr_shift = ubi->vid_hdr_offset -						ubi->vid_hdr_aloffset;	}	/* Similar for the data offset */	ubi->leb_start = ubi->vid_hdr_offset + UBI_EC_HDR_SIZE;	ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size);	dbg_msg("vid_hdr_offset   %d", ubi->vid_hdr_offset);	dbg_msg("vid_hdr_aloffset %d", ubi->vid_hdr_aloffset);	dbg_msg("vid_hdr_shift    %d", ubi->vid_hdr_shift);	dbg_msg("leb_start        %d", ubi->leb_start);	/* The shift must be aligned to 32-bit boundary */	if (ubi->vid_hdr_shift % 4) {		ubi_err("unaligned VID header shift %d",			ubi->vid_hdr_shift);		return -EINVAL;	}	/* Check sanity */	if (ubi->vid_hdr_offset < UBI_EC_HDR_SIZE ||	    ubi->leb_start < ubi->vid_hdr_offset + UBI_VID_HDR_SIZE ||	    ubi->leb_start > ubi->peb_size - UBI_VID_HDR_SIZE ||	    ubi->leb_start & (ubi->min_io_size - 1)) {		ubi_err("bad VID header (%d) or data offsets (%d)",			ubi->vid_hdr_offset, ubi->leb_start);		return -EINVAL;	}	/*	 * It may happen that EC and VID headers are situated in one minimal	 * I/O unit. In this case we can only accept this UBI image in	 * read-only mode.	 */	if (ubi->vid_hdr_offset + UBI_VID_HDR_SIZE <= ubi->hdrs_min_io_size) {		ubi_warn("EC and VID headers are in the same minimal I/O unit, "			 "switch to read-only mode");		ubi->ro_mode = 1;	}	ubi->leb_size = ubi->peb_size - ubi->leb_start;	if (!(ubi->mtd->flags & MTD_WRITEABLE)) {		ubi_msg("MTD device %d is write-protected, attach in "			"read-only mode", ubi->mtd->index);		ubi->ro_mode = 1;	}	ubi_msg("physical eraseblock size:   %d bytes (%d KiB)",		ubi->peb_size, ubi->peb_size >> 10);	ubi_msg("logical eraseblock size:    %d bytes", ubi->leb_size);	ubi_msg("smallest flash I/O unit:    %d", ubi->min_io_size);	if (ubi->hdrs_min_io_size != ubi->min_io_size)		ubi_msg("sub-page size:              %d",			ubi->hdrs_min_io_size);	ubi_msg("VID header offset:          %d (aligned %d)",		ubi->vid_hdr_offset, ubi->vid_hdr_aloffset);	ubi_msg("data offset:                %d", ubi->leb_start);	/*	 * Note, ideally, we have to initialize ubi->bad_peb_count here. But	 * unfortunately, MTD does not provide this information. We should loop	 * over all physical eraseblocks and invoke mtd->block_is_bad() for	 * each physical eraseblock. So, we skip ubi->bad_peb_count	 * uninitialized and initialize it after scanning.	 */	return 0;}/** * autoresize - re-size the volume which has the "auto-resize" flag set. * @ubi: UBI device description object * @vol_id: ID of the volume to re-size * * This function re-sizes the volume marked by the @UBI_VTBL_AUTORESIZE_FLG in * the volume table to the largest possible size. See comments in ubi-header.h * for more description of the flag. Returns zero in case of success and a * negative error code in case of failure. */static int autoresize(struct ubi_device *ubi, int vol_id){	struct ubi_volume_desc desc;	struct ubi_volume *vol = ubi->volumes[vol_id];	int err, old_reserved_pebs = vol->reserved_pebs;	/*	 * Clear the auto-resize flag in the volume in-memory copy of the	 * volume table, and 'ubi_resize_volume()' will propagate this change	 * to the flash.	 */	ubi->vtbl[vol_id].flags &= ~UBI_VTBL_AUTORESIZE_FLG;	if (ubi->avail_pebs == 0) {		struct ubi_vtbl_record vtbl_rec;		/*		 * No available PEBs to re-size the volume, clear the flag on		 * flash and exit.		 */		memcpy(&vtbl_rec, &ubi->vtbl[vol_id],		       sizeof(struct ubi_vtbl_record));		err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);		if (err)			ubi_err("cannot clean auto-resize flag for volume %d",				vol_id);	} else {		desc.vol = vol;		err = ubi_resize_volume(&desc,					old_reserved_pebs + ubi->avail_pebs);		if (err)			ubi_err("cannot auto-resize volume %d", vol_id);	}	if (err)		return err;	ubi_msg("volume %d (\"%s\") re-sized from %d to %d LEBs", vol_id,		vol->name, old_reserved_pebs, vol->reserved_pebs);	return 0;}/** * ubi_attach_mtd_dev - attach an MTD device. * @mtd: MTD device description object * @ubi_num: number to assign to the new UBI device * @vid_hdr_offset: VID header offset * * This function attaches MTD device @mtd_dev to UBI and assign @ubi_num number * to the newly created UBI device, unless @ubi_num is %UBI_DEV_NUM_AUTO, in * which case this function finds a vacant device number and assigns it * automatically. Returns the new UBI device number in case of success and a * negative error code in case of failure. * * Note, the invocations of this function has to be serialized by the * @ubi_devices_mutex. */int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset){	struct ubi_device *ubi;	int i, err, do_free = 1;	/*	 * Check if we already have the same MTD device attached.	 *	 * Note, this function assumes that UBI devices creations and deletions	 * are serialized, so it does not take the &ubi_devices_lock.	 */	for (i = 0; i < UBI_MAX_DEVICES; i++) {		ubi = ubi_devices[i];		if (ubi && mtd->index == ubi->mtd->index) {			dbg_err("mtd%d is already attached to ubi%d",				mtd->index, i);			return -EEXIST;		}	}	/*	 * Make sure this MTD device is not emulated on top of an UBI volume	 * already. Well, generally this recursion works fine, but there are	 * different problems like the UBI module takes a reference to itself	 * by attaching (and thus, opening) the emulated MTD device. This	 * results in inability to unload the module. And in general it makes	 * no sense to attach emulated MTD devices, so we prohibit this.	 */	if (mtd->type == MTD_UBIVOLUME) {		ubi_err("refuse attaching mtd%d - it is already emulated on "			"top of UBI", mtd->index);		return -EINVAL;	}	if (ubi_num == UBI_DEV_NUM_AUTO) {		/* Search for an empty slot in the @ubi_devices array */		for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++)			if (!ubi_devices[ubi_num])				break;		if (ubi_num == UBI_MAX_DEVICES) {			dbg_err("only %d UBI devices may be created",				UBI_MAX_DEVICES);			return -ENFILE;		}	} else {		if (ubi_num >= UBI_MAX_DEVICES)			return -EINVAL;		/* Make sure ubi_num is not busy */		if (ubi_devices[ubi_num]) {			dbg_err("ubi%d already exists", ubi_num);			return -EEXIST;		}	}	ubi = kzalloc(sizeof(struct ubi_device), GFP_KERNEL);	if (!ubi)		return -ENOMEM;	ubi->mtd = mtd;	ubi->ubi_num = ubi_num;	ubi->vid_hdr_offset = vid_hdr_offset;	ubi->autoresize_vol_id = -1;	mutex_init(&ubi->buf_mutex);	mutex_init(&ubi->ckvol_mutex);	mutex_init(&ubi->mult_mutex);	mutex_init(&ubi->volumes_mutex);	spin_lock_init(&ubi->volumes_lock);

⌨️ 快捷键说明

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