1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** LevelX Component                                                      */
16 /**                                                                       */
17 /**   NAND Flash Simulator                                                */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 
23 /* Include necessary files.  */
24 
25 #include "lx_api.h"
26 
27 /* Define constants for the NAND flash simulation. */
28 
29 #define TOTAL_BLOCKS                        1024
30 #define PHYSICAL_PAGES_PER_BLOCK            256         /* Min value of 2                                               */
31 #define BYTES_PER_PHYSICAL_PAGE             512         /* 512 bytes per page                                           */
32 #define WORDS_PER_PHYSICAL_PAGE             512 / 4     /* Words per page                                               */
33 #define SPARE_BYTES_PER_PAGE                16          /* 16 "spare" bytes per page                                    */
34                                                         /* For 2048 byte block spare area:                              */
35 #define BAD_BLOCK_POSITION                  0           /*      0 is the bad block byte postion                         */
36 #define EXTRA_BYTE_POSITION                 0           /*      0 is the extra bytes starting byte postion              */
37 #define ECC_BYTE_POSITION                   8           /*      8 is the ECC starting byte position                     */
38 #define SPARE_DATA1_OFFSET                  4
39 #define SPARE_DATA1_LENGTH                  4
40 #define SPARE_DATA2_OFFSET                  2
41 #define SPARE_DATA2_LENGTH                  2
42 
43 
44 
45 /* Definition of the spare area is relative to the block size of the NAND part and perhaps manufactures of the NAND part.
46    Here are some common definitions:
47 
48    256 Byte Block
49 
50         Bytes               Meaning
51 
52         0,1,2           ECC bytes
53         3,4,6,7         Extra
54         5               Bad block flag
55 
56     512 Byte Block
57 
58         Bytes               Meaning
59 
60         0,1,2,3,6,7     ECC bytes
61         8-15            Extra
62         5               Bad block flag
63 
64     2048 Byte Block
65 
66         Bytes               Meaning
67 
68         0               Bad block flag
69         2-39            Extra
70         40-63           ECC bytes
71 */
72 
73 
74 typedef struct PHYSICAL_PAGE_STRUCT
75 {
76     unsigned long memory[WORDS_PER_PHYSICAL_PAGE];
77     unsigned char spare[SPARE_BYTES_PER_PAGE];
78 } PHYSICAL_PAGE;
79 
80 typedef struct NAND_BLOCK_DIAG_STRUCT
81 {
82     unsigned long erases;
83     unsigned long page_writes[PHYSICAL_PAGES_PER_BLOCK];
84     unsigned long max_page_writes[PHYSICAL_PAGES_PER_BLOCK];
85 } NAND_BLOCK_DIAG;
86 
87 
88 
89 
90 typedef struct NAND_FLASH_BLOCK_STRUCT
91 {
92     PHYSICAL_PAGE       physical_pages[PHYSICAL_PAGES_PER_BLOCK];
93 } NAND_FLASH_BLOCK;
94 
95 NAND_FLASH_BLOCK   nand_memory_area[TOTAL_BLOCKS];
96 
97 NAND_BLOCK_DIAG    nand_block_diag[TOTAL_BLOCKS];
98 
99 
100 /* Define NAND flash buffer for LevelX.  */
101 
102 ULONG  nand_flash_simulator_buffer[WORDS_PER_PHYSICAL_PAGE];
103 ULONG  *nand_flash_memory;
104 
105 
106 UINT  _lx_nand_flash_simulator_initialize(LX_NAND_FLASH *nand_flash);
107 UINT  _lx_nand_flash_simulator_erase_all(VOID);
108 
109 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
110 UINT  _lx_nand_flash_simulator_read(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, ULONG *destination, ULONG words);
111 UINT  _lx_nand_flash_simulator_write(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, ULONG *source, ULONG words);
112 UINT  _lx_nand_flash_simulator_block_erase(LX_NAND_FLASH *nand_flash, ULONG block, ULONG erase_count);
113 UINT  _lx_nand_flash_simulator_block_erased_verify(LX_NAND_FLASH *nand_flash, ULONG block);
114 UINT  _lx_nand_flash_simulator_page_erased_verify(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page);
115 UINT  _lx_nand_flash_simulator_block_status_get(LX_NAND_FLASH *nand_flash, ULONG block, UCHAR *bad_block_byte);
116 UINT  _lx_nand_flash_simulator_block_status_set(LX_NAND_FLASH *nand_flash, ULONG block, UCHAR bad_block_byte);
117 UINT  _lx_nand_flash_simulator_extra_bytes_get(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, UCHAR *destination, UINT size);
118 UINT  _lx_nand_flash_simulator_extra_bytes_set(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, UCHAR *source, UINT size);
119 UINT  _lx_nand_flash_simulator_system_error(LX_NAND_FLASH *nand_flash, UINT error_code, ULONG block, ULONG page);
120 
121 UINT  _lx_nand_flash_simulator_pages_read(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, UCHAR* main_buffer, UCHAR* spare_buffer, ULONG pages);
122 UINT  _lx_nand_flash_simulator_pages_write(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, UCHAR* main_buffer, UCHAR* spare_buffer, ULONG pages);
123 UINT  _lx_nand_flash_simulator_pages_copy(LX_NAND_FLASH *nand_flash, ULONG source_block, ULONG source_page, ULONG destination_block, ULONG destination_page, ULONG pages, UCHAR* data_buffer);
124 #else
125 UINT  _lx_nand_flash_simulator_read(ULONG block, ULONG page, ULONG *destination, ULONG words);
126 UINT  _lx_nand_flash_simulator_write(ULONG block, ULONG page, ULONG *source, ULONG words);
127 UINT  _lx_nand_flash_simulator_block_erase(ULONG block, ULONG erase_count);
128 UINT  _lx_nand_flash_simulator_block_erased_verify(ULONG block);
129 UINT  _lx_nand_flash_simulator_page_erased_verify(ULONG block, ULONG page);
130 UINT  _lx_nand_flash_simulator_block_status_get(ULONG block, UCHAR *bad_block_byte);
131 UINT  _lx_nand_flash_simulator_block_status_set(ULONG block, UCHAR bad_block_byte);
132 UINT  _lx_nand_flash_simulator_extra_bytes_get(ULONG block, ULONG page, UCHAR *destination, UINT size);
133 UINT  _lx_nand_flash_simulator_extra_bytes_set(ULONG block, ULONG page, UCHAR *source, UINT size);
134 UINT  _lx_nand_flash_simulator_system_error(UINT error_code, ULONG block, ULONG page);
135 
136 UINT  _lx_nand_flash_simulator_pages_read(ULONG block, ULONG page, UCHAR* main_buffer, UCHAR* spare_buffer, ULONG pages);
137 UINT  _lx_nand_flash_simulator_pages_write(ULONG block, ULONG page, UCHAR* main_buffer, UCHAR* spare_buffer, ULONG pages);
138 UINT  _lx_nand_flash_simulator_pages_copy(ULONG source_block, ULONG source_page, ULONG destination_block, ULONG destination_page, ULONG pages, UCHAR* data_buffer);
139 #endif
140 UINT  _lx_nand_flash_simulator_page_ecc_check(ULONG block, ULONG page);
141 
_lx_nand_flash_simulator_initialize(LX_NAND_FLASH * nand_flash)142 UINT  _lx_nand_flash_simulator_initialize(LX_NAND_FLASH *nand_flash)
143 {
144 
145     /* Setup the buffer pointer.  */
146     nand_flash_memory = (ULONG *) &nand_memory_area[0];
147 
148     /* Setup geometry of the NAND flash.  */
149     nand_flash -> lx_nand_flash_total_blocks =                  TOTAL_BLOCKS;
150     nand_flash -> lx_nand_flash_pages_per_block =               PHYSICAL_PAGES_PER_BLOCK;
151     nand_flash -> lx_nand_flash_bytes_per_page =                BYTES_PER_PHYSICAL_PAGE;
152 
153     /* Setup function pointers for the NAND flash services.  */
154     nand_flash -> lx_nand_flash_driver_read =                   _lx_nand_flash_simulator_read;
155     nand_flash -> lx_nand_flash_driver_write =                  _lx_nand_flash_simulator_write;
156     nand_flash -> lx_nand_flash_driver_block_erase =            _lx_nand_flash_simulator_block_erase;
157     nand_flash -> lx_nand_flash_driver_block_erased_verify =    _lx_nand_flash_simulator_block_erased_verify;
158     nand_flash -> lx_nand_flash_driver_page_erased_verify =     _lx_nand_flash_simulator_page_erased_verify;
159     nand_flash -> lx_nand_flash_driver_block_status_get =       _lx_nand_flash_simulator_block_status_get;
160     nand_flash -> lx_nand_flash_driver_block_status_set =       _lx_nand_flash_simulator_block_status_set;
161     nand_flash -> lx_nand_flash_driver_extra_bytes_get =        _lx_nand_flash_simulator_extra_bytes_get;
162     nand_flash -> lx_nand_flash_driver_extra_bytes_set =        _lx_nand_flash_simulator_extra_bytes_set;
163     nand_flash -> lx_nand_flash_driver_system_error =           _lx_nand_flash_simulator_system_error;
164 
165     nand_flash -> lx_nand_flash_driver_pages_read =             _lx_nand_flash_simulator_pages_read;
166     nand_flash -> lx_nand_flash_driver_pages_write =            _lx_nand_flash_simulator_pages_write;
167     nand_flash -> lx_nand_flash_driver_pages_copy =             _lx_nand_flash_simulator_pages_copy;
168 
169     nand_flash -> lx_nand_flash_spare_data1_offset =            SPARE_DATA1_OFFSET;
170     nand_flash -> lx_nand_flash_spare_data1_length =            SPARE_DATA1_LENGTH;
171 
172     nand_flash -> lx_nand_flash_spare_data2_offset =            SPARE_DATA2_OFFSET;
173     nand_flash -> lx_nand_flash_spare_data2_length =            SPARE_DATA2_LENGTH;
174 
175     nand_flash -> lx_nand_flash_spare_total_length =            SPARE_BYTES_PER_PAGE;
176 
177     /* Return success.  */
178     return(LX_SUCCESS);
179 }
_lx_nand_flash_simulator_page_ecc_check(ULONG block,ULONG page)180 UINT _lx_nand_flash_simulator_page_ecc_check(ULONG block, ULONG page)
181 {
182 
183 UINT    i;
184 INT     ecc_pos = 0;
185 UINT    ecc_status = LX_SUCCESS;
186 UINT    status;
187 
188 
189     for (i = 0; i < BYTES_PER_PHYSICAL_PAGE; i += 256)
190     {
191         status = lx_nand_flash_256byte_ecc_check((UCHAR*)&nand_memory_area[block].physical_pages[page].memory[i / sizeof(ULONG)],
192             &nand_memory_area[block].physical_pages[page].spare[ECC_BYTE_POSITION + ecc_pos]);
193 
194         if (status == LX_NAND_ERROR_NOT_CORRECTED)
195         {
196             ecc_status = LX_NAND_ERROR_NOT_CORRECTED;
197             break;
198         }
199         else if (status == LX_NAND_ERROR_CORRECTED)
200         {
201             ecc_status = LX_NAND_ERROR_CORRECTED;
202         }
203 
204         ecc_pos += 3;
205     }
206 
207     if (ecc_status == LX_NAND_ERROR_CORRECTED)
208     {
209 
210         return(LX_ERROR);
211     }
212     else if (ecc_status == LX_NAND_ERROR_NOT_CORRECTED)
213     {
214 
215         return(LX_ERROR);
216     }
217     return ecc_status;
218 }
219 
220 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
_lx_nand_flash_simulator_read(LX_NAND_FLASH * nand_flash,ULONG block,ULONG page,ULONG * destination,ULONG words)221 UINT  _lx_nand_flash_simulator_read(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, ULONG *destination, ULONG words)
222 #else
223 UINT  _lx_nand_flash_simulator_read(ULONG block, ULONG page, ULONG *destination, ULONG words)
224 #endif
225 {
226 
227 ULONG   *flash_address;
228 UINT    status;
229 
230 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
231     LX_PARAMETER_NOT_USED(nand_flash);
232 #endif
233 
234     status = _lx_nand_flash_simulator_page_ecc_check(block, page);
235 
236     /* Pickup the flash address.  */
237     flash_address =  &(nand_memory_area[block].physical_pages[page].memory[0]);
238 
239     /* Loop to read flash.  */
240     while (words--)
241     {
242         /* Copy word.  */
243         *destination++ =  *flash_address++;
244     }
245 
246     return(status);
247 }
248 
249 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
_lx_nand_flash_simulator_pages_read(LX_NAND_FLASH * nand_flash,ULONG block,ULONG page,UCHAR * main_buffer,UCHAR * spare_buffer,ULONG pages)250 UINT  _lx_nand_flash_simulator_pages_read(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, UCHAR* main_buffer, UCHAR* spare_buffer, ULONG pages)
251 #else
252 UINT  _lx_nand_flash_simulator_pages_read(ULONG block, ULONG page, UCHAR* main_buffer, UCHAR* spare_buffer, ULONG pages)
253 #endif
254 {
255 
256 UINT    i;
257 UINT    status;
258 UINT    ecc_status = LX_SUCCESS;
259 
260 
261     for (i = 0; i < pages; i++)
262     {
263         if (main_buffer)
264         {
265 
266 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
267             status = _lx_nand_flash_simulator_read(nand_flash, block, page + i, (ULONG*)(main_buffer + i * BYTES_PER_PHYSICAL_PAGE), WORDS_PER_PHYSICAL_PAGE);
268 #else
269             status = _lx_nand_flash_simulator_read(block, page + i, (ULONG*)(main_buffer + i * BYTES_PER_PHYSICAL_PAGE), WORDS_PER_PHYSICAL_PAGE);
270 #endif
271             if (status == LX_NAND_ERROR_CORRECTED)
272             {
273                 ecc_status = LX_NAND_ERROR_CORRECTED;
274             }
275             else if (status == LX_NAND_ERROR_NOT_CORRECTED)
276             {
277                 ecc_status = LX_ERROR;
278                 break;
279             }
280         }
281 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
282         status = _lx_nand_flash_simulator_extra_bytes_get(nand_flash, block, page + i, spare_buffer + i * SPARE_BYTES_PER_PAGE, SPARE_BYTES_PER_PAGE);
283 #else
284         status = _lx_nand_flash_simulator_extra_bytes_get(block, page + i, spare_buffer + i * SPARE_BYTES_PER_PAGE, SPARE_BYTES_PER_PAGE);
285 #endif
286     }
287     return (ecc_status);
288 }
289 
290 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
_lx_nand_flash_simulator_write(LX_NAND_FLASH * nand_flash,ULONG block,ULONG page,ULONG * source,ULONG words)291 UINT  _lx_nand_flash_simulator_write(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, ULONG *source, ULONG words)
292 #else
293 UINT  _lx_nand_flash_simulator_write(ULONG block, ULONG page, ULONG *source, ULONG words)
294 #endif
295 {
296 
297 ULONG   *flash_address;
298 UCHAR   *flash_spare_address;
299 UINT    bytes_computed;
300 UINT    ecc_bytes =0;
301 UCHAR   new_ecc_buffer[24];
302 UCHAR   *new_ecc_buffer_ptr = new_ecc_buffer;
303 UCHAR   *ecc_buffer_ptr = new_ecc_buffer_ptr;
304 ULONG   *page_ptr = &(nand_memory_area[block].physical_pages[page].memory[0]);
305 
306 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
307     LX_PARAMETER_NOT_USED(nand_flash);
308 #endif
309 
310     /* Increment the diag info.  */
311     nand_block_diag[block].page_writes[page]++;
312     if (nand_block_diag[block].page_writes[page] > nand_block_diag[block].max_page_writes[page])
313         nand_block_diag[block].max_page_writes[page] =  nand_block_diag[block].page_writes[page];
314 
315     /* Pickup the flash address.  */
316     flash_address =  &(nand_memory_area[block].physical_pages[page].memory[0]);
317 
318     /* Loop to write flash.  */
319     while (words--)
320     {
321 
322         /* Can the word be written?  We can clear new bits, but just can't unclear
323            in a NAND device.  */
324         if ((*source & *flash_address) != *source)
325            return(LX_INVALID_WRITE);
326 
327         /* Copy word.  */
328         *flash_address++ =  *source++;
329     }
330 
331     /* Loop to compute the ECC over the entire NAND flash page.  */
332     bytes_computed =  0;
333 
334     while (bytes_computed < BYTES_PER_PHYSICAL_PAGE)
335     {
336 
337         /* Compute the ECC for this 256 byte piece of the page.  */
338         _lx_nand_flash_256byte_ecc_compute((UCHAR *)page_ptr, (UCHAR *)new_ecc_buffer_ptr);
339 
340         /* Move to the next 256 byte portion of the page.  */
341         bytes_computed =  bytes_computed + 256;
342 
343         /* Move the page buffer forward.  */
344         page_ptr =  page_ptr + 64;
345 
346         ecc_bytes = ecc_bytes + 3;
347 
348         /* Move the ECC buffer forward, note there are 3 bytes of ECC per page. */
349         new_ecc_buffer_ptr =   new_ecc_buffer_ptr + 3;
350     }
351 
352     /* Setup destination pointer in the spare area.  */
353     flash_spare_address =  (UCHAR *) &(nand_memory_area[block].physical_pages[page].spare[ECC_BYTE_POSITION]);
354     while(ecc_bytes--)
355     {
356 
357         /* Can the word be written?  We can clear new bits, but just can't unclear
358            in a NAND device.  */
359         if ((*ecc_buffer_ptr & *flash_spare_address) != *ecc_buffer_ptr)
360            return(LX_INVALID_WRITE);
361 
362         /* Set an ecc byte in the spare area.  */
363        *flash_spare_address++ =  *ecc_buffer_ptr++;
364 
365     }
366     return(LX_SUCCESS);
367 }
368 
369 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
_lx_nand_flash_simulator_pages_write(LX_NAND_FLASH * nand_flash,ULONG block,ULONG page,UCHAR * main_buffer,UCHAR * spare_buffer,ULONG pages)370 UINT  _lx_nand_flash_simulator_pages_write(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, UCHAR* main_buffer, UCHAR* spare_buffer, ULONG pages)
371 #else
372 UINT  _lx_nand_flash_simulator_pages_write(ULONG block, ULONG page, UCHAR* main_buffer, UCHAR* spare_buffer, ULONG pages)
373 #endif
374 {
375 
376 UINT    i;
377 UINT    status = LX_SUCCESS;
378 
379 
380     for (i = 0; i < pages; i++)
381     {
382 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
383         _lx_nand_flash_simulator_extra_bytes_set(nand_flash, block, page + i, spare_buffer + i * SPARE_BYTES_PER_PAGE, SPARE_BYTES_PER_PAGE);
384         status = _lx_nand_flash_simulator_write(nand_flash, block, page + i, (ULONG*)(main_buffer + i * BYTES_PER_PHYSICAL_PAGE), WORDS_PER_PHYSICAL_PAGE);
385 #else
386         _lx_nand_flash_simulator_extra_bytes_set(block, page + i, spare_buffer + i * SPARE_BYTES_PER_PAGE, SPARE_BYTES_PER_PAGE);
387         status = _lx_nand_flash_simulator_write(block, page + i, (ULONG*)(main_buffer + i * BYTES_PER_PHYSICAL_PAGE), WORDS_PER_PHYSICAL_PAGE);
388 #endif
389         if (status == LX_INVALID_WRITE)
390         {
391             break;
392         }
393 
394     }
395     return (status);
396 }
397 
398 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
_lx_nand_flash_simulator_pages_copy(LX_NAND_FLASH * nand_flash,ULONG source_block,ULONG source_page,ULONG destination_block,ULONG destination_page,ULONG pages,UCHAR * data_buffer)399 UINT  _lx_nand_flash_simulator_pages_copy(LX_NAND_FLASH *nand_flash, ULONG source_block, ULONG source_page, ULONG destination_block, ULONG destination_page, ULONG pages, UCHAR *data_buffer)
400 #else
401 UINT  _lx_nand_flash_simulator_pages_copy(ULONG source_block, ULONG source_page, ULONG destination_block, ULONG destination_page, ULONG pages, UCHAR *data_buffer)
402 #endif
403 {
404     UINT    i;
405     UINT    status = LX_SUCCESS;
406 
407 
408     for (i = 0; i < pages; i++)
409     {
410 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
411         status = _lx_nand_flash_simulator_pages_read(nand_flash, source_block, source_page + i, data_buffer, data_buffer + BYTES_PER_PHYSICAL_PAGE, 1);
412 #else
413         status = _lx_nand_flash_simulator_pages_read(source_block, source_page + i, data_buffer, data_buffer + BYTES_PER_PHYSICAL_PAGE, 1);
414 #endif
415         if (status != LX_SUCCESS && status != LX_NAND_ERROR_CORRECTED)
416         {
417             break;
418         }
419 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
420         status = _lx_nand_flash_simulator_pages_write(nand_flash, destination_block, destination_page + i, data_buffer, data_buffer + BYTES_PER_PHYSICAL_PAGE, 1);
421 #else
422         status = _lx_nand_flash_simulator_pages_write(destination_block, destination_page + i, data_buffer, data_buffer + BYTES_PER_PHYSICAL_PAGE, 1);
423 #endif
424         if (status != LX_SUCCESS)
425         {
426             break;
427         }
428 
429     }
430     return (status);
431 
432 }
433 
434 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
_lx_nand_flash_simulator_block_erase(LX_NAND_FLASH * nand_flash,ULONG block,ULONG erase_count)435 UINT  _lx_nand_flash_simulator_block_erase(LX_NAND_FLASH *nand_flash, ULONG block, ULONG erase_count)
436 #else
437 UINT  _lx_nand_flash_simulator_block_erase(ULONG block, ULONG erase_count)
438 #endif
439 {
440 
441 ULONG   *pointer;
442 ULONG   words;
443 UINT    i;
444 
445     LX_PARAMETER_NOT_USED(erase_count);
446 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
447     LX_PARAMETER_NOT_USED(nand_flash);
448 #endif
449 
450     /* Increment the diag info.  */
451     nand_block_diag[block].erases++;
452     for (i = 0; i < PHYSICAL_PAGES_PER_BLOCK;i++)
453         nand_block_diag[block].page_writes[i] = 0;
454 
455     /* Setup pointer.  */
456     pointer =  (ULONG *) &nand_memory_area[block];
457 
458     /* Loop to erase block.  */
459     words =  sizeof(NAND_FLASH_BLOCK)/sizeof(ULONG);
460     while (words--)
461     {
462 
463         /* Erase word of block.  */
464         *pointer++ =  (ULONG) 0xFFFFFFFF;
465     }
466 
467     return(LX_SUCCESS);
468 }
469 
470 
_lx_nand_flash_simulator_erase_all(VOID)471 UINT  _lx_nand_flash_simulator_erase_all(VOID)
472 {
473 
474 ULONG   *pointer;
475 ULONG   words;
476 UINT    i, j;
477 
478 
479     /* Increment the diag info.  */
480     for (i = 0; i < TOTAL_BLOCKS; i++)
481     {
482     nand_block_diag[i].erases =  0;
483     for (j = 0; j < PHYSICAL_PAGES_PER_BLOCK;j++)
484         nand_block_diag[i].page_writes[j] = 0;
485     }
486 
487     /* Setup pointer.  */
488     pointer =  (ULONG *) &nand_memory_area[0];
489 
490     /* Loop to erase block.  */
491     words =  sizeof(nand_memory_area)/(sizeof(ULONG));
492     while (words--)
493     {
494 
495         /* Erase word of block.  */
496         *pointer++ =  (ULONG) 0xFFFFFFFF;
497     }
498 
499     return(LX_SUCCESS);
500 }
501 
502 
503 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
_lx_nand_flash_simulator_block_erased_verify(LX_NAND_FLASH * nand_flash,ULONG block)504 UINT  _lx_nand_flash_simulator_block_erased_verify(LX_NAND_FLASH *nand_flash, ULONG block)
505 #else
506 UINT  _lx_nand_flash_simulator_block_erased_verify(ULONG block)
507 #endif
508 {
509 
510 ULONG   *word_ptr;
511 ULONG   words;
512 
513 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
514     LX_PARAMETER_NOT_USED(nand_flash);
515 #endif
516 
517     /* Determine if the block is completely erased.  */
518 
519     /* Pickup the pointer to the first word of the block.  */
520     word_ptr =  (ULONG *) &nand_memory_area[block];
521 
522     /* Calculate the number of words in a block.  */
523     words =  sizeof(NAND_FLASH_BLOCK)/sizeof(ULONG);
524 
525     /* Loop to check if the block is erased.  */
526     while (words--)
527     {
528 
529         /* Is this word erased?  */
530         if (*word_ptr++ != 0xFFFFFFFF)
531             return(LX_ERROR);
532     }
533 
534     /* Return success.  */
535     return(LX_SUCCESS);
536 }
537 
538 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
_lx_nand_flash_simulator_page_erased_verify(LX_NAND_FLASH * nand_flash,ULONG block,ULONG page)539 UINT  _lx_nand_flash_simulator_page_erased_verify(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page)
540 #else
541 UINT  _lx_nand_flash_simulator_page_erased_verify(ULONG block, ULONG page)
542 #endif
543 {
544 
545 ULONG   *word_ptr;
546 ULONG   words;
547 
548 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
549     LX_PARAMETER_NOT_USED(nand_flash);
550 #endif
551 
552     /* Determine if the block is completely erased.  */
553 
554     /* Pickup the pointer to the first word of the block's page.  */
555     word_ptr =  (ULONG *) &nand_memory_area[block].physical_pages[page];
556 
557     /* Calculate the number of words in a block.  */
558     words =  WORDS_PER_PHYSICAL_PAGE;
559 
560     /* Loop to check if the page is erased.  */
561     while (words--)
562     {
563 
564         /* Is this word erased?  */
565         if (*word_ptr++ != 0xFFFFFFFF)
566             return(LX_ERROR);
567     }
568 
569     /* Return success.  */
570     return(LX_SUCCESS);
571 }
572 
573 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
_lx_nand_flash_simulator_block_status_get(LX_NAND_FLASH * nand_flash,ULONG block,UCHAR * bad_block_byte)574 UINT  _lx_nand_flash_simulator_block_status_get(LX_NAND_FLASH *nand_flash, ULONG block, UCHAR *bad_block_byte)
575 #else
576 UINT  _lx_nand_flash_simulator_block_status_get(ULONG block, UCHAR *bad_block_byte)
577 #endif
578 {
579 
580 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
581     LX_PARAMETER_NOT_USED(nand_flash);
582 #endif
583 
584     /* Pickup the bad block byte and return it.  */
585     *bad_block_byte =  nand_memory_area[block].physical_pages[0].spare[BAD_BLOCK_POSITION];
586 
587     /* Return success.  */
588     return(LX_SUCCESS);
589 }
590 
591 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
_lx_nand_flash_simulator_block_status_set(LX_NAND_FLASH * nand_flash,ULONG block,UCHAR bad_block_byte)592 UINT  _lx_nand_flash_simulator_block_status_set(LX_NAND_FLASH *nand_flash, ULONG block, UCHAR bad_block_byte)
593 #else
594 UINT  _lx_nand_flash_simulator_block_status_set(ULONG block, UCHAR bad_block_byte)
595 #endif
596 {
597 
598 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
599     LX_PARAMETER_NOT_USED(nand_flash);
600 #endif
601 
602     /* Set the bad block byte.  */
603     nand_memory_area[block].physical_pages[0].spare[BAD_BLOCK_POSITION] =  bad_block_byte;
604 
605     /* Return success.  */
606     return(LX_SUCCESS);
607 }
608 
609 
610 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
_lx_nand_flash_simulator_extra_bytes_get(LX_NAND_FLASH * nand_flash,ULONG block,ULONG page,UCHAR * destination,UINT size)611 UINT  _lx_nand_flash_simulator_extra_bytes_get(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, UCHAR *destination, UINT size)
612 #else
613 UINT  _lx_nand_flash_simulator_extra_bytes_get(ULONG block, ULONG page, UCHAR *destination, UINT size)
614 #endif
615 {
616 
617 UCHAR   *source;
618 
619 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
620     LX_PARAMETER_NOT_USED(nand_flash);
621 #endif
622 
623     /* Setup source pointer in the spare area.  */
624     source =  (UCHAR *) &(nand_memory_area[block].physical_pages[page].spare[EXTRA_BYTE_POSITION]);
625 
626     /* Loop to return the extra bytes requested.  */
627     while (size--)
628     {
629 
630         /* Retrieve an extra byte from the spare area.  */
631         *destination++ =  *source++;
632     }
633 
634     /* Return success.  */
635     return(LX_SUCCESS);
636 }
637 
638 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
_lx_nand_flash_simulator_extra_bytes_set(LX_NAND_FLASH * nand_flash,ULONG block,ULONG page,UCHAR * source,UINT size)639 UINT  _lx_nand_flash_simulator_extra_bytes_set(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, UCHAR *source, UINT size)
640 #else
641 UINT  _lx_nand_flash_simulator_extra_bytes_set(ULONG block, ULONG page, UCHAR *source, UINT size)
642 #endif
643 {
644 
645 UCHAR   *destination;
646 
647 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
648     LX_PARAMETER_NOT_USED(nand_flash);
649 #endif
650 
651     /* Increment the diag info.  */
652     nand_block_diag[block].page_writes[page]++;
653     if (nand_block_diag[block].page_writes[page] > nand_block_diag[block].max_page_writes[page])
654         nand_block_diag[block].max_page_writes[page] =  nand_block_diag[block].page_writes[page];
655 
656     /* Setup destination pointer in the spare area.  */
657     destination =  (UCHAR *) &(nand_memory_area[block].physical_pages[page].spare[EXTRA_BYTE_POSITION]);
658 
659     /* Loop to set the extra bytes.  */
660     while (size--)
661     {
662 
663         /* Set an extra byte in the spare area.  */
664         *destination++ =  *source++;
665     }
666 
667     /* Return success.  */
668     return(LX_SUCCESS);
669 }
670 
671 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
_lx_nand_flash_simulator_system_error(LX_NAND_FLASH * nand_flash,UINT error_code,ULONG block,ULONG page)672 UINT  _lx_nand_flash_simulator_system_error(LX_NAND_FLASH *nand_flash, UINT error_code, ULONG block, ULONG page)
673 #else
674 UINT  _lx_nand_flash_simulator_system_error(UINT error_code, ULONG block, ULONG page)
675 #endif
676 {
677     LX_PARAMETER_NOT_USED(error_code);
678     LX_PARAMETER_NOT_USED(block);
679     LX_PARAMETER_NOT_USED(page);
680 #ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
681     LX_PARAMETER_NOT_USED(nand_flash);
682 #endif
683 
684     /* Custom processing goes here...  all errors except for LX_NAND_ERROR_CORRECTED are fatal.  */
685     return(LX_ERROR);
686 }
687 
688 
689 
690