summaryrefslogtreecommitdiffstats
path: root/cpukit/libblock/include/rtems/flashdisk.h
blob: c24b9b08bec831e6dfd61f6f8fe4f2fd4665f450 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
/*
 * flashdisk.h -- Flash disk block device implementation
 *
 * Copyright (C) 2007 Chris Johns
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rtems.com/license/LICENSE.
 *
 * $Id$
 */

#if !defined (_RTEMS_FLASHDISK_H_)
#define _RTEMS_FLASHDISK_H_

#include <stdint.h>
#include <sys/ioctl.h>

#include <rtems.h>

/**
 * The base name of the flash disks.
 */
#define RTEMS_FLASHDISK_DEVICE_BASE_NAME "/dev/fdd"

/**
 * Flash disk specific ioctl request types. To use open the
 * device and issue the ioctl call.
 *
 * @code
 *  int fd = open ("/dev/flashdisk0", O_WRONLY, 0);
 *  if (fd < 0)
 *  {
 *    printf ("driver open failed: %s\n", strerror (errno));
 *    exit (1);
 *  }
 *  if (ioctl (fd, RTEMS_FDISK_IOCTL_ERASE_DISK) < 0)
 *  {
 *    printf ("driver erase failed: %s\n", strerror (errno));
 *    exit (1);
 *  }
 *  close (fd);
 * @endcode
 */
#define RTEMS_FDISK_IOCTL_ERASE_DISK   _IO('B', 128)
#define RTEMS_FDISK_IOCTL_COMPACT      _IO('B', 129)
#define RTEMS_FDISK_IOCTL_ERASE_USED   _IO('B', 130)
#define RTEMS_FDISK_IOCTL_MONITORING   _IO('B', 131)
#define RTEMS_FDISK_IOCTL_INFO_LEVEL   _IO('B', 132)
#define RTEMS_FDISK_IOCTL_PRINT_STATUS _IO('B', 133)

/**
 * Flash Disk Monitoring Data allows a user to obtain
 * the current status of the disk.
 */
typedef struct rtems_fdisk_monitor_data
{
  uint32_t block_size;
  uint32_t block_count;
  uint32_t unavail_blocks;
  uint32_t device_count;
  uint32_t segment_count;
  uint32_t page_count;
  uint32_t blocks_used;
  uint32_t segs_available;
  uint32_t segs_used;
  uint32_t segs_failed;
  uint32_t seg_erases;
  uint32_t pages_desc;
  uint32_t pages_active;
  uint32_t pages_used;
  uint32_t pages_bad;
  uint32_t info_level;
} rtems_fdisk_monitor_data;

/**
 * Flash Segment Descriptor holds, number of continuous segments in the
 * device of this type, the base segment number in the device, the
 * address offset of the base segment in the device, and the size of
 * segment.
 *
 * Typically this structure is part of a table of segments in the
 * device which is referenced in the flash disk configuration table.
 * The reference is kept in the driver and used all the time to
 * manage the flash device, therefore it must always exist.
 */
typedef struct rtems_fdisk_segment_desc
{
  uint16_t count;    /**< Number of segments of this type in a row. */
  uint16_t segment;  /**< The base segment number. */
  uint32_t offset;   /**< Address offset of base segment in device. */
  uint32_t size;     /**< Size of the segment in bytes. */
} rtems_fdisk_segment_desc;

/**
 * Return the number of kilo-bytes.
 */
#define RTEMS_FDISK_KBYTES(_k) (UINT32_C(1024) * (_k))

/**
 * Forward declaration of the device descriptor.
 */
struct rtems_fdisk_device_desc;

/**
 * Flash Low Level driver handlers.

 * Typically this structure is part of a table of handlers in the
 * device which is referenced in the flash disk configuration table.
 * The reference is kept in the driver and used all the time to
 * manage the flash device, therefore it must always exist.
 */
typedef struct rtems_fdisk_driver_handlers
{
  /**
   * Read data from the device into the buffer. Return an errno
   * error number if the device cannot be read. A segment descriptor
   * can describe more than one segment in a device if the device has
   * repeating segments. The segment number is the device segment to
   * access and the segment descriptor must reference the segment
   * being requested. For example the segment number must resided in
   * the range [base, base + count).
   *
   * @param sd The segment descriptor.
   * @param device The device to read data from.
   * @param segment The segment within the device to read.
   * @param offset The offset in the segment to read.
   * @param buffer The buffer to read the data into.
   * @param size The amount of data to read.
   * @retval 0 No error.
   * @retval EIO The read did not complete.
   */
  int (*read) (const rtems_fdisk_segment_desc* sd,
               uint32_t                        device,
               uint32_t                        segment,
               uint32_t                        offset,
               void*                           buffer,
               uint32_t                        size);

  /**
   * Write data from the buffer to the device. Return an errno
   * error number if the device cannot be written to. A segment
   * descriptor can describe more than segment in a device if the
   * device has repeating segments. The segment number is the device
   * segment to access and the segment descriptor must reference
   * the segment being requested. For example the segment number must
   * resided in the range [base, base + count).
   *
   * @param sd The segment descriptor.
   * @param device The device to write data from.
   * @param segment The segment within the device to write to.
   * @param offset The offset in the segment to write.
   * @param buffer The buffer to write the data from.
   * @param size The amount of data to write.
   * @retval 0 No error.
   * @retval EIO The write did not complete or verify.
   */
  int (*write) (const rtems_fdisk_segment_desc* sd,
                uint32_t                        device,
                uint32_t                        segment,
                uint32_t                        offset,
                const void*                     buffer,
                uint32_t                        size);

  /**
   * Blank a segment in the device. Return an errno error number
   * if the device cannot be read or is not blank. A segment descriptor
   * can describe more than segment in a device if the device has
   * repeating segments. The segment number is the device segment to
   * access and the segment descriptor must reference the segment
   * being requested. For example the segment number must resided in
   * the range [base, base + count).
   *
   * @param sd The segment descriptor.
   * @param device The device to read data from.
   * @param segment The segment within the device to read.
   * @param offset The offset in the segment to checl.
   * @param size The amount of data to check.
   * @retval 0 No error.
   * @retval EIO The segment is not blank.
   */
  int (*blank) (const rtems_fdisk_segment_desc* sd,
                uint32_t                        device,
                uint32_t                        segment,
                uint32_t                        offset,
                uint32_t                        size);

  /**
   * Verify data in the buffer to the data in the device. Return an
   * errno error number if the device cannot be read. A segment
   * descriptor can describe more than segment in a device if the
   * device has repeating segments. The segment number is the
   * segment to access and the segment descriptor must reference
   * the device segment being requested. For example the segment number
   * must resided in the range [base, base + count).
   *
   * @param sd The segment descriptor.
   * @param device The device to verify data in.
   * @param segment The segment within the device to verify.
   * @param offset The offset in the segment to verify.
   * @param buffer The buffer to verify the data in the device with.
   * @param size The amount of data to verify.
   * @retval 0 No error.
   * @retval EIO The data did not verify.
   */
  int (*verify) (const rtems_fdisk_segment_desc* sd,
                 uint32_t                        device,
                 uint32_t                        segment,
                 uint32_t                        offset,
                 const void*                     buffer,
                 uint32_t                        size);

  /**
   * Erase the segment. Return an errno error number if the
   * segment cannot be erased. A segment descriptor can describe
   * more than segment in a device if the device has repeating
   * segments. The segment number is the device segment to access and
   * the segment descriptor must reference the segment being requested.
   *
   * @param sd The segment descriptor.
   * @param device The device to erase the segment of.
   * @param segment The segment within the device to erase.
   * @retval 0 No error.
   * @retval EIO The segment was not erased.
   */
  int (*erase) (const rtems_fdisk_segment_desc* sd,
                uint32_t                        device,
                uint32_t                        segment);

  /**
   * Erase the device. Return an errno error number if the
   * segment cannot be erased. A segment descriptor can describe
   * more than segment in a device if the device has repeating
   * segments. The segment number is the segment to access and
   * the segment descriptor must reference the segment being requested.
   *
   * @param sd The segment descriptor.
   * @param device The device to erase.
   * @retval 0 No error.
   * @retval EIO The device was not erased.
   */
  int (*erase_device) (const struct rtems_fdisk_device_desc* dd,
                       uint32_t                              device);

} rtems_fdisk_driver_handlers;

/**
 * Flash Device Descriptor holds the segments in a device. The
 * placing of the segments in a device decriptor allows the
 * low level driver to share the segment descriptors for a
 * number of devices.
 *
 * Typically this structure is part of a table of segments in the
 * device which is referenced in the flash disk configuration table.
 * The reference is kept in the driver and used all the time to
 * manage the flash device, therefore it must always exist.
 */
typedef struct rtems_fdisk_device_desc
{
  uint32_t                           segment_count; /**< Number of segments. */
  const rtems_fdisk_segment_desc*    segments;      /**< Array of segments. */
  const rtems_fdisk_driver_handlers* flash_ops;     /**< Device handlers. */
} rtems_fdisk_device_desc;

/**
 * RTEMS Flash Disk configuration table used to initialise the
 * driver.
 *
 * The unavailable blocks count is the number of blocks less than the
 * available number of blocks the file system is given. This means there
 * will always be that number of blocks available when the file system
 * thinks the disk is full. The compaction code needs blocks to compact
 * with so you will never be able to have all the blocks allocated to the
 * file system and be able to full the disk.
 *
 * The compacting segment count is the number of segments that are
 * moved into a new segment. A high number will mean more segments with
 * low active page counts and high used page counts will be moved into
 * avaliable pages how-ever this extends the compaction time due to
 * time it takes the erase the pages. There is no pont making this number
 * greater than the maximum number of pages in a segment.
 *
 * The available compacting segment count is the level when compaction occurs
 * when writing. If you set this to 0 then compaction will fail because
 * there will be no segments to compact into.
 *
 * The info level can be 0 for off with error, and abort messages allowed.
 * Level 1 is warning messages, level 1 is informational messages, and level 3
 * is debugging type prints. The info level can be turned off with a compile
 * time directive on the command line to the compiler of:
 *
 *     -DRTEMS_FDISK_TRACE=0
 */
typedef struct rtems_flashdisk_config
{
  uint32_t                       block_size;     /**< The block size. */
  uint32_t                       device_count;   /**< The number of devices. */
  const rtems_fdisk_device_desc* devices;        /**< The device descriptions. */
  uint32_t                       flags;          /**< Set of flags to control
                                                      driver. */
  uint32_t                       unavail_blocks; /**< Number of blocks not
                                                      available to the file sys. */
  uint32_t                       compact_segs;   /**< Max number of segs to
                                                      compact in one pass. */
  uint32_t                       avail_compact_segs; /**< The number of segments
                                                          when compaction occurs
                                                          when writing. */
  uint32_t                       info_level;     /**< Default info level. */
} rtems_flashdisk_config;

/*
 * Driver flags.
 */

/**
 * Leave the erasing of used segment to the background handler.
 */
#define RTEMS_FDISK_BACKGROUND_ERASE (1 << 0)

/**
 * Leave the compacting of of used segment to the background handler.
 */
#define RTEMS_FDISK_BACKGROUND_COMPACT (1 << 1)

/**
 * Check the pages during initialisation to see which pages are
 * valid and which are not. This could slow down initialising the
 * disk driver.
 */
#define RTEMS_FDISK_CHECK_PAGES (1 << 2)

/**
 * Blank check the flash device before writing to them. This is needed if
 * you think you have a driver or device problem.
 */
#define RTEMS_FDISK_BLANK_CHECK_BEFORE_WRITE (1 << 3)

/**
 * Flash disk device driver initialization. Place in a table as the
 * initialisation entry and remainder of the entries are the
 * RTEMS block device generic handlers.
 *
 * @param major Flash disk major device number.
 * @param minor Minor device number, not applicable.
 * @param arg Initialization argument, not applicable.
 * @return The rtems_device_driver is actually just
 *         rtems_status_code.
 */
rtems_device_driver
rtems_fdisk_initialize (rtems_device_major_number major,
                        rtems_device_minor_number minor,
                        void*                     arg);

/**
 * External reference to the configuration. Please supply.
 * Support is present in confdefs.h for providing this variable.
 */
extern const rtems_flashdisk_config rtems_flashdisk_configuration[];

/**
 * External reference to the number of configurations. Please supply.
 * Support is present in confdefs.h for providing this variable.
 */
extern uint32_t rtems_flashdisk_configuration_size;

#endif