1 /* 2 This file is part of UFFS, the Ultra-low-cost Flash File System. 3 4 Copyright (C) 2005-2009 Ricky Zheng <[email protected]> 5 6 UFFS is free software; you can redistribute it and/or modify it under 7 the GNU Library General Public License as published by the Free Software 8 Foundation; either version 2 of the License, or (at your option) any 9 later version. 10 11 UFFS is distributed in the hope that it will be useful, but WITHOUT 12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 or GNU Library General Public License, as applicable, for more details. 15 16 You should have received a copy of the GNU General Public License 17 and GNU Library General Public License along with UFFS; if not, write 18 to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 Boston, MA 02110-1301, USA. 20 21 As a special exception, if other files instantiate templates or use 22 macros or inline functions from this file, or you compile this file 23 and link it with other works to produce a work based on this file, 24 this file does not by itself cause the resulting work to be covered 25 by the GNU General Public License. However the source code for this 26 file must still be made available in accordance with section (3) of 27 the GNU General Public License v2. 28 29 This exception does not invalidate any other reasons why a work based 30 on this file might be covered by the GNU General Public License. 31 */ 32 33 /** 34 * \file uffs_public.h 35 * \brief flash interface for UFFS 36 * \author Ricky Zheng 37 */ 38 39 #ifndef _UFFS_FLASH_H_ 40 #define _UFFS_FLASH_H_ 41 42 #include "uffs/uffs_types.h" 43 #include "uffs/uffs_core.h" 44 #include "uffs/uffs_device.h" 45 #include "uffs/uffs_fs.h" 46 47 #ifdef __cplusplus 48 extern "C"{ 49 #endif 50 51 52 /** ECC options (uffs_StorageAttrSt.ecc_opt) */ 53 #define UFFS_ECC_NONE 0 //!< do not use ECC 54 #define UFFS_ECC_SOFT 1 //!< UFFS calculate the ECC 55 #define UFFS_ECC_HW 2 //!< Flash driver(or by hardware) calculate the ECC 56 #define UFFS_ECC_HW_AUTO 3 //!< Hardware calculate the ECC and automatically write to spare. 57 58 #define UFFS_ECC_OPTION_STRING \ 59 { "none", "soft", "hw", "auto" } // index is the ecc option value. 60 61 /** spare layout options (uffs_StorageAttrSt.layout_opt) */ 62 #define UFFS_LAYOUT_UFFS 0 //!< do layout by dev->attr information 63 #define UFFS_LAYOUT_FLASH 1 //!< flash driver do the layout 64 65 #define UFFS_SPARE_LAYOUT_SIZE 6 //!< maximum spare layout array size, 2 segments 66 67 /** flash operation return code */ 68 #define UFFS_FLASH_NO_ERR 0 //!< no error 69 #define UFFS_FLASH_ECC_OK 1 //!< bit-flip found, but corrected by ECC 70 #define UFFS_FLASH_NOT_SEALED 2 //!< page spare area is not sealed properly (only for ReadPageWithLayout()) 71 #define UFFS_FLASH_IO_ERR -1 //!< I/O error 72 #define UFFS_FLASH_ECC_FAIL -2 //!< ECC failed 73 #define UFFS_FLASH_BAD_BLK -3 //!< bad block 74 #define UFFS_FLASH_CRC_ERR -4 //!< CRC failed 75 #define UFFS_FLASH_UNKNOWN_ERR -100 //!< unkown error? 76 77 #define UFFS_FLASH_HAVE_ERR(e) ((e) < 0) 78 79 #if defined(CONFIG_BAD_BLOCK_POLICY_STRICT) 80 # define UFFS_FLASH_IS_BAD_BLOCK(e) \ 81 ((e) == UFFS_FLASH_ECC_FAIL || (e) == UFFS_FLASH_ECC_OK || (e) == UFFS_FLASH_BAD_BLK || (e) == UFFS_FLASH_CRC_ERR) 82 #else 83 # define UFFS_FLASH_IS_BAD_BLOCK(e) \ 84 ((e) == UFFS_FLASH_ECC_FAIL || (e) == UFFS_FLASH_BAD_BLK || (e) == UFFS_FLASH_CRC_ERR) 85 #endif 86 87 88 /** defines for page info (data length and data sum) */ 89 #define UFFS_PAGE_INFO_CLEAN 0xFFFFFFFF 90 #define UFFS_PAGE_INFO_IOERR 0xDEADFFFF 91 #define UFFS_PAGE_GET_LEN(info) (info & 0xFFFF) 92 #define UFFS_PAGE_GET_DSUM(info) (info >> 16) 93 #define UFFS_PAGE_MAKE_INFO(d_len, d_sum) ((d_sum << 16) | d_len) 94 95 /** 96 * \struct uffs_StorageAttrSt 97 * \brief uffs device storage attribute, provide by nand specific file 98 */ 99 struct uffs_StorageAttrSt { 100 u32 total_blocks; //!< total blocks in this chip 101 u16 page_data_size; //!< page data size (physical page data size, e.g. 512) 102 u16 pages_per_block; //!< pages per block 103 u8 spare_size; //!< page spare size (physical page spare size, e.g. 16) 104 u8 block_status_offs; //!< block status byte offset in spare 105 int ecc_opt; //!< ecc option ( #UFFS_ECC_[NONE|SOFT|HW|HW_AUTO] ) 106 int layout_opt; //!< layout option (#UFFS_LAYOUT_UFFS or #UFFS_LAYOUT_FLASH) 107 int ecc_size; //!< ecc size in bytes 108 const u8 *ecc_layout; //!< page data ECC layout: [ofs1, size1, ofs2, size2, ..., 0xFF, 0] 109 const u8 *data_layout; //!< spare data layout: [ofs1, size1, ofs2, size2, ..., 0xFF, 0] 110 u8 _uffs_ecc_layout[UFFS_SPARE_LAYOUT_SIZE]; //!< uffs spare ecc layout 111 u8 _uffs_data_layout[UFFS_SPARE_LAYOUT_SIZE]; //!< uffs spare data layout 112 void *_private; //!< private data for storage attribute 113 }; 114 115 116 /** 117 * \struct uffs_FlashOpsSt 118 * \brief low level flash operations, should be implement in flash driver 119 */ 120 struct uffs_FlashOpsSt { 121 /** 122 * Initilize flash driver, called once when UFFS initilize partition 123 * 124 * \return 0 if no error, return -1 when failed. 125 * 126 * \note This function is optional. 127 */ 128 int (*InitFlash)(uffs_Device *dev); 129 130 /** 131 * Release flash driver, called once when UFFS unmount partition 132 * 133 * \return 0 if no error, return -1 when failed. 134 * 135 * \note This function is optional. 136 */ 137 int (*ReleaseFlash)(uffs_Device *dev); 138 139 /** 140 * Read a full nand page, UFFS do the layout. 141 * 142 * \param[out] ecc ecc of page data 143 * if ecc_opt is UFFS_ECC_HW, flash driver must calculate and return ecc of data(if ecc != NULL). 144 * if ecc_opt is UFFS_ECC_HW_AUTO, flash driver do ecc correction before return data and flash driver do not need to return ecc. 145 * if ecc_opt is UFFS_ECC_NONE or UFFS_ECC_SOFT, flash driver do not need to calculate data ecc and return ecc. 146 * 147 * \return #UFFS_FLASH_NO_ERR: success and/or has no flip bits. 148 * #UFFS_FLASH_IO_ERR: I/O error, expect retry ? 149 * #UFFS_FLASH_ECC_FAIL: page data has flip bits and ecc correct failed (when ecc_opt == UFFS_ECC_HW_AUTO) 150 * #UFFS_FLASH_ECC_OK: page data has flip bits and corrected by ecc (when ecc_opt == UFFS_ECC_HW_AUTO) 151 * #UFFS_FLASH_BAD_BLK: if the block is a bad block (e.g., the bad block mark byte is not 0xFF). 152 * 153 * \note if data is NULL, do not return data; if spare is NULL, do not return spare; if both data and spare are all NULL, 154 * then read bad block mark and return UFFS_FLASH_BAD_BLK if bad block mark is not 0xFF. 155 * 156 * \note pad 0xFF for calculating ECC if len < page_data_size 157 */ 158 int (*ReadPage)(uffs_Device *dev, u32 block, u32 page, u8 *data, int data_len, u8 *ecc, 159 u8 *spare, int spare_len); 160 161 /** 162 * Read a full nand page, driver do the layout. 163 * 164 * \param[out] ecc ecc of page data 165 * if ecc_opt is UFFS_ECC_HW, flash driver must calculate and return ecc of data(if ecc != NULL). 166 * if ecc_opt is UFFS_ECC_HW_AUTO, flash driver do ecc correction before return data and flash driver do not need to return ecc. 167 * if ecc_opt is UFFS_ECC_NONE or UFFS_ECC_SOFT, flash driver do not need calculate data ecc and return ecc. 168 * 169 * \param[out] ecc_store ecc store on spare area 170 * if ecc_opt is UFFS_ECC_NONE or UFFS_ECC_HW_AUTO, do not need to return ecc_store. 171 * 172 * \note flash driver must provide this function if layout_opt is UFFS_LAYOUT_FLASH. 173 * UFFS will use this function (if exist) prio to 'ReadPageSpare()' 174 * 175 * \return #UFFS_FLASH_NO_ERR: success 176 * #UFFS_FLASH_IO_ERR: I/O error, expect retry ? 177 * #UFFS_FLASH_ECC_FAIL: page data has flip bits and ecc correct failed (when ecc_opt == UFFS_ECC_HW_AUTO) 178 * #UFFS_FLASH_ECC_OK: page data has flip bits and corrected by ecc (when ecc_opt == UFFS_ECC_HW_AUTO) 179 * #UFFS_FLASH_BAD_BLK: if the block is a bad block (e.g., the bad block mark byte is not 0xFF) 180 * #UFFS_FLASH_NOT_SEALED: if the page spare is not sealed properly 181 * 182 * \note if data is NULL, do not return data; if ts is NULL, do not read tag; if both data and ts are NULL, 183 * then read bad block mark and return UFFS_FLASH_BAD_BLK if bad block mark is not 0xFF. 184 * 185 * \note flash driver DO NOT need to do ecc correction for tag, 186 * UFFS will take care of tag ecc. 187 */ 188 int (*ReadPageWithLayout)(uffs_Device *dev, u32 block, u32 page, u8* data, int data_len, u8 *ecc, 189 uffs_TagStore *ts, u8 *ecc_store); 190 191 /** 192 * Write a full page, UFFS do the layout for spare area. 193 * 194 * \note If you have ecc_opt UFFS_ECC_HW or UFFS_ECC_HW_AUTO, you MUST implement WritePageWithLayout(). 195 * Implement WritePage() function if you have ecc_opt UFFS_ECC_NONE or UFFS_ECC_SOFT and 196 * WritePageWithLayout() is not implemented. 197 * 198 * \note If data == NULL && spare == NULL, driver should mark this block as a 'bad block'. 199 * 200 * \return #UFFS_FLASH_NO_ERR: success 201 * #UFFS_FLASH_IO_ERR: I/O error, expect retry ? 202 * #UFFS_FLASH_BAD_BLK: a bad block detected. 203 */ 204 int (*WritePage)(uffs_Device *dev, u32 block, u32 page, 205 const u8 *data, int data_len, const u8 *spare, int spare_len); 206 207 /** 208 * Write full page, flash driver do the layout for spare area. 209 * 210 * \note if layout_opt is UFFS_LAYOUT_FLASH or ecc_opt is UFFS_ECC_HW/UFFS_ECC_HW_AUTO, flash driver MUST implement 211 * this function. UFFS will use this function (if provided) prio to 'WritePage()' 212 * 213 * \param[in] ecc ecc of data. if ecc_opt is UFFS_ECC_SOFT and this function is implemented, 214 * UFFS will calculate page data ecc and pass it to WritePageWithLayout(). 215 * if ecc_opt is UFFS_ECC_NONE/UFFS_ECC_HW/UFFS_ECC_HW_AUTO, UFFS pass ecc = NULL. 216 * 217 * \note If data == NULL && ts == NULL, driver should mark this block as a 'bad block'. 218 * 219 * \return #UFFS_FLASH_NO_ERR: success 220 * #UFFS_FLASH_IO_ERR: I/O error, expect retry ? 221 * #UFFS_FLASH_BAD_BLK: a bad block detected. 222 */ 223 int (*WritePageWithLayout)(uffs_Device *dev, u32 block, u32 page, 224 const u8 *data, int data_len, const u8 *ecc, const uffs_TagStore *ts); 225 226 /** 227 * Check block status. 228 * 229 * \note flash driver may maintain a bad block table to speed up bad block checking or 230 * it will require one or two read spare I/O to check block status. 231 * 232 * \note if this function is not implented by driver, UFFS check the block_status byte in spare. 233 * 234 * \return 1 if it's a bad block, 0 if it's not. 235 */ 236 int (*IsBadBlock)(uffs_Device *dev, u32 block); 237 238 /** 239 * Mark a new bad block. 240 * 241 * \note if this function is not implemented, UFFS mark bad block by call 'WritePage()/WritePageWithLayout()' 242 * with: data == NULL && spare == NULL && ts == NULL. 243 * 244 * \return 0 if success, otherwise return -1. 245 */ 246 int (*MarkBadBlock)(uffs_Device *dev, u32 block); 247 248 /** 249 * Erase a block, driver MUST implement this function. 250 * 251 * \return #UFFS_FLASH_NO_ERR: success 252 * #UFFS_FLASH_IO_ERR: I/O error, expect retry ? 253 * #UFFS_FLASH_BAD_BLK: a bad block detected. 254 */ 255 int (*EraseBlock)(uffs_Device *dev, u32 block); 256 }; 257 258 /** make spare from tag store and ecc */ 259 void uffs_FlashMakeSpare(uffs_Device *dev, const uffs_TagStore *ts, const u8 *ecc, u8* spare); 260 261 /** unload tag and ecc from spare */ 262 void uffs_FlashUnloadSpare(uffs_Device *dev, const u8 *spare, struct uffs_TagStoreSt *ts, u8 *ecc); 263 264 /** read page spare and fill to tag */ 265 int uffs_FlashReadPageTag(uffs_Device *dev, int block, int page, uffs_Tags *tag); 266 267 /** read page data to page buf and do ECC correct */ 268 int uffs_FlashReadPage(uffs_Device *dev, int block, int page, uffs_Buf *buf, UBOOL skip_ecc); 269 270 /** write page data and spare */ 271 int uffs_FlashWritePageCombine(uffs_Device *dev, int block, int page, uffs_Buf *buf, uffs_Tags *tag); 272 273 /** Mark this block as bad block */ 274 int uffs_FlashMarkBadBlock(uffs_Device *dev, int block); 275 276 /** Is this block a bad block ? */ 277 UBOOL uffs_FlashIsBadBlock(uffs_Device *dev, int block); 278 279 /** Erase flash block */ 280 int uffs_FlashEraseBlock(uffs_Device *dev, int block); 281 282 /* mark a clean page as 'dirty' (and 'invalid') */ 283 int uffs_FlashMarkDirtyPage(uffs_Device *dev, uffs_BlockInfo *bc, int page); 284 285 /* check if the block pages are all clean */ 286 URET uffs_FlashCheckErasedBlock(uffs_Device *dev, int block); 287 288 /** 289 * get page head info 290 * 291 * \return #UFFS_PAGE_INFO_IOERR if I/O error, otherwise return page info 292 */ 293 u32 uffs_FlashGetPageInfo(uffs_Device *dev, int block, int page); 294 295 /** load uffs_FileInfo from flash storage */ 296 URET uffs_FlashReadFileinfoPhy(uffs_Device *dev, int block, int page, uffs_FileInfo *info); 297 298 /** 299 * Initialize UFFS flash interface 300 */ 301 URET uffs_FlashInterfaceInit(uffs_Device *dev); 302 303 /** 304 * Release UFFS flash interface 305 */ 306 URET uffs_FlashInterfaceRelease(uffs_Device *dev); 307 308 #ifdef __cplusplus 309 } 310 #endif 311 #endif 312