source: rtems/cpukit/libblock/include/rtems/flashdisk.h @ 9ab091e

4.11
Last change on this file since 9ab091e was 9ab091e, checked in by Mathew Kallada <matkallada@…>, on Dec 28, 2012 at 4:35:32 PM

Header File Doxygen Enhancement Task #2

  • Property mode set to 100644
File size: 18.0 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup RTEMSFDisk
5 *
6 * @brief Interface to a Flash Disk Block Device
7 *
8 * This file defines the interface to a flash disk block device.
9 */
10
11/*
12 * Copyright (C) 2007 Chris Johns
13 *
14 * The license and distribution terms for this file may be
15 * found in the file LICENSE in this distribution or at
16 * http://www.rtems.com/license/LICENSE.
17 */
18
19#if !defined (_RTEMS_FLASHDISK_H_)
20#define _RTEMS_FLASHDISK_H_
21
22#include <stdint.h>
23#include <sys/ioctl.h>
24
25#include <rtems.h>
26
27/**
28 * @defgroup RTEMSFDisk Flash Disk Device
29 *
30 * @ingroup rtems_blkdev
31 *
32 * Flash disk driver for RTEMS provides support for block based
33 * file systems on flash devices. The driver is not a flash file
34 * system nor does it try to compete with flash file systems. It
35 * currently does not journal how-ever block sequence numbering
36 * could be added to allow recovery of a past positions if
37 * a power down occurred while being updated.
38 *
39 * This flash driver provides block device support for most flash
40 * devices. The driver has been tested on NOR type devices such
41 * as the AMLV160 or M28W160. Support for NAND type devices may
42 * require driver changes to allow speedy recover of the block
43 * mapping data and to also handle the current use of word programming.
44 * Currently the page descriptors are stored in the first few pages
45 * of each segment.
46 *
47 * The driver supports devices, segments and pages. You provide
48 * to the driver the device descriptions as a table of device
49 * descriptors. Each device descriptor contain a table of
50 * segment descriptions or segment descriptors. The driver uses
51 * this information to manage the devices.
52 *
53 * A device is made up of segments. These are also called
54 * sectors or blocks. It is the smallest erasable part of a device.
55 * A device can have differing size segments at different
56 * offsets in the device. The segment descriptors support repeating
57 * segments that are continuous in the device. The driver breaks the
58 * segments up into pages. The first pages of a segment contain
59 * the page descriptors. A page descriptor hold the page flags,
60 * a CRC for the page of data and the block number the page
61 * holds. The block can appear in any order in the devices. A
62 * page is active if it hold a current block of data. If the
63 * used bit is set the page is counted as used. A page moves
64 * from erased to active to used then back to erased. If a block
65 * is written that is already in a page, the block is written to
66 * a new page the old page is flagged as used.
67 *
68 * At initialization time each segment's page descriptors are
69 * read into memory and scanned to determine the active pages,
70 * the used pages and the bad pages. If a segment has any erased
71 * pages it is queue on the available queue. If the segment has
72 * no erased pages it is queue on the used queue.
73 *
74 * The available queue is sorted from the least number available
75 * to the most number of available pages. A segment that has just
76 * been erased will placed at the end of the queue. A segment that
77 * has only a few available pages will be used sooner and once
78 * there are no available pages it is queued on the used queue.
79 * The used queue hold segments that have no available pages and
80 * is sorted from the least number of active pages to the most
81 * number of active pages.
82 *
83 * The driver is required to compact segments. Compacting takes
84 * the segment with the most number of available pages from the
85 * available queue then takes segments with the least number of
86 * active pages from the used queue until it has enough pages
87 * to fill the empty segment. As the active pages are moved
88 * they flagged as used and once the segment has only used pages
89 * it is erased.
90 *
91 * A flash block driver like this never knows if a page is not
92 * being used by the file-system. A typical file system is not
93 * design with the idea of erasing a block on a disk once it is
94 * not being used. The file-system will normally use a flag
95 * or a location as a marker to say that part of the disk is
96 * no longer in use. This means a number of blocks could be
97 * held in active pages but are no in use by the file system.
98 * The file system may also read blocks that have never been
99 * written to disk. This complicates the driver and may make
100 * the wear, usage and erase patterns harsher than a flash
101 * file system. The driver may also suffer from problems if
102 * power is lost.
103 *
104 * There are some flash disk specific IO control request types.
105 * To use open the device and issue the ioctl() call.
106 *
107 * @code
108 *  int fd = open ("/dev/flashdisk0", O_WRONLY, 0);
109 *  if (fd < 0)
110 *  {
111 *    printf ("driver open failed: %s\n", strerror (errno));
112 *    exit (1);
113 *  }
114 *  if (ioctl (fd, RTEMS_FDISK_IOCTL_ERASE_DISK) < 0)
115 *  {
116 *    printf ("driver erase failed: %s\n", strerror (errno));
117 *    exit (1);
118 *  }
119 *  close (fd);
120 * @endcode
121 *
122 * @{
123 */
124
125/**
126 * @brief The base name of the flash disks.
127 */
128#define RTEMS_FLASHDISK_DEVICE_BASE_NAME "/dev/fdd"
129
130#define RTEMS_FDISK_IOCTL_ERASE_DISK   _IO('B', 128)
131#define RTEMS_FDISK_IOCTL_COMPACT      _IO('B', 129)
132#define RTEMS_FDISK_IOCTL_ERASE_USED   _IO('B', 130)
133#define RTEMS_FDISK_IOCTL_MONITORING   _IO('B', 131)
134#define RTEMS_FDISK_IOCTL_INFO_LEVEL   _IO('B', 132)
135#define RTEMS_FDISK_IOCTL_PRINT_STATUS _IO('B', 133)
136
137/**
138 * @brief Flash Disk Monitoring Data allows a user to obtain
139 * the current status of the disk.
140 */
141typedef struct rtems_fdisk_monitor_data
142{
143  uint32_t block_size;
144  uint32_t block_count;
145  uint32_t unavail_blocks;
146  uint32_t device_count;
147  uint32_t segment_count;
148  uint32_t page_count;
149  uint32_t blocks_used;
150  uint32_t segs_available;
151  uint32_t segs_used;
152  uint32_t segs_failed;
153  uint32_t seg_erases;
154  uint32_t pages_desc;
155  uint32_t pages_active;
156  uint32_t pages_used;
157  uint32_t pages_bad;
158  uint32_t info_level;
159} rtems_fdisk_monitor_data;
160
161/**
162 * @brief Flash Segment Descriptor holds, number of continuous segments in the
163 * device of this type, the base segment number in the device, the address
164 * offset of the base segment in the device, and the size of segment.
165 *
166 * Typically this structure is part of a table of segments in the
167 * device which is referenced in the flash disk configuration table.
168 * The reference is kept in the driver and used all the time to
169 * manage the flash device, therefore it must always exist.
170 */
171typedef struct rtems_fdisk_segment_desc
172{
173  uint16_t count;    /**< Number of segments of this type in a row. */
174  uint16_t segment;  /**< The base segment number. */
175  uint32_t offset;   /**< Address offset of base segment in device. */
176  uint32_t size;     /**< Size of the segment in bytes. */
177} rtems_fdisk_segment_desc;
178
179/**
180 * @brief Return the number of kilo-bytes.
181 */
182#define RTEMS_FDISK_KBYTES(_k) (UINT32_C(1024) * (_k))
183
184/**
185 * Forward declaration of the device descriptor.
186 */
187struct rtems_fdisk_device_desc;
188
189/**
190 * @brief Flash Low Level driver handlers.
191 *
192 * Typically this structure is part of a table of handlers in the
193 * device which is referenced in the flash disk configuration table.
194 * The reference is kept in the driver and used all the time to
195 * manage the flash device, therefore it must always exist.
196 */
197typedef struct rtems_fdisk_driver_handlers
198{
199  /**
200   * Read data from the device into the buffer. Return an errno
201   * error number if the device cannot be read. A segment descriptor
202   * can describe more than one segment in a device if the device has
203   * repeating segments. The segment number is the device segment to
204   * access and the segment descriptor must reference the segment
205   * being requested. For example the segment number must resided in
206   * the range [base, base + count).
207   *
208   * @param sd The segment descriptor.
209   * @param device The device to read data from.
210   * @param segment The segment within the device to read.
211   * @param offset The offset in the segment to read.
212   * @param buffer The buffer to read the data into.
213   * @param size The amount of data to read.
214   * @retval 0 No error.
215   * @retval EIO The read did not complete.
216   */
217  int (*read) (const rtems_fdisk_segment_desc* sd,
218               uint32_t                        device,
219               uint32_t                        segment,
220               uint32_t                        offset,
221               void*                           buffer,
222               uint32_t                        size);
223
224  /**
225   * Write data from the buffer to the device. Return an errno
226   * error number if the device cannot be written to. A segment
227   * descriptor can describe more than segment in a device if the
228   * device has repeating segments. The segment number is the device
229   * segment to access and the segment descriptor must reference
230   * the segment being requested. For example the segment number must
231   * resided in the range [base, base + count).
232   *
233   * @param sd The segment descriptor.
234   * @param device The device to write data from.
235   * @param segment The segment within the device to write to.
236   * @param offset The offset in the segment to write.
237   * @param buffer The buffer to write the data from.
238   * @param size The amount of data to write.
239   * @retval 0 No error.
240   * @retval EIO The write did not complete or verify.
241   */
242  int (*write) (const rtems_fdisk_segment_desc* sd,
243                uint32_t                        device,
244                uint32_t                        segment,
245                uint32_t                        offset,
246                const void*                     buffer,
247                uint32_t                        size);
248
249  /**
250   * Blank a segment in the device. Return an errno error number
251   * if the device cannot be read or is not blank. A segment descriptor
252   * can describe more than segment in a device if the device has
253   * repeating segments. The segment number is the device segment to
254   * access and the segment descriptor must reference the segment
255   * being requested. For example the segment number must resided in
256   * the range [base, base + count).
257   *
258   * @param sd The segment descriptor.
259   * @param device The device to read data from.
260   * @param segment The segment within the device to read.
261   * @param offset The offset in the segment to checl.
262   * @param size The amount of data to check.
263   * @retval 0 No error.
264   * @retval EIO The segment is not blank.
265   */
266  int (*blank) (const rtems_fdisk_segment_desc* sd,
267                uint32_t                        device,
268                uint32_t                        segment,
269                uint32_t                        offset,
270                uint32_t                        size);
271
272  /**
273   * Verify data in the buffer to the data in the device. Return an
274   * errno error number if the device cannot be read. A segment
275   * descriptor can describe more than segment in a device if the
276   * device has repeating segments. The segment number is the
277   * segment to access and the segment descriptor must reference
278   * the device segment being requested. For example the segment number
279   * must resided in the range [base, base + count).
280   *
281   * @param sd The segment descriptor.
282   * @param device The device to verify data in.
283   * @param segment The segment within the device to verify.
284   * @param offset The offset in the segment to verify.
285   * @param buffer The buffer to verify the data in the device with.
286   * @param size The amount of data to verify.
287   * @retval 0 No error.
288   * @retval EIO The data did not verify.
289   */
290  int (*verify) (const rtems_fdisk_segment_desc* sd,
291                 uint32_t                        device,
292                 uint32_t                        segment,
293                 uint32_t                        offset,
294                 const void*                     buffer,
295                 uint32_t                        size);
296
297  /**
298   * Erase the segment. Return an errno error number if the
299   * segment cannot be erased. A segment descriptor can describe
300   * more than segment in a device if the device has repeating
301   * segments. The segment number is the device segment to access and
302   * the segment descriptor must reference the segment being requested.
303   *
304   * @param sd The segment descriptor.
305   * @param device The device to erase the segment of.
306   * @param segment The segment within the device to erase.
307   * @retval 0 No error.
308   * @retval EIO The segment was not erased.
309   */
310  int (*erase) (const rtems_fdisk_segment_desc* sd,
311                uint32_t                        device,
312                uint32_t                        segment);
313
314  /**
315   * Erase the device. Return an errno error number if the
316   * segment cannot be erased. A segment descriptor can describe
317   * more than segment in a device if the device has repeating
318   * segments. The segment number is the segment to access and
319   * the segment descriptor must reference the segment being requested.
320   *
321   * @param sd The segment descriptor.
322   * @param device The device to erase.
323   * @retval 0 No error.
324   * @retval EIO The device was not erased.
325   */
326  int (*erase_device) (const struct rtems_fdisk_device_desc* dd,
327                       uint32_t                              device);
328
329} rtems_fdisk_driver_handlers;
330
331/**
332 * @brief Flash Device Descriptor holds the segments in a device.
333 *
334 * The placing of the segments in a device decriptor allows the low level
335 * driver to share the segment descriptors for a number of devices.
336 *
337 * Typically this structure is part of a table of segments in the
338 * device which is referenced in the flash disk configuration table.
339 * The reference is kept in the driver and used all the time to
340 * manage the flash device, therefore it must always exist.
341 */
342typedef struct rtems_fdisk_device_desc
343{
344  uint32_t                           segment_count; /**< Number of segments. */
345  const rtems_fdisk_segment_desc*    segments;      /**< Array of segments. */
346  const rtems_fdisk_driver_handlers* flash_ops;     /**< Device handlers. */
347} rtems_fdisk_device_desc;
348
349/**
350 * @brief RTEMS Flash Disk configuration table used to initialise the
351 * driver.
352 *
353 * The unavailable blocks count is the number of blocks less than the
354 * available number of blocks the file system is given. This means there
355 * will always be that number of blocks available when the file system
356 * thinks the disk is full. The compaction code needs blocks to compact
357 * with so you will never be able to have all the blocks allocated to the
358 * file system and be able to full the disk.
359 *
360 * The compacting segment count is the number of segments that are
361 * moved into a new segment. A high number will mean more segments with
362 * low active page counts and high used page counts will be moved into
363 * avaliable pages how-ever this extends the compaction time due to
364 * time it takes the erase the pages. There is no pont making this number
365 * greater than the maximum number of pages in a segment.
366 *
367 * The available compacting segment count is the level when compaction occurs
368 * when writing. If you set this to 0 then compaction will fail because
369 * there will be no segments to compact into.
370 *
371 * The info level can be 0 for off with error, and abort messages allowed.
372 * Level 1 is warning messages, level 1 is informational messages, and level 3
373 * is debugging type prints. The info level can be turned off with a compile
374 * time directive on the command line to the compiler of:
375 *
376 *     -DRTEMS_FDISK_TRACE=0
377 */
378typedef struct rtems_flashdisk_config
379{
380  uint32_t                       block_size;     /**< The block size. */
381  uint32_t                       device_count;   /**< The number of devices. */
382  const rtems_fdisk_device_desc* devices;        /**< The device descriptions. */
383  uint32_t                       flags;          /**< Set of flags to control
384                                                      driver. */
385  /**
386   * Number of blocks not available to the file system.  This number must be
387   * greater than or equal to the number of blocks in the largest segment to
388   * avoid starvation of erased blocks.
389   */
390  uint32_t                       unavail_blocks;
391
392  uint32_t                       compact_segs;   /**< Max number of segs to
393                                                      compact in one pass. */
394  /**
395   * The number of segments when compaction occurs when writing.  In case the
396   * number of segments in the available queue is less than or equal to this
397   * number the compaction process will be triggered.  The available queue
398   * contains all segments with erased blocks.
399   */
400  uint32_t                       avail_compact_segs;
401  uint32_t                       info_level;     /**< Default info level. */
402} rtems_flashdisk_config;
403
404/*
405 * Driver flags.
406 */
407
408/**
409 * Leave the erasing of used segment to the background handler.
410 */
411#define RTEMS_FDISK_BACKGROUND_ERASE (1 << 0)
412
413/**
414 * Leave the compacting of of used segment to the background handler.
415 */
416#define RTEMS_FDISK_BACKGROUND_COMPACT (1 << 1)
417
418/**
419 * Check the pages during initialisation to see which pages are
420 * valid and which are not. This could slow down initialising the
421 * disk driver.
422 */
423#define RTEMS_FDISK_CHECK_PAGES (1 << 2)
424
425/**
426 * Blank check the flash device before writing to them. This is needed if
427 * you think you have a driver or device problem.
428 */
429#define RTEMS_FDISK_BLANK_CHECK_BEFORE_WRITE (1 << 3)
430
431/**
432 * Flash disk device driver initialization. Place in a table as the
433 * initialisation entry and remainder of the entries are the
434 * RTEMS block device generic handlers.
435 *
436 * @param major Flash disk major device number.
437 * @param minor Minor device number, not applicable.
438 * @param arg Initialization argument, not applicable.
439 * @return The rtems_device_driver is actually just
440 *         rtems_status_code.
441 */
442rtems_device_driver
443rtems_fdisk_initialize (rtems_device_major_number major,
444                        rtems_device_minor_number minor,
445                        void*                     arg);
446
447/**
448 * @brief External reference to the configuration. Please supply.
449 * Support is present in confdefs.h for providing this variable.
450 */
451extern const rtems_flashdisk_config rtems_flashdisk_configuration[];
452
453/**
454 * @brief External reference to the number of configurations. Please supply.
455 * Support is present in confdefs.h for providing this variable.
456 */
457extern uint32_t rtems_flashdisk_configuration_size;
458
459/** @} */
460
461#endif
Note: See TracBrowser for help on using the repository browser.