主機:Gentoo Linux 11.2 with linux kernel 3.0.6
硬件平台:FL2440(S3C2440)with linux kernel 2.6.35
MTD(memory technology device內存技術設備) 在硬件和文件系統層之間的提供了一個抽象的接口,MTD是用來訪問內存設備(如:ROM、flash)的中間層,它將內存設備的共有特性抽取出來,從而使增加新的內存設備驅動程序變得更簡單。MTD的源代碼都在/drivers/mtd目錄中。
MTD中間層細分為四層,按從上到下依次為:設備節點、MTD設備層、MTD原始設備層和硬件驅動層。MTD中間層層次結構圖如下:
從上圖可以看出,原始設備是MTD字符設備和MTD塊設備的抽象。
MTD設備層、MTD原始設備層和Flash硬件驅動層之間的接口關系如下圖:
下面首先分析下MTD原始層設備
1、mtd_info數據結構
[cpp]
- struct mtd_info {
- u_char type;//內存技術類型,例如MTD_RAM,MTD_ROM,MTD_NORFLASH,MTD_NAND_FLASH,MTD_PEROM等
- uint32_t flags;//標志位
- uint64_t size; // Total size of the MTD//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)//oob(Out of band)塊大小
- uint32_t oobavail; // Available OOB bytes per block//每塊的可用的oob字節
-
- /*
- * 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;//eec布局結構
-
- /* Data for variable erase regions. If numeraseregions is zero,
- * it means that the whole device has erasesize as given above.
- */
- int numeraseregions;//擦除區域個數,通常為1
- 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);//函數指針,erase函數的功能是將一個erase_info加入擦除隊列
-
- /* 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);//point函數功能是允許片內執行(XIP)
-
- /* 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);//unpoint函數與point函數相反,是禁止片內執行(XIP)
-
- /* 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
- */
- //如果不是NULL,則允許無MMU單元的地址映射,返回偏移地址
- 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;
-
- //MTD設備的讀寫函數
- 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);
-
- //用於MTD設備的OBB數據讀寫
- int (*read_oob) (struct mtd_info *mtd, loff_t from,
- struct mtd_oob_ops *ops);
- int (*write_oob) (struct mtd_info *mtd, loff_t to,
- 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 */
- //MTD設備的同步函數
- 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;//ECC狀態信息
- /* 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);
- };
2、mtd_part結構體信息
[cpp]
- /* Our partition linked list */
- static LIST_HEAD(mtd_partitions);//分區鏈表
[cpp]
- /* Our partition node structure */
- //分區結構信息
- struct mtd_part {
- struct mtd_info mtd;//mtd_info數據結構,會被加入mtd_table中
- struct mtd_info *master;//該分區的主分區
- uint64_t offset;//該分區的偏移地址
- struct list_head list;//分區鏈表
- };
3、mtd_partition描述mtd具體分區結構
[cpp]
- /*
- * Partition definition structure:
- *
- * An array of struct partition is passed along with a MTD object to
- * add_mtd_partitions() to create them.
- *
- * For each partition, these fields are available:
- * name: string that will be used to label the partition's MTD device.
- * size: the partition size; if defined as MTDPART_SIZ_FULL, the partition
- * will extend to the end of the master MTD device.
- * offset: absolute starting position within the master MTD device; if
- * defined as MTDPART_OFS_APPEND, the partition will start where the
- * previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block.
- * mask_flags: contains flags that have to be masked (removed) from the
- * master MTD flag set for the corresponding MTD partition.
- * For example, to force a read-only partition, simply adding
- * MTD_WRITEABLE to the mask_flags will do the trick.
- *
- * Note: writeable partitions require their size and offset be
- * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
- */
-
- struct mtd_partition {
- char *name; /* identifier string 分區名*/
- uint64_t size; /* partition size 分區大小*/
- uint64_t offset; /* offset within the master MTD space 偏移地址*/
- uint32_t mask_flags; /* master MTD flags to mask out for this partition */
- struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/
- };
下篇分析MTD設備基本管理 http://www.linuxidc.com/Linux/2012-01/51744p2.htm