1 // Copyright 2018 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #pragma once 6 7 #include <inc/config.h> 8 9 #if INC_FTL_NDM 10 #include <errno.h> 11 #include <string.h> 12 #include <sys.h> 13 #include <kprivate/ftl_vc.h> 14 #include <kprivate/ndm.h> 15 #include <kprivate/ftl_mc.h> 16 17 /***********************************************************************/ 18 /* Configuration */ 19 /***********************************************************************/ 20 #define FTLN_LEGACY TRUE // TRUE to be backward compatible 21 #define INC_ELIST TRUE // if true, write erased blocks list 22 #define DEBUG_ELIST FALSE 23 #ifndef FTLN_DEBUG 24 #define FTLN_DEBUG TRUE 25 #endif 26 #ifndef FTLN_DEBUG_PTR 27 #define FTLN_DEBUG_PTR FALSE 28 #endif 29 #if !FTLN_LEGACY 30 #define FTLN_3B_PN TRUE // if true, use 3B page numbers 31 #endif 32 33 /***********************************************************************/ 34 /* Symbol Definitions */ 35 /***********************************************************************/ 36 #define FTLN_MIN_FREE_BLKS 4 37 38 // 39 // FTL Flag Values 40 // 41 #define FTLN_FAT_VOL (1 << 0) // TargetFAT volume 42 #define FTLN_XFS_VOL (1 << 1) // TargetXFS volume 43 #define FTLN_FATAL_ERR (1 << 2) // fatal I/O error has occurred 44 #define FTLN_MOUNTED (1 << 3) // FTL is mounted flag 45 46 // 47 // FTL meta-page information 48 // 49 #define FTLN_META_VER0 20100427 // first metapage version 50 #define FTLN_META_VER1 20180423 // second metapage version 51 #define FTLN_META_VER_LOC 0 // version location in page 52 #define FTLN_META_TYP_LOC 4 // page type location 53 #define FTLN_META_DATA_BEG 8 // starting data offset 54 55 // 56 // Meta-Page Types 57 // 58 #define CONT_FORMAT 0 59 #define ERASED_LIST 1 60 61 /***********************************************************************/ 62 /* Macro Definitions */ 63 /***********************************************************************/ 64 // 65 // Block Array Definitions 66 // 67 // A bdata entry is a 32 bit value that holds block metadata in RAM 68 // Bit 31 indicates if a block is free (1) or used (0) 69 // For free blocks: 70 // Bit 30 indicates if a free block is erased (1) or not (0) 71 // For used blocks: 72 // Bit 30 - indicates if a block is map (1) or volume (0) block 73 // Bits 29 through 20 - number of used pages in block 74 // Bits 19 through 0 - block read count 75 // 76 // 0xC0000000 - free/erased block 77 // 0x80000000 - free block 78 // 0x7XXXXXXX-0x4XXXXXXX - map block 79 // 0x3XXXXXXX-0x0XXXXXXX - used block 80 // 81 #define BLK_STATE_MASK 0xC0000000 82 #define FREE_BLK_FLAG 0x80000000 83 #define ERASED_BLK_FLAG 0x40000000 // applies only to free blocks 84 #define MAP_BLK_STATE 0x40000000 85 #define USED_MASK 0x3FF00000 // applies to map/vol blocks 86 #define RC_MASK 0x000FFFFF // applies to map/vol blocks 87 88 #define PGS_PER_BLK_MAX (USED_MASK >> 20) 89 90 #define IS_FREE(b) ((b)&FREE_BLK_FLAG) 91 #define IS_ERASED(b) (((b)&BLK_STATE_MASK) == (FREE_BLK_FLAG | ERASED_BLK_FLAG)) 92 #define IS_MAP_BLK(b) (((b)&BLK_STATE_MASK) == MAP_BLK_STATE) 93 #define SET_MAP_BLK(bd) (bd = MAP_BLK_STATE) 94 95 #define NUM_USED(bd) (((bd)&USED_MASK) >> 20) 96 #define DEC_USED(bd) ((bd) -= (1 << 20)) 97 #define INC_USED(bd) ((bd) += (1 << 20)) 98 #define GET_RC(bd) ((bd)&RC_MASK) 99 #define SET_RC(bd, n) ((bd) = ((bd) & ~RC_MASK) | n) 100 #define INC_RC(ftl, bdp, c) \ 101 do { \ 102 ui32 rc = GET_RC(*bdp) + c; \ 103 \ 104 if (rc > RC_MASK) \ 105 rc = RC_MASK; \ 106 *bdp = rc | (*bdp & ~RC_MASK); \ 107 if (rc >= (ftl)->max_rc) \ 108 (ftl)->max_rc_blk = (ui32)-2; \ 109 } /*lint !e717*/ \ 110 while (0) 111 #define SET_MAX_RC(ftl, bdp) \ 112 do { \ 113 (ftl)->max_rc_blk = (ui32)-2; \ 114 *bdp = (ftl)->max_rc | (*bdp & ~RC_MASK); \ 115 } /*lint !e717*/ \ 116 while (0) 117 118 119 // Map Page Array Definitions 120 // 121 // Get/set the physical page corresponding to a VPN 122 // 123 #if FTLN_3B_PN 124 #define FTLN_PN_SZ 3 125 #define UNMAPPED_PN 0x00FFFFFF 126 #define GET_MAP_PPN(maddr) RD24_LE(maddr) 127 #define SET_MAP_PPN(maddr, pn) WR24_LE(pn, maddr) 128 #else 129 #define FTLN_PN_SZ 4 130 #define UNMAPPED_PN 0xFFFFFFFF 131 #define GET_MAP_PPN(maddr) RD32_LE(maddr) 132 #define SET_MAP_PPN(maddr, pn) WR32_LE(pn, maddr) 133 #endif 134 135 // 136 // Spare Area Access Definitions// 137 // 138 // Layout of Spare Area (Extra Bytes) 139 // - byte 0: bad block mark byte - unused by the FTL 140 // - bytes 1 - 4: virtual page number 141 // - bytes 5 - 8: block count (BC) 142 // - bytes 9 - 11 and MSH of 12: block wear count (WC) 143 // - bytes LSH of 12 and 13 - 14: page validity check 144 // - byte 15: NDM control page mark byte 145 // 146 // 147 // Get/set virtual page number from spare area (bytes 1 - 4) 148 // 149 #define GET_SA_VPN(spare) RD32_LE(&spare[1]) 150 #define SET_SA_VPN(vpn, spare) WR32_LE(vpn, &spare[1]) 151 152 // 153 // Get/set block count from spare area (bytes 5 - 8) 154 // 155 #define GET_SA_BC(spare) RD32_LE(&spare[5]) 156 #define SET_SA_BC(bc, spare) WR32_LE(bc, &spare[5]) 157 158 // 159 // Get/set block wear count from spare area (bytes 9 - 11 and MSH of 12) 160 // 161 #define GET_SA_WC(spare) (RD24_LE(&spare[9]) | ((spare[12] & 0xF0) << 20)) 162 #define SET_SA_WC(wc, spare) \ 163 { \ 164 WR24_LE(wc, &spare[9]); \ 165 spare[12] = (spare[12] & 0xF) | ((wc >> 20) & 0xF0); \ 166 } 167 168 /***********************************************************************/ 169 /* Type Declarations */ 170 /***********************************************************************/ 171 // 172 // The TargetFTL-NDM volume type 173 // 174 typedef struct ftln* FTLN; 175 typedef const struct ftln* CFTLN; 176 struct ftln { 177 CircLink link; // volume list link 178 179 // Driver Functions 180 int (*write_page)(ui32 pn, const void* data, void* spare, void* ndm); 181 int (*read_spare)(ui32 pn, void* spare, void* ndm); 182 int (*read_pages)(ui32 start_pn, ui32 count, void* data, void* spare, void* ndm); 183 int (*write_pages)(ui32 start_pn, ui32 count, const void* data, void* spare, void* ndm); 184 int (*page_check)(ui32 pn, ui8* data, ui8* spare, void* ndm); 185 int (*xfer_page)(ui32 old_pn, ui32 new_pn, ui8* data, ui8* spare, void* ndm); 186 int (*erase_block)(ui32 pn, void* ndm); 187 #if INC_FTL_NDM_MLC 188 ui32 (*pair_offset)(ui32 page_offset, void* ndm); 189 #endif 190 191 // 192 // Callback function for freeing FTL specific resources 193 // 194 void (*free_ftl)(void* vol); 195 196 // Virtual Volume Variables 197 #if INC_FAT_MBR 198 ui32 vol_frst_sect; // first (boot) volume sector 199 #endif 200 ui32 sect_size; // virtual sector size in bytes 201 ui32 sects_per_page; // virtual sectors in a page 202 203 // Driver Dependent Variables 204 ui32 num_pages; // total number of pages 205 ui32 pgs_per_blk; // number of pages in a block 206 ui32 block_size; // block size in bytes 207 ui32 num_blks; // number of blocks 208 ui32 page_size; // page size in bytes 209 ui32 start_pn; // first page on device for volume 210 void* ndm; // pointer to NDM this FTL belongs to 211 212 ui32 flags; // holds various FTL flags 213 #if INC_FAT_MBR 214 ui32 frst_clust_sect; // first sector of first FAT cluster 215 ui32 clust_off; // offset to page align cluster sectors 216 #endif 217 ui32* bdata; // block metadata: flags and counts 218 ui8* blk_wc_lag; // amount block erase counts lag 'high_wc' 219 ui32* mpns; // array holding phy page # of map pages 220 221 #if INC_FTL_PAGE_CACHE 222 void* vol_cache; // handle to volume page cache 223 #endif 224 FTLMC* map_cache; // handle to map page cache 225 ui32 free_vpn; // next free page for volume page write 226 ui32 free_mpn; // next free page for map page write 227 ui32 mappings_per_mpg; // number of phys page numbers per map page 228 ui32 num_vsects; // number of volume sectors (FAT) 229 ui32 num_vpages; // number of volume pages 230 ui32 num_free_blks; // number of free blocks 231 ui32 num_map_pgs; // number of pages holding map data 232 ui32 high_wc; // highest block wear count 233 ui32 high_bc; // highest map block write count 234 ui32 max_rc; // per block read wear limit 235 ui32 max_rc_blk; // if not -1, # of block w/high read cnt 236 ui32 high_bc_mblk; // last map block 237 ui32 high_bc_mblk_po; // used page offset on last map block 238 ui32 resume_vblk; // vblk in interrupted recycle recovery 239 ui32 resume_tblk; // tmp blk for interrupted recycle recovery 240 ui32 resume_po; // resume vblk's highest used page offset 241 #if INC_ELIST 242 ui32 elist_blk; // if valid, # of block holding erased list 243 #endif 244 ftl_ndm_stats stats; // driver call counts 245 246 ui8* main_buf; // NAND main page buffer 247 #if INC_SECT_FTL 248 ui8* swap_page; // for accessing sector in page 249 #endif 250 ui8* spare_buf; // spare buffer for single/multi-pg access 251 252 ui32 type; // type of NAND - SLC or MLC 253 ui8 eb_size; // spare area size in bytes 254 ui8 copy_end_found; // vblk resume copy-end mark found 255 ui8 deferment; // # of recycles before applying wear limit 256 #if FTLN_DEBUG 257 ui8 max_wc_lag; // maximum observed lag below hi wear count 258 ui8 max_wc_over; // # of times max WC (0xFF) was exceeded 259 #endif 260 #if FS_ASSERT 261 ui8 assert_no_recycle; // test no recycle changes physical page # 262 #endif 263 char vol_name[FILENAME_MAX]; // volume name 264 }; 265 266 /***********************************************************************/ 267 /* Variable Declarations */ 268 /***********************************************************************/ 269 extern CircLink FtlnVols; 270 #if FTLN_DEBUG_PTR 271 extern FTLN Ftln; 272 #endif 273 274 /***********************************************************************/ 275 /* Function Prototypes */ 276 /***********************************************************************/ 277 void* FtlnAddVol(FtlNdmVol* ftl, int type, int sect_size, void* fs_vol); 278 int FtlnDelVol(FTLN ftl); 279 int FtlnWrSects(const void* buf, ui32 first, int count, void* vol); 280 int FtlnRdSects(void* buf, ui32 first, int count, void* vol); 281 int FtlnReport(void* vol, ui32 msg, ...); 282 ui32 FtlnGarbLvl(CFTLN ftl); 283 int FtlnVclean(FTLN ftl); 284 int FtlnMapGetPpn(CFTLN ftl, ui32 vpn, ui32* pnp); 285 int FtlnMapSetPpn(CFTLN ftl, ui32 vpn, ui32 ppn); 286 int FtlnRecCheck(FTLN ftl, int wr_cnt); 287 int FtlnRecNeeded(CFTLN ftl, int wr_cnt); 288 int FtlnRdPage(FTLN ftl, ui32 pn, void* buf); 289 290 int FtlnMapWr(void* vol, ui32 mpn, void* buf); 291 int FtlnMapRd(void* vol, ui32 mpn, void* buf, int* unmapped); 292 int FtlnMetaWr(FTLN ftl, ui32 type); 293 294 int FtlnVpnWr(FcEntry* c_e, int unused, void* vol); 295 int FtlnVpnRd(void* buf, ui32 vpn, void* vol); 296 297 void FtlnDecUsed(FTLN ftl, ui32 pn, ui32 vpn); 298 int FtlnFormat(FTLN ftl, ui32 meta_block); 299 void FtlnStateRst(FTLN ftl); 300 int FtlnEraseBlk(FTLN ftl, ui32 b); 301 ui32 FtlnLoWcFreeBlk(CFTLN ftl); 302 ui32 FtlnHiWcFreeBlk(CFTLN ftl); 303 int FtlnRecycleMapBlk(FTLN ftl, ui32 recycle_b); 304 305 int FtlnSetClustSect1(FTLN ftl, const ui8* bpb, int format_req); 306 int FtlnFatErr(FTLN ftl); 307 308 #if INC_FTL_NDM_MLC 309 void FtlnMlcSafeFreeVpn(FTLN ftl); 310 #endif 311 312 void FtlnBlkStats(CFTLN ftl); 313 void FtlnStats(FTLN ftl); 314 void FtlnShowBlks(void); 315 void FtlnCheckBlank(FTLN ftl, ui32 b); 316 317 #endif // INC_FTL_NDM 318