Chinaunix首页 | 论坛 | 博客
  • 博客访问: 699140
  • 博文数量: 152
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1793
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-12 12:26
个人简介

相信自己,只有不想做的,没有做不到的。

文章分类

全部博文(152)

文章存档

2021年(1)

2015年(2)

2014年(74)

2013年(75)

分类: LINUX

2014-05-09 14:05:08

首先查看mtd_info结构体:


struct mtd_info {
        u_char type;
        uint32_t flags;
        uint64_t size;   // Total size of the MTD


        /* "Major" erase size for the device. Na茂ve users may take this
         * to be the only erase size available, or may use the more detailed
         * information below if they desire
         */
        uint32_t erasesize;
        /* Minimal writable flash unit size. In case of NOR flash it is 1 (even
         * though individual bits can be cleared), in case of NAND flash it is
         * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR
         * it is of ECC block size, etc. It is illegal to have writesize = 0.
         * Any driver registering a struct mtd_info must ensure a writesize of
         * 1 or larger.
         */
        uint32_t writesize;


        uint32_t oobsize;   // Amount of OOB data per block (e.g. 16)
        uint32_t oobavail;  // Available OOB bytes per block


        /*
         * If erasesize is a power of 2 then the shift is stored in
         * erasesize_shift otherwise erasesize_shift is zero. Ditto writesize.
         */
        unsigned int erasesize_shift;
        unsigned int writesize_shift;
        /* Masks based on erasesize_shift and writesize_shift */
        unsigned int erasesize_mask;
        unsigned int writesize_mask;


        // Kernel-only stuff starts here.
        const char *name;
        int index;


        /* ecc layout structure pointer - read only ! */
        struct nand_ecclayout *ecclayout;


        /* Data for variable erase regions. If numeraseregions is zero,
         * it means that the whole device has erasesize as given above.
         */
        int numeraseregions;
        struct mtd_erase_region_info *eraseregions;


        /*
      * Erase is an asynchronous operation.  Device drivers are supposed
         * to call instr->callback() whenever the operation completes, even
         * if it completes with a failure.
         * Callers are supposed to pass a callback function and wait for it
         * to be called before writing to the block.
         */
        int (*erase) (struct mtd_info *mtd, struct erase_info *instr);


        /* This stuff for eXecute-In-Place */
        /* phys is optional and may be set to NULL */
        int (*point) (struct mtd_info *mtd, loff_t from, size_t len,
                        size_t *retlen, void **virt, resource_size_t *phys);


        /* We probably shouldn't allow XIP if the unpoint isn't a NULL */
        void (*unpoint) (struct mtd_info *mtd, loff_t from, size_t len);


        /* Allow NOMMU mmap() to directly map the device (if not NULL)
         * - return the address to which the offset maps
         * - return -ENOSYS to indicate refusal to do the mapping
         */
        unsigned long (*get_unmapped_area) (struct mtd_info *mtd,
                                            unsigned long len,
                                            unsigned long offset,
                                            unsigned long flags);


        /* Backing device capabilities for this device
         * - provides mmap capabilities
         */
        struct backing_dev_info *backing_dev_info;




        int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
        int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);


        /* In blackbox flight recorder like scenarios we want to make successful
           writes in interrupt context. panic_write() is only intended to be
           called when its known the kernel is about to panic and we need the
           write to succeed. Since the kernel is not going to be running for much
           longer, this function can break locks and delay to ensure the write
           succeeds (but not sleep). */


        int (*panic_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);


        int (*read_oob) (struct mtd_info *mtd, loff_t from,
                         struct mtd_oob_ops *ops);
     /*
         * Methods to access the protection register area, present in some
         * flash devices. The user data is one time programmable but the
         * factory data is read only.
         */
        int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
        int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
        int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
        int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
        int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
        int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len);


        /* kvec-based read/write methods.
           NB: The 'count' parameter is the number of _vectors_, each of
           which contains an (ofs, len) tuple.
        */
        int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen);


        /* Sync */
        void (*sync) (struct mtd_info *mtd);


        /* Chip-supported device locking */
        int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
        int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);


        /* Power Management functions */
        int (*suspend) (struct mtd_info *mtd);
        void (*resume) (struct mtd_info *mtd);


        /* Bad block management functions */
        int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
        int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);


        struct notifier_block reboot_notifier;  /* default mode before reboot */


        /* ECC status information */
        struct mtd_ecc_stats ecc_stats;
        /* Subpage shift (NAND) */
        int subpage_sft;


        void *priv;


        struct module *owner;
        struct device dev;
        int usecount;



        /* If the driver is something smart, like UBI, it may need to maintain
         * its own reference counting. The below functions are only for driver.
         * The driver may register its callbacks. These callbacks are not
         * supposed to be called by MTD users */
        int (*get_device) (struct mtd_info *mtd);
        void (*put_device) (struct mtd_info *mtd);
};

可以看到mtd_info结构体很多参数,nandflash在写数据之前要进行擦除;所以我app对nandflash进行读写的话需要关注一下几个参数:
 int (*erase) (struct mtd_info *mtd, struct erase_info *instr);     //擦除nandflash分区
int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);  //写nandflash分区
 int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);//读nandflash分区

查看linux-2.6.32.2/drivers/mtd/mtdcore.c
通过分区中的名字来获取mtd结构体的信息
/**
 *      get_mtd_device_nm - obtain a validated handle for an MTD device by
 *      device name
 *      @name: MTD device name to open
 *
 *      This function returns MTD device description structure in case of
 *      success and an error code in case of failure.
 */


struct mtd_info *get_mtd_device_nm(const char *name)
{
        int i, err = -ENODEV;
        struct mtd_info *mtd = NULL;


        mutex_lock(&mtd_table_mutex);


        for (i = 0; i < MAX_MTD_DEVICES; i++) {
                if (mtd_table[i] && !strcmp(name, mtd_table[i]->name)) {
                        mtd = mtd_table[i];
                        break;
                }
        }


        if (!mtd)
                goto out_unlock;


        if (!try_module_get(mtd->owner))
                goto out_unlock;


        if (mtd->get_device) {
                err = mtd->get_device(mtd);
                if (err)
                        goto out_put;
        }


        mtd->usecount++;
        mutex_unlock(&mtd_table_mutex);
        return mtd;


out_put:
        module_put(mtd->owner);
out_unlock:
        mutex_unlock(&mtd_table_mutex);
        return ERR_PTR(err);
}


查看擦除的结构体
/* If the erase fails, fail_addr might indicate exactly which block failed.  If
   fail_addr = MTD_FAIL_ADDR_UNKNOWN, the failure was not at the device level or was not
   specific to any particular block. */
struct erase_info {
        struct mtd_info *mtd;
        uint64_t addr;
        uint64_t len;
        uint64_t fail_addr;
        u_long time;
        u_long retries;
        unsigned dev;
        unsigned cell;
        void (*callback) (struct erase_info *self);
        u_long priv;
        u_char state;
        struct erase_info *next;
};




阅读(750) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~