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