wiki中关于mtd的说明
Memory technology devices (MTD) are a new type of device file in for interacting with . The MTD subsystem was created to provide an between the hardware-specific device drivers and higher-level applications.
Hardware drivers need to know nothing about the storage formats used,
such as FTL, FFS2, etc., but will only need to provide simple routines
for read, write and erase
It makes it possible to use the same API when
working with different flash types and technologies, e.g. NAND, OneNAND, NOR,
AG-AND, ECC'd NOR, etc
Flash doesn't match the desciption of either block or character devices.
mtd只是针对于flash memory的,而且提供了很好的抽象层次
在linux 系統中提供了MTD (memory technolog device)來建立flash針對linux 統一,抽象的接口,
好處有以下兩點:
1.我們要做Mtd設備的驅動模塊,所要做的事情就是去實現公共接口函數的實際內容.再設級模塊是不用理會字符還是塊設備的驅動設計標準,因為所有這些接口的機制,mtd已經為我們做好了
2.上层应用只需要访问mtd抽象层提供的字符设备方式或者块设备方式来访问mtd设备,因此具体驱动对于上层应用来说是具有独立性的,即使底层驱动修改了,上层拥有也不需要改动。并且由于mtd抽象层,上层应用就可以避免直接对具体硬件操作,而是对mtd操作,这样的话这些应用就不是建立在某个具体的设备上,更好的实现了通用性和兼容性
2.
有了MTD 之後,linux系統中的flash可分為4層:
硬件驅動層,MTD原始設備層,MTD設備層還有設備節點.
CFI:Common Flash Interface 通用的Falsh接口
OOB:out of band 某些内存技术支持out-of-band 数据用于纠错
一个mtd 原始设备可以通过mtd_part分隔成为数个mtd 原始的设备注册进mtd_table, mtd_table 中的每个mtd原始设备都可以被注册成一个mtd设备
mtd_info用於描述MTD的設備,定義了關於mtd設備的數據和操作函數,每個分區也被認為一個mtd_info.而mtd_info的指針北存放在mtd_table的數組里.
- 101struct mtd_info {
-
102 u_char type;
-
103 uint32_t flags;
-
104 uint64_t size; // Total size of the MTD
-
105
-
106 /* "Major" erase size for the device. Nave users may take this
-
107 * to be the only erase size available, or may use the more detailed
-
108 * information below if they desire
-
109 */
-
110 uint32_t erasesize;
-
111 /* Minimal writable flash unit size. In case of NOR flash it is 1 (even
-
112 * though individual bits can be cleared), in case of NAND flash it is
-
113 * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR
-
114 * it is of ECC block size, etc. It is illegal to have writesize = 0.
-
115 * Any driver registering a struct mtd_info must ensure a writesize of
-
116 * 1 or larger.
-
117 */
-
118 uint32_t writesize;
-
119
-
120 uint32_t oobsize; // Amount of OOB data per block (e.g. 16)
-
121 uint32_t oobavail; // Available OOB bytes per block
-
122
-
123 /*
-
124 * If erasesize is a power of 2 then the shift is stored in
-
125 * erasesize_shift otherwise erasesize_shift is zero. Ditto writesize.
-
126 */
-
127 unsigned int erasesize_shift;
-
128 unsigned int writesize_shift;
-
129 /* Masks based on erasesize_shift and writesize_shift */
-
130 unsigned int erasesize_mask;
-
131 unsigned int writesize_mask;
-
132
-
133 // Kernel-only stuff starts here.
-
134 const char *name;
-
135 int index;
-
136
-
137 /* ecc layout structure pointer - read only ! */
-
138 struct nand_ecclayout *ecclayout;
-
139
-
140 /* Data for variable erase regions. If numeraseregions is zero,
-
141 * it means that the whole device has erasesize as given above.
-
142 */
-
143 int numeraseregions;
-
144 struct mtd_erase_region_info *eraseregions;
-
145
-
146 /*
-
147 * Erase is an asynchronous operation. Device drivers are supposed
-
148 * to call instr->callback() whenever the operation completes, even
-
149 * if it completes with a failure.
-
150 * Callers are supposed to pass a callback function and wait for it
-
151 * to be called before writing to the block.
-
152 */
-
153 int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
-
154
-
155 /* This stuff for eXecute-In-Place */
-
156 /* phys is optional and may be set to NULL */
-
157 int (*point) (struct mtd_info *mtd, loff_t from, size_t len,
-
158 size_t *retlen, void **virt, resource_size_t *phys);
-
159
-
160 /* We probably shouldn't allow XIP if the unpoint isn't a NULL */
-
161 void (*unpoint) (struct mtd_info *mtd, loff_t from, size_t len);
-
162
-
163 /* Allow NOMMU mmap() to directly map the device (if not NULL)
-
164 * - return the address to which the offset maps
-
165 * - return -ENOSYS to indicate refusal to do the mapping
-
166 */
-
167 unsigned long (*get_unmapped_area) (struct mtd_info *mtd,
-
168 unsigned long len,
-
169 unsigned long offset,
-
170 unsigned long flags);
-
171
-
172 /* Backing device capabilities for this device
-
173 * - provides mmap capabilities
-
174 */
-
175 struct backing_dev_info *backing_dev_info;
-
176
-
177
-
178 int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
-
179 int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
-
180
-
181 /* In blackbox flight recorder like scenarios we want to make successful
-
182 writes in interrupt context. panic_write() is only intended to be
-
183 called when its known the kernel is about to panic and we need the
-
184 write to succeed. Since the kernel is not going to be running for much
-
185 longer, this function can break locks and delay to ensure the write
-
186 succeeds (but not sleep). */
-
187
-
188 int (*panic_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
-
189
-
190 int (*read_oob) (struct mtd_info *mtd, loff_t from,
-
191 struct mtd_oob_ops *ops);
-
192 int (*write_oob) (struct mtd_info *mtd, loff_t to,
-
193 struct mtd_oob_ops *ops);
-
194
-
195 /*
-
196 * Methods to access the protection register area, present in some
-
197 * flash devices. The user data is one time programmable but the
-
198 * factory data is read only.
-
199 */
-
200 int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
-
201 int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
-
202 int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
-
203 int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
-
204 int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
-
205 int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len);
-
206
-
207 /* kvec-based read/write methods.
-
208 NB: The 'count' parameter is the number of _vectors_, each of
-
209 which contains an (ofs, len) tuple.
-
210 */
-
211 int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to,size_t *retlen);
-
212
-
213 /* Sync */
-
214 void (*sync) (struct mtd_info *mtd);
-
215
-
216 /* Chip-supported device locking */
-
217 int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
-
218 int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
-
219
-
220 /* Power Management functions */
-
221 int (*suspend) (struct mtd_info *mtd);
-
222 void (*resume) (struct mtd_info *mtd);
-
223
-
224 /* Bad block management functions */
-
225 int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
-
226 int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
-
227
-
228 struct notifier_block reboot_notifier; /* default mode before reboot */
-
229
-
230 /* ECC status information */
-
231 struct mtd_ecc_stats ecc_stats;
-
232 /* Subpage shift (NAND) */
-
233 int subpage_sft;
-
234
-
235 void *priv;
-
236
-
237 struct module *owner;
-
238 struct device dev;
-
239 int usecount;
-
240
-
241 /* If the driver is something smart, like UBI, it may need to maintain
-
242 * its own reference counting. The below functions are only for driver.
-
243 * The driver may register its callbacks. These callbacks are not
-
244 * supposed to be called by MTD users */
-
245 int (*get_device) (struct mtd_info *mtd);
-
246 void (*put_device) (struct mtd_info *mtd);
-
247};
-
248
flash驅動註冊和註銷mtd設備函數
- int add_mtd_device(struct mtd_info *mtd);
- int del_mtd_device (struct *);
- /////
mtd_part結構體用於表示分區,是已經分好了的分區,一个MTD原始
设备可以通过mtd_part分割成数个MTD原始设备注册进
mtd_table,mtd_table中的
每个MTD原始设备都可以被注册成一
个MTD设备,其中字符设备的主设备号为90,次设备号为0、2、
4、6…(奇数次设备号为只读设备),块设备的主设
备号为31,次
设备号为0、1、2、3
- 26struct mtd_part {
-
27 struct mtd_info mtd; /* 分區的信息*/
-
28 struct mtd_info *master; /* 該分區的主分區*/
-
29 uint64_t offset; /* 該分區的偏移地址*/
-
30 struct list_head list;
-
31};
- ///
上面是2.6.35的了,已經與之前的結構體的內容不同.
mtd_partiton會在mtd原始設備層調用add_mtd_partions()是傳遞分區信息
- 15/*
-
16 * Partition definition structure:
-
17 *
-
18 * An array of struct partition is passed along with a MTD object to
-
19 * add_mtd_partitions() to create them.
-
20 *
-
21 * For each partition, these fields are available:
-
22 * name: string that will be used to label the partition's MTD device.
-
23 * size: the partition size; if defined as MTDPART_SIZ_FULL, the partition
-
24 * will extend to the end of the master MTD device.
-
25 * offset: absolute starting position within the master MTD device; if
-
26 * defined as MTDPART_OFS_APPEND, the partition will start where the
-
27 * previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block.
-
28 * mask_flags: contains flags that have to be masked (removed) from the
-
29 * master MTD flag set for the corresponding MTD partition.
-
30 * For example, to force a read-only partition, simply adding
-
31 * MTD_WRITEABLE to the mask_flags will do the trick.
-
32 *
-
33 * Note: writeable partitions require their size and offset be
-
34 * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
-
35 */
-
36
-
37struct mtd_partition {
-
38 char *name; /* identifier string */
-
39 uint64_t size; /* partition size */
-
40 uint64_t offset; /* offset within the master MTD space */
-
41 uint32_t mask_flags; /* master MTD flags to mask out for this partition */
-
42 struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/
-
43};
mtdcore.c 主要实现了MTD原始设备层的数据结构mtd_table 和对其的操作函数
阅读(2831) | 评论(0) | 转发(0) |