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