source: rtems/cpukit/include/rtems/flashdisk.h @ 2cec5ac

5
Last change on this file since 2cec5ac was 0fb724a, checked in by Sebastian Huber <sebastian.huber@…>, on 03/12/18 at 09:04:11

libblock: C++ compatibility

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