![]() |
|
|||
File indexing completed on 2025-05-11 08:24:13
0001 /* SPDX-License-Identifier: BSD-2-Clause */ 0002 0003 /** 0004 * @file 0005 * 0006 * @ingroup RTEMSFDisk 0007 * 0008 * @brief Interface to a Flash Disk Block Device 0009 * 0010 * This file defines the interface to a flash disk block device. 0011 */ 0012 0013 /* 0014 * Copyright (C) 2007 Chris Johns 0015 * 0016 * Redistribution and use in source and binary forms, with or without 0017 * modification, are permitted provided that the following conditions 0018 * are met: 0019 * 1. Redistributions of source code must retain the above copyright 0020 * notice, this list of conditions and the following disclaimer. 0021 * 2. Redistributions in binary form must reproduce the above copyright 0022 * notice, this list of conditions and the following disclaimer in the 0023 * documentation and/or other materials provided with the distribution. 0024 * 0025 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 0026 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 0027 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 0028 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 0029 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 0030 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 0031 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 0032 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 0033 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 0034 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 0035 * POSSIBILITY OF SUCH DAMAGE. 0036 */ 0037 0038 #if !defined (_RTEMS_FLASHDISK_H_) 0039 #define _RTEMS_FLASHDISK_H_ 0040 0041 #include <stdint.h> 0042 #include <sys/ioctl.h> 0043 0044 #include <rtems.h> 0045 0046 #ifdef __cplusplus 0047 extern "C" { 0048 #endif /* __cplusplus */ 0049 0050 /** 0051 * @defgroup RTEMSFDisk Flash Disk Device 0052 * 0053 * @ingroup rtems_blkdev 0054 * 0055 * Flash disk driver for RTEMS provides support for block based 0056 * file systems on flash devices. The driver is not a flash file 0057 * system nor does it try to compete with flash file systems. It 0058 * currently does not journal how-ever block sequence numbering 0059 * could be added to allow recovery of a past positions if 0060 * a power down occurred while being updated. 0061 * 0062 * This flash driver provides block device support for most flash 0063 * devices. The driver has been tested on NOR type devices such 0064 * as the AMLV160 or M28W160. Support for NAND type devices may 0065 * require driver changes to allow speedy recover of the block 0066 * mapping data and to also handle the current use of word programming. 0067 * Currently the page descriptors are stored in the first few pages 0068 * of each segment. 0069 * 0070 * The driver supports devices, segments and pages. You provide 0071 * to the driver the device descriptions as a table of device 0072 * descriptors. Each device descriptor contain a table of 0073 * segment descriptions or segment descriptors. The driver uses 0074 * this information to manage the devices. 0075 * 0076 * A device is made up of segments. These are also called 0077 * sectors or blocks. It is the smallest erasable part of a device. 0078 * A device can have differing size segments at different 0079 * offsets in the device. The segment descriptors support repeating 0080 * segments that are continuous in the device. The driver breaks the 0081 * segments up into pages. The first pages of a segment contain 0082 * the page descriptors. A page descriptor hold the page flags, 0083 * a CRC for the page of data and the block number the page 0084 * holds. The block can appear in any order in the devices. A 0085 * page is active if it hold a current block of data. If the 0086 * used bit is set the page is counted as used. A page moves 0087 * from erased to active to used then back to erased. If a block 0088 * is written that is already in a page, the block is written to 0089 * a new page the old page is flagged as used. 0090 * 0091 * At initialization time each segment's page descriptors are 0092 * read into memory and scanned to determine the active pages, 0093 * the used pages and the bad pages. If a segment has any erased 0094 * pages it is queue on the available queue. If the segment has 0095 * no erased pages it is queue on the used queue. 0096 * 0097 * The available queue is sorted from the least number available 0098 * to the most number of available pages. A segment that has just 0099 * been erased will placed at the end of the queue. A segment that 0100 * has only a few available pages will be used sooner and once 0101 * there are no available pages it is queued on the used queue. 0102 * The used queue hold segments that have no available pages and 0103 * is sorted from the least number of active pages to the most 0104 * number of active pages. 0105 * 0106 * The driver is required to compact segments. Compacting takes 0107 * the segment with the most number of available pages from the 0108 * available queue then takes segments with the least number of 0109 * active pages from the used queue until it has enough pages 0110 * to fill the empty segment. As the active pages are moved 0111 * they flagged as used and once the segment has only used pages 0112 * it is erased. 0113 * 0114 * A flash block driver like this never knows if a page is not 0115 * being used by the file-system. A typical file system is not 0116 * design with the idea of erasing a block on a disk once it is 0117 * not being used. The file-system will normally use a flag 0118 * or a location as a marker to say that part of the disk is 0119 * no longer in use. This means a number of blocks could be 0120 * held in active pages but are no in use by the file system. 0121 * The file system may also read blocks that have never been 0122 * written to disk. This complicates the driver and may make 0123 * the wear, usage and erase patterns harsher than a flash 0124 * file system. The driver may also suffer from problems if 0125 * power is lost. 0126 * 0127 * There are some flash disk specific IO control request types. 0128 * To use open the device and issue the ioctl() call. 0129 * 0130 * @code 0131 * int fd = open ("/dev/flashdisk0", O_WRONLY, 0); 0132 * if (fd < 0) 0133 * { 0134 * printf ("driver open failed: %s\n", strerror (errno)); 0135 * exit (1); 0136 * } 0137 * if (ioctl (fd, RTEMS_FDISK_IOCTL_ERASE_DISK) < 0) 0138 * { 0139 * printf ("driver erase failed: %s\n", strerror (errno)); 0140 * exit (1); 0141 * } 0142 * close (fd); 0143 * @endcode 0144 */ 0145 /**@{**/ 0146 0147 /** 0148 * @brief The base name of the flash disks. 0149 */ 0150 #define RTEMS_FLASHDISK_DEVICE_BASE_NAME "/dev/fdd" 0151 0152 #define RTEMS_FDISK_IOCTL_ERASE_DISK _IO('B', 128) 0153 #define RTEMS_FDISK_IOCTL_COMPACT _IO('B', 129) 0154 #define RTEMS_FDISK_IOCTL_ERASE_USED _IO('B', 130) 0155 #define RTEMS_FDISK_IOCTL_MONITORING _IO('B', 131) 0156 #define RTEMS_FDISK_IOCTL_INFO_LEVEL _IO('B', 132) 0157 #define RTEMS_FDISK_IOCTL_PRINT_STATUS _IO('B', 133) 0158 0159 /** 0160 * @brief Flash Disk Monitoring Data allows a user to obtain 0161 * the current status of the disk. 0162 */ 0163 typedef struct rtems_fdisk_monitor_data 0164 { 0165 uint32_t block_size; 0166 uint32_t block_count; 0167 uint32_t unavail_blocks; 0168 uint32_t device_count; 0169 uint32_t segment_count; 0170 uint32_t page_count; 0171 uint32_t blocks_used; 0172 uint32_t segs_available; 0173 uint32_t segs_used; 0174 uint32_t segs_failed; 0175 uint32_t seg_erases; 0176 uint32_t pages_desc; 0177 uint32_t pages_active; 0178 uint32_t pages_used; 0179 uint32_t pages_bad; 0180 uint32_t info_level; 0181 } rtems_fdisk_monitor_data; 0182 0183 /** 0184 * @brief Flash Segment Descriptor holds, number of continuous segments in the 0185 * device of this type, the base segment number in the device, the address 0186 * offset of the base segment in the device, and the size of segment. 0187 * 0188 * Typically this structure is part of a table of segments in the 0189 * device which is referenced in the flash disk configuration table. 0190 * The reference is kept in the driver and used all the time to 0191 * manage the flash device, therefore it must always exist. 0192 */ 0193 typedef struct rtems_fdisk_segment_desc 0194 { 0195 uint16_t count; /**< Number of segments of this type in a row. */ 0196 uint16_t segment; /**< The base segment number. */ 0197 uint32_t offset; /**< Address offset of base segment in device. */ 0198 uint32_t size; /**< Size of the segment in bytes. */ 0199 } rtems_fdisk_segment_desc; 0200 0201 /** 0202 * @brief Return the number of kilo-bytes. 0203 */ 0204 #define RTEMS_FDISK_KBYTES(_k) (UINT32_C(1024) * (_k)) 0205 0206 /** 0207 * Forward declaration of the device descriptor. 0208 */ 0209 struct rtems_fdisk_device_desc; 0210 0211 /** 0212 * @brief Flash Low Level driver handlers. 0213 * 0214 * Typically this structure is part of a table of handlers in the 0215 * device which is referenced in the flash disk configuration table. 0216 * The reference is kept in the driver and used all the time to 0217 * manage the flash device, therefore it must always exist. 0218 */ 0219 typedef struct rtems_fdisk_driver_handlers 0220 { 0221 /** 0222 * Read data from the device into the buffer. Return an errno 0223 * error number if the device cannot be read. A segment descriptor 0224 * can describe more than one segment in a device if the device has 0225 * repeating segments. The segment number is the device segment to 0226 * access and the segment descriptor must reference the segment 0227 * being requested. For example the segment number must resided in 0228 * the range [base, base + count). 0229 * 0230 * @param sd The segment descriptor. 0231 * @param device The device to read data from. 0232 * @param segment The segment within the device to read. 0233 * @param offset The offset in the segment to read. 0234 * @param buffer The buffer to read the data into. 0235 * @param size The amount of data to read. 0236 * @retval 0 No error. 0237 * @retval EIO The read did not complete. 0238 */ 0239 int (*read) (const rtems_fdisk_segment_desc* sd, 0240 uint32_t device, 0241 uint32_t segment, 0242 uint32_t offset, 0243 void* buffer, 0244 uint32_t size); 0245 0246 /** 0247 * Write data from the buffer to the device. Return an errno 0248 * error number if the device cannot be written to. A segment 0249 * descriptor can describe more than segment in a device if the 0250 * device has repeating segments. The segment number is the device 0251 * segment to access and the segment descriptor must reference 0252 * the segment being requested. For example the segment number must 0253 * resided in the range [base, base + count). 0254 * 0255 * @param sd The segment descriptor. 0256 * @param device The device to write data from. 0257 * @param segment The segment within the device to write to. 0258 * @param offset The offset in the segment to write. 0259 * @param buffer The buffer to write the data from. 0260 * @param size The amount of data to write. 0261 * @retval 0 No error. 0262 * @retval EIO The write did not complete or verify. 0263 */ 0264 int (*write) (const rtems_fdisk_segment_desc* sd, 0265 uint32_t device, 0266 uint32_t segment, 0267 uint32_t offset, 0268 const void* buffer, 0269 uint32_t size); 0270 0271 /** 0272 * Blank a segment in the device. Return an errno error number 0273 * if the device cannot be read or is not blank. A segment descriptor 0274 * can describe more than segment in a device if the device has 0275 * repeating segments. The segment number is the device segment to 0276 * access and the segment descriptor must reference the segment 0277 * being requested. For example the segment number must resided in 0278 * the range [base, base + count). 0279 * 0280 * @param sd The segment descriptor. 0281 * @param device The device to read data from. 0282 * @param segment The segment within the device to read. 0283 * @param offset The offset in the segment to checl. 0284 * @param size The amount of data to check. 0285 * @retval 0 No error. 0286 * @retval EIO The segment is not blank. 0287 */ 0288 int (*blank) (const rtems_fdisk_segment_desc* sd, 0289 uint32_t device, 0290 uint32_t segment, 0291 uint32_t offset, 0292 uint32_t size); 0293 0294 /** 0295 * Verify data in the buffer to the data in the device. Return an 0296 * errno error number if the device cannot be read. A segment 0297 * descriptor can describe more than segment in a device if the 0298 * device has repeating segments. The segment number is the 0299 * segment to access and the segment descriptor must reference 0300 * the device segment being requested. For example the segment number 0301 * must resided in the range [base, base + count). 0302 * 0303 * @param sd The segment descriptor. 0304 * @param device The device to verify data in. 0305 * @param segment The segment within the device to verify. 0306 * @param offset The offset in the segment to verify. 0307 * @param buffer The buffer to verify the data in the device with. 0308 * @param size The amount of data to verify. 0309 * @retval 0 No error. 0310 * @retval EIO The data did not verify. 0311 */ 0312 int (*verify) (const rtems_fdisk_segment_desc* sd, 0313 uint32_t device, 0314 uint32_t segment, 0315 uint32_t offset, 0316 const void* buffer, 0317 uint32_t size); 0318 0319 /** 0320 * Erase the segment. Return an errno error number if the 0321 * segment cannot be erased. A segment descriptor can describe 0322 * more than segment in a device if the device has repeating 0323 * segments. The segment number is the device segment to access and 0324 * the segment descriptor must reference the segment being requested. 0325 * 0326 * @param sd The segment descriptor. 0327 * @param device The device to erase the segment of. 0328 * @param segment The segment within the device to erase. 0329 * @retval 0 No error. 0330 * @retval EIO The segment was not erased. 0331 */ 0332 int (*erase) (const rtems_fdisk_segment_desc* sd, 0333 uint32_t device, 0334 uint32_t segment); 0335 0336 /** 0337 * Erase the device. Return an errno error number if the 0338 * segment cannot be erased. A segment descriptor can describe 0339 * more than segment in a device if the device has repeating 0340 * segments. The segment number is the segment to access and 0341 * the segment descriptor must reference the segment being requested. 0342 * 0343 * @param sd The segment descriptor. 0344 * @param device The device to erase. 0345 * @retval 0 No error. 0346 * @retval EIO The device was not erased. 0347 */ 0348 int (*erase_device) (const struct rtems_fdisk_device_desc* dd, 0349 uint32_t device); 0350 0351 } rtems_fdisk_driver_handlers; 0352 0353 /** 0354 * @brief Flash Device Descriptor holds the segments in a device. 0355 * 0356 * The placing of the segments in a device decriptor allows the low level 0357 * driver to share the segment descriptors for a number of devices. 0358 * 0359 * Typically this structure is part of a table of segments in the 0360 * device which is referenced in the flash disk configuration table. 0361 * The reference is kept in the driver and used all the time to 0362 * manage the flash device, therefore it must always exist. 0363 */ 0364 typedef struct rtems_fdisk_device_desc 0365 { 0366 uint32_t segment_count; /**< Number of segments. */ 0367 const rtems_fdisk_segment_desc* segments; /**< Array of segments. */ 0368 const rtems_fdisk_driver_handlers* flash_ops; /**< Device handlers. */ 0369 } rtems_fdisk_device_desc; 0370 0371 /** 0372 * @brief RTEMS Flash Disk configuration table used to initialise the 0373 * driver. 0374 * 0375 * The unavailable blocks count is the number of blocks less than the 0376 * available number of blocks the file system is given. This means there 0377 * will always be that number of blocks available when the file system 0378 * thinks the disk is full. The compaction code needs blocks to compact 0379 * with so you will never be able to have all the blocks allocated to the 0380 * file system and be able to full the disk. 0381 * 0382 * The compacting segment count is the number of segments that are 0383 * moved into a new segment. A high number will mean more segments with 0384 * low active page counts and high used page counts will be moved into 0385 * avaliable pages how-ever this extends the compaction time due to 0386 * time it takes the erase the pages. There is no pont making this number 0387 * greater than the maximum number of pages in a segment. 0388 * 0389 * The available compacting segment count is the level when compaction occurs 0390 * when writing. If you set this to 0 then compaction will fail because 0391 * there will be no segments to compact into. 0392 * 0393 * The info level can be 0 for off with error, and abort messages allowed. 0394 * Level 1 is warning messages, level 1 is informational messages, and level 3 0395 * is debugging type prints. The info level can be turned off with a compile 0396 * time directive on the command line to the compiler of: 0397 * 0398 * -DRTEMS_FDISK_TRACE=0 0399 */ 0400 typedef struct rtems_flashdisk_config 0401 { 0402 uint32_t block_size; /**< The block size. */ 0403 uint32_t device_count; /**< The number of devices. */ 0404 const rtems_fdisk_device_desc* devices; /**< The device descriptions. */ 0405 uint32_t flags; /**< Set of flags to control 0406 driver. */ 0407 /** 0408 * Number of blocks not available to the file system. This number must be 0409 * greater than or equal to the number of blocks in the largest segment to 0410 * avoid starvation of erased blocks. 0411 */ 0412 uint32_t unavail_blocks; 0413 0414 uint32_t compact_segs; /**< Max number of segs to 0415 compact in one pass. */ 0416 /** 0417 * The number of segments when compaction occurs when writing. In case the 0418 * number of segments in the available queue is less than or equal to this 0419 * number the compaction process will be triggered. The available queue 0420 * contains all segments with erased blocks. 0421 */ 0422 uint32_t avail_compact_segs; 0423 uint32_t info_level; /**< Default info level. */ 0424 } rtems_flashdisk_config; 0425 0426 /* 0427 * Driver flags. 0428 */ 0429 0430 /** 0431 * Leave the erasing of used segment to the background handler. 0432 */ 0433 #define RTEMS_FDISK_BACKGROUND_ERASE (1 << 0) 0434 0435 /** 0436 * Leave the compacting of of used segment to the background handler. 0437 */ 0438 #define RTEMS_FDISK_BACKGROUND_COMPACT (1 << 1) 0439 0440 /** 0441 * Check the pages during initialisation to see which pages are 0442 * valid and which are not. This could slow down initialising the 0443 * disk driver. 0444 */ 0445 #define RTEMS_FDISK_CHECK_PAGES (1 << 2) 0446 0447 /** 0448 * Blank check the flash device before writing to them. This is needed if 0449 * you think you have a driver or device problem. 0450 */ 0451 #define RTEMS_FDISK_BLANK_CHECK_BEFORE_WRITE (1 << 3) 0452 0453 /** 0454 * Flash disk device driver initialization. Place in a table as the 0455 * initialisation entry and remainder of the entries are the 0456 * RTEMS block device generic handlers. 0457 * 0458 * @param major Flash disk major device number. 0459 * @param minor Minor device number, not applicable. 0460 * @param arg Initialization argument, not applicable. 0461 * @return The rtems_device_driver is actually just 0462 * rtems_status_code. 0463 */ 0464 rtems_device_driver 0465 rtems_fdisk_initialize (rtems_device_major_number major, 0466 rtems_device_minor_number minor, 0467 void* arg); 0468 0469 /** 0470 * @brief External reference to the configuration. Please supply. 0471 * Support is present in confdefs.h for providing this variable. 0472 */ 0473 extern const rtems_flashdisk_config rtems_flashdisk_configuration[]; 0474 0475 /** 0476 * @brief External reference to the number of configurations. Please supply. 0477 * Support is present in confdefs.h for providing this variable. 0478 */ 0479 extern uint32_t rtems_flashdisk_configuration_size; 0480 0481 /** @} */ 0482 0483 #ifdef __cplusplus 0484 } 0485 #endif /* __cplusplus */ 0486 0487 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |