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_NDM
10 #include <stdlib.h>
11 #include <string.h>
12 #include <stdio_tfs.h>
13 #include <errno.h>
14 
15 #include <sys.h>
16 #include <modules.h>
17 #include <kprivate/ndm.h>
18 
19 /***********************************************************************/
20 /* Configuration                                                       */
21 /***********************************************************************/
22 #undef NDM_DEBUG
23 #define NDM_DEBUG FALSE    // TRUE for TargetNDM debug output
24 #define RDBACK_CHECK FALSE // TRUE for metadata read-back check
25 
26 /***********************************************************************/
27 /* Symbol Definitions                                                  */
28 /***********************************************************************/
29 #define CTRL_SIG_SZ 7 // ctrl sig bytes
30 #define CTRL_SIG "NDMTA01"
31 
32 //
33 // Location in control header of all header fields. A header consists of:
34 //   - 2 bytes of current page number in this control sequence
35 //   - 2 bytes of last page number in this control sequence
36 //   - 4 bytes of sequence number
37 //   - 4 bytes of CRC
38 //
39 #define HDR_CURR_LOC 0
40 #define HDR_LAST_LOC 2
41 #define HDR_SEQ_LOC 4
42 #define HDR_CRC_LOC 8
43 #define HDR_SIZE 12
44 #define CTRL_DATA_START 12
45 
46 // Control scan flag value
47 #define PARTIAL_SCAN 2
48 
49 // Actions that can cause a block to go bad
50 #define ERASE_BLOCK 1
51 #define WRITE_PAGE 2//
52 
53 //
54 // Layout for the spare area:
55 //  - byte 0 - bad block mark byte
56 //  - bytes 1 - 14 - reserved for the above layers - will be ECC-ed
57 //  - byte 15 - NDM regular page mark byte
58 //  - rest are left to the driver to place ECC codes in them
59 //
60 #define EB_BBLOCK_MARK 0
61 #define EB_FRST_RESERVED 1
62 #define EB_LAST_RESERVED 14
63 #define EB_REG_MARK 15  // NDM control page iff zero
64 
65 /***********************************************************************/
66 /* Type Declarations                                                   */
67 /***********************************************************************/
68 
69 // <key, value> pair
70 typedef struct {
71     ui32 key;  // vblk
72     ui32 val;  // pblk
73 } Pair;
74 
75 // NDM Control Block
76 struct ndm {
77     CircLink link;      // linked list of NDM devices
78     ui32 num_vblks;     // number of virtual blocks
79     SEM sem;            // access semaphore
80     ui8* main_buf;      // main page data buffer
81     ui8* spare_buf;     // spare area buffer
82     ui8* tmp_spare;     // temp buffer for driver transfer routine
83     ui32* init_bad_blk; // initial bad blocks list
84     Pair* run_bad_blk;  // running bad blocks list
85     ui32 num_rbb;       // number of blocks in running bad block list
86     ui32 num_bad_blks;  // current total number of bad blocks
87     ui32 frst_reserved; // first block reserved for NDM
88     ui32 free_virt_blk; // next free block NDM uses for bad virtual
89     ui32 free_ctrl_blk; // next free block NDM uses for bad control
90     ui32 ctrl_blk0;     // two blocks used for control info
91     ui32 ctrl_blk1;
92     ui32 frst_ctrl_page;  // first page of control information
93     ui32 last_ctrl_page;  // last page of control information
94     ui32 next_ctrl_start; // starting page of next control write
95     ui32 ctrl_pages;      // number of control pages
96     ui32 ctrl_seq;        // control information sequence number
97     ui32 xfr_tblk;        // interrupted 'transfer to' block
98     ui32 xfr_fblk;        // interrupted 'transfer from' block
99     ui32 xfr_bad_po;      // bad page offset in 'transfer from' block
100     ui32 last_wr_vbn;     // last virtual block number written to
101     ui32 last_wr_pbn;     // last physical block number written to
102     ui32 last_rd_vbn;     // last virtual block number read from
103     ui32 last_rd_pbn;     // last physical block number read from
104     ui32 flags;           // option flags
105 
106     // Partition Information
107     ui32 num_partitions;
108     NDMPartition* partitions;
109 
110     // Driver Functions
111     int (*write_page)(ui32 pn, const ui8* data, ui8* spare, int action, void* dev);
112     int (*write_pages)(ui32 pn, ui32 count, const ui8* data, ui8* spare, int action, void* dev);
113     int (*read_page)(ui32 pn, ui8* data, ui8* spare, void* dev);
114     int (*read_pages)(ui32 pn, ui32 count, ui8* data, ui8* spare, void* dev);
115     int (*xfr_page)(ui32 old_pn, ui32 new_pn, ui8* data, ui8* old_spare, ui8* new_spare,
116                     int encode_spare, void* dev);
117 #if INC_FFS_NDM_MLC || INC_FTL_NDM_MLC
118     ui32 (*pair_offset)(ui32 page_offset, void* dev);
119 #endif
120     int (*read_decode_spare)(ui32 pn, ui8* spare, void* dev);
121     int (*read_spare)(ui32 pn, ui8* spare, void* dev);
122     int (*page_blank)(ui32 pn, ui8* data, ui8* spare, void* dev);
123 #if INC_FTL_NDM
124     int (*check_page)(ui32 pn, ui8* data, ui8* spr, int* stat, void* dev);
125 #endif
126     int (*erase_block)(ui32 pn, void* dev);
127 #if INC_FTL_NDM || INC_FFS_NDM
128     int (*is_block_bad)(ui32 pn, void* dev);
129 #endif
130 
131     // Device Dependent Variables
132     void* dev;         // optional value set by driver
133     void* dev_ndm;     // driver/ndm handle used with transfer page
134     ui32 num_dev_blks; // number of device blocks
135     ui32 block_size;   // block size in bytes
136     ui32 max_bad_blks; // maximum number of bad blocks
137     ui32 pgs_per_blk;  // number of pages in a block
138     ui32 page_size;    // page size in bytes
139     ui8 eb_size;       // spare area size in bytes
140     ui8 dev_type;      // NAND device type
141 };
142 
143 /***********************************************************************/
144 /* Variable Declarations                                               */
145 /***********************************************************************/
146 extern CircLink NdmDevs;
147 extern SEM NdmSem;
148 
149 /***********************************************************************/
150 /* Function Prototypes                                                 */
151 /***********************************************************************/
152 int ndmInitBadBlock(CNDM ndm, ui32 b);
153 int ndmWrCtrl(NDM ndm);
154 void ndmCkMeta(NDM ndm);
155 int ndmMarkBadBlock(NDM ndm, ui32 arg, ui32 action);
156 void* ndmAddFatFTL(NDM ndm, ui32 part_num, FtlNdmVol* ftl, FatVol* fat);
157 
158 #if NDM_DEBUG
159 int printf(const char*, ...);
160 #endif
161 
162 #endif // INC_NDM
163