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