GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lx_nand_flash_simulator.c Lines: 126 158 79.7 %
Date: 2026-03-06 18:45:40 Branches: 49 70 70.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
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
143
9
UINT  _lx_nand_flash_simulator_initialize(LX_NAND_FLASH *nand_flash)
144
{
145
146
    /* Setup the buffer pointer.  */
147
9
    nand_flash_memory = (ULONG *) &nand_memory_area[0];
148
149
    /* Setup geometry of the NAND flash.  */
150
9
    nand_flash -> lx_nand_flash_total_blocks =                  TOTAL_BLOCKS;
151
9
    nand_flash -> lx_nand_flash_pages_per_block =               PHYSICAL_PAGES_PER_BLOCK;
152
9
    nand_flash -> lx_nand_flash_bytes_per_page =                BYTES_PER_PHYSICAL_PAGE;
153
154
    /* Setup function pointers for the NAND flash services.  */
155
9
    nand_flash -> lx_nand_flash_driver_read =                   _lx_nand_flash_simulator_read;
156
9
    nand_flash -> lx_nand_flash_driver_write =                  _lx_nand_flash_simulator_write;
157
9
    nand_flash -> lx_nand_flash_driver_block_erase =            _lx_nand_flash_simulator_block_erase;
158
9
    nand_flash -> lx_nand_flash_driver_block_erased_verify =    _lx_nand_flash_simulator_block_erased_verify;
159
9
    nand_flash -> lx_nand_flash_driver_page_erased_verify =     _lx_nand_flash_simulator_page_erased_verify;
160
9
    nand_flash -> lx_nand_flash_driver_block_status_get =       _lx_nand_flash_simulator_block_status_get;
161
9
    nand_flash -> lx_nand_flash_driver_block_status_set =       _lx_nand_flash_simulator_block_status_set;
162
9
    nand_flash -> lx_nand_flash_driver_extra_bytes_get =        _lx_nand_flash_simulator_extra_bytes_get;
163
9
    nand_flash -> lx_nand_flash_driver_extra_bytes_set =        _lx_nand_flash_simulator_extra_bytes_set;
164
9
    nand_flash -> lx_nand_flash_driver_system_error =           _lx_nand_flash_simulator_system_error;
165
166
9
    nand_flash -> lx_nand_flash_driver_pages_read =             _lx_nand_flash_simulator_pages_read;
167
9
    nand_flash -> lx_nand_flash_driver_pages_write =            _lx_nand_flash_simulator_pages_write;
168
9
    nand_flash -> lx_nand_flash_driver_pages_copy =             _lx_nand_flash_simulator_pages_copy;
169
170
9
    nand_flash -> lx_nand_flash_spare_data1_offset =            SPARE_DATA1_OFFSET;
171
9
    nand_flash -> lx_nand_flash_spare_data1_length =            SPARE_DATA1_LENGTH;
172
173
9
    nand_flash -> lx_nand_flash_spare_data2_offset =            SPARE_DATA2_OFFSET;
174
9
    nand_flash -> lx_nand_flash_spare_data2_length =            SPARE_DATA2_LENGTH;
175
176
9
    nand_flash -> lx_nand_flash_spare_total_length =            SPARE_BYTES_PER_PAGE;
177
178
    /* Return success.  */
179
9
    return(LX_SUCCESS);
180
}
181
295282
UINT _lx_nand_flash_simulator_page_ecc_check(ULONG block, ULONG page)
182
{
183
184
UINT    i;
185
295282
INT     ecc_pos = 0;
186
295282
UINT    ecc_status = LX_SUCCESS;
187
UINT    status;
188
189
190
885846
    for (i = 0; i < BYTES_PER_PHYSICAL_PAGE; i += 256)
191
    {
192
590564
        status = lx_nand_flash_256byte_ecc_check((UCHAR*)&nand_memory_area[block].physical_pages[page].memory[i / sizeof(ULONG)],
193
590564
            &nand_memory_area[block].physical_pages[page].spare[ECC_BYTE_POSITION + ecc_pos]);
194
195
590564
        if (status == LX_NAND_ERROR_NOT_CORRECTED)
196
        {
197
            ecc_status = LX_NAND_ERROR_NOT_CORRECTED;
198
            break;
199
        }
200
590564
        else if (status == LX_NAND_ERROR_CORRECTED)
201
        {
202
            ecc_status = LX_NAND_ERROR_CORRECTED;
203
        }
204
205
590564
        ecc_pos += 3;
206
    }
207
208
295282
    if (ecc_status == LX_NAND_ERROR_CORRECTED)
209
    {
210
211
        return(LX_ERROR);
212
    }
213
295282
    else if (ecc_status == LX_NAND_ERROR_NOT_CORRECTED)
214
    {
215
216
        return(LX_ERROR);
217
    }
218
295282
    return ecc_status;
219
}
220
221
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
222
UINT  _lx_nand_flash_simulator_read(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, ULONG *destination, ULONG words)
223
#else
224
295282
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
295282
    status = _lx_nand_flash_simulator_page_ecc_check(block, page);
236
237
    /* Pickup the flash address.  */
238
295282
    flash_address =  &(nand_memory_area[block].physical_pages[page].memory[0]);
239
240
    /* Loop to read flash.  */
241
38091378
    while (words--)
242
    {
243
        /* Copy word.  */
244
37796096
        *destination++ =  *flash_address++;
245
    }
246
247
295282
    return(status);
248
}
249
250
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
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
1407715
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
1407715
UINT    ecc_status = LX_SUCCESS;
260
261
262
2815430
    for (i = 0; i < pages; i++)
263
    {
264
1407715
        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
295282
            status = _lx_nand_flash_simulator_read(block, page + i, (ULONG*)(main_buffer + i * BYTES_PER_PHYSICAL_PAGE), WORDS_PER_PHYSICAL_PAGE);
271
#endif
272
295282
            if (status == LX_NAND_ERROR_CORRECTED)
273
            {
274
                ecc_status = LX_NAND_ERROR_CORRECTED;
275
            }
276
295282
            else if (status == LX_NAND_ERROR_NOT_CORRECTED)
277
            {
278
                ecc_status = LX_ERROR;
279
                break;
280
            }
281
        }
282
283
1407715
        if (spare_buffer)
284
        {
285
286
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
287
            status = _lx_nand_flash_simulator_extra_bytes_get(nand_flash, block, page + i, spare_buffer + i * SPARE_BYTES_PER_PAGE, SPARE_BYTES_PER_PAGE);
288
#else
289
1406699
            status = _lx_nand_flash_simulator_extra_bytes_get(block, page + i, spare_buffer + i * SPARE_BYTES_PER_PAGE, SPARE_BYTES_PER_PAGE);
290
#endif
291
        }
292
    }
293
1407715
    return (ecc_status);
294
}
295
296
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
297
UINT  _lx_nand_flash_simulator_write(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, ULONG *source, ULONG words)
298
#else
299
396827
UINT  _lx_nand_flash_simulator_write(ULONG block, ULONG page, ULONG *source, ULONG words)
300
#endif
301
{
302
303
ULONG   *flash_address;
304
UCHAR   *flash_spare_address;
305
UINT    bytes_computed;
306
396827
UINT    ecc_bytes =0;
307
UCHAR   new_ecc_buffer[24];
308
396827
UCHAR   *new_ecc_buffer_ptr = new_ecc_buffer;
309
396827
UCHAR   *ecc_buffer_ptr = new_ecc_buffer_ptr;
310
396827
ULONG   *page_ptr = &(nand_memory_area[block].physical_pages[page].memory[0]);
311
312
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
313
    LX_PARAMETER_NOT_USED(nand_flash);
314
#endif
315
316
    /* Increment the diag info.  */
317
396827
    nand_block_diag[block].page_writes[page]++;
318
396827
    if (nand_block_diag[block].page_writes[page] > nand_block_diag[block].max_page_writes[page])
319
252824
        nand_block_diag[block].max_page_writes[page] =  nand_block_diag[block].page_writes[page];
320
321
    /* Pickup the flash address.  */
322
396827
    flash_address =  &(nand_memory_area[block].physical_pages[page].memory[0]);
323
324
    /* Loop to write flash.  */
325
51190683
    while (words--)
326
    {
327
328
        /* Can the word be written?  We can clear new bits, but just can't unclear
329
           in a NAND device.  */
330
50793856
        if ((*source & *flash_address) != *source)
331
           return(LX_INVALID_WRITE);
332
333
        /* Copy word.  */
334
50793856
        *flash_address++ =  *source++;
335
    }
336
337
    /* Loop to compute the ECC over the entire NAND flash page.  */
338
396827
    bytes_computed =  0;
339
340
1190481
    while (bytes_computed < BYTES_PER_PHYSICAL_PAGE)
341
    {
342
343
        /* Compute the ECC for this 256 byte piece of the page.  */
344
793654
        _lx_nand_flash_256byte_ecc_compute((UCHAR *)page_ptr, (UCHAR *)new_ecc_buffer_ptr);
345
346
        /* Move to the next 256 byte portion of the page.  */
347
793654
        bytes_computed =  bytes_computed + 256;
348
349
        /* Move the page buffer forward.  */
350
793654
        page_ptr =  page_ptr + 64;
351
352
793654
        ecc_bytes = ecc_bytes + 3;
353
354
        /* Move the ECC buffer forward, note there are 3 bytes of ECC per page. */
355
793654
        new_ecc_buffer_ptr =   new_ecc_buffer_ptr + 3;
356
    }
357
358
    /* Setup destination pointer in the spare area.  */
359
396827
    flash_spare_address =  (UCHAR *) &(nand_memory_area[block].physical_pages[page].spare[ECC_BYTE_POSITION]);
360
2777789
    while(ecc_bytes--)
361
    {
362
363
        /* Can the word be written?  We can clear new bits, but just can't unclear
364
           in a NAND device.  */
365
2380962
        if ((*ecc_buffer_ptr & *flash_spare_address) != *ecc_buffer_ptr)
366
           return(LX_INVALID_WRITE);
367
368
        /* Set an ecc byte in the spare area.  */
369
2380962
       *flash_spare_address++ =  *ecc_buffer_ptr++;
370
371
    }
372
396827
    return(LX_SUCCESS);
373
}
374
375
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
376
UINT  _lx_nand_flash_simulator_pages_write(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, UCHAR* main_buffer, UCHAR* spare_buffer, ULONG pages)
377
#else
378
396827
UINT  _lx_nand_flash_simulator_pages_write(ULONG block, ULONG page, UCHAR* main_buffer, UCHAR* spare_buffer, ULONG pages)
379
#endif
380
{
381
382
UINT    i;
383
396827
UINT    status = LX_SUCCESS;
384
385
386
793654
    for (i = 0; i < pages; i++)
387
    {
388
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
389
        _lx_nand_flash_simulator_extra_bytes_set(nand_flash, block, page + i, spare_buffer + i * SPARE_BYTES_PER_PAGE, SPARE_BYTES_PER_PAGE);
390
        status = _lx_nand_flash_simulator_write(nand_flash, block, page + i, (ULONG*)(main_buffer + i * BYTES_PER_PHYSICAL_PAGE), WORDS_PER_PHYSICAL_PAGE);
391
#else
392
396827
        _lx_nand_flash_simulator_extra_bytes_set(block, page + i, spare_buffer + i * SPARE_BYTES_PER_PAGE, SPARE_BYTES_PER_PAGE);
393
396827
        status = _lx_nand_flash_simulator_write(block, page + i, (ULONG*)(main_buffer + i * BYTES_PER_PHYSICAL_PAGE), WORDS_PER_PHYSICAL_PAGE);
394
#endif
395
396827
        if (status == LX_INVALID_WRITE)
396
        {
397
            break;
398
        }
399
400
    }
401
396827
    return (status);
402
}
403
404
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
405
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)
406
#else
407
8731
UINT  _lx_nand_flash_simulator_pages_copy(ULONG source_block, ULONG source_page, ULONG destination_block, ULONG destination_page, ULONG pages, UCHAR *data_buffer)
408
#endif
409
{
410
    UINT    i;
411
8731
    UINT    status = LX_SUCCESS;
412
413
414
299314
    for (i = 0; i < pages; i++)
415
    {
416
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
417
        status = _lx_nand_flash_simulator_pages_read(nand_flash, source_block, source_page + i, data_buffer, data_buffer + BYTES_PER_PHYSICAL_PAGE, 1);
418
#else
419
290583
        status = _lx_nand_flash_simulator_pages_read(source_block, source_page + i, data_buffer, data_buffer + BYTES_PER_PHYSICAL_PAGE, 1);
420
#endif
421

290583
        if (status != LX_SUCCESS && status != LX_NAND_ERROR_CORRECTED)
422
        {
423
            break;
424
        }
425
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
426
        status = _lx_nand_flash_simulator_pages_write(nand_flash, destination_block, destination_page + i, data_buffer, data_buffer + BYTES_PER_PHYSICAL_PAGE, 1);
427
#else
428
290583
        status = _lx_nand_flash_simulator_pages_write(destination_block, destination_page + i, data_buffer, data_buffer + BYTES_PER_PHYSICAL_PAGE, 1);
429
#endif
430
290583
        if (status != LX_SUCCESS)
431
        {
432
            break;
433
        }
434
435
    }
436
8731
    return (status);
437
438
}
439
440
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
441
UINT  _lx_nand_flash_simulator_block_erase(LX_NAND_FLASH *nand_flash, ULONG block, ULONG erase_count)
442
#else
443
5514
UINT  _lx_nand_flash_simulator_block_erase(ULONG block, ULONG erase_count)
444
#endif
445
{
446
447
ULONG   *pointer;
448
ULONG   words;
449
UINT    i;
450
451
    LX_PARAMETER_NOT_USED(erase_count);
452
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
453
    LX_PARAMETER_NOT_USED(nand_flash);
454
#endif
455
456
    /* Increment the diag info.  */
457
5514
    nand_block_diag[block].erases++;
458
1417098
    for (i = 0; i < PHYSICAL_PAGES_PER_BLOCK;i++)
459
1411584
        nand_block_diag[block].page_writes[i] = 0;
460
461
    /* Setup pointer.  */
462
5514
    pointer =  (ULONG *) &nand_memory_area[block];
463
464
    /* Loop to erase block.  */
465
5514
    words =  sizeof(NAND_FLASH_BLOCK)/sizeof(ULONG);
466
186334602
    while (words--)
467
    {
468
469
        /* Erase word of block.  */
470
186329088
        *pointer++ =  (ULONG) 0xFFFFFFFF;
471
    }
472
473
5514
    return(LX_SUCCESS);
474
}
475
476
477
4
UINT  _lx_nand_flash_simulator_erase_all(VOID)
478
{
479
480
ULONG   *pointer;
481
ULONG   words;
482
UINT    i, j;
483
484
485
    /* Increment the diag info.  */
486
4100
    for (i = 0; i < TOTAL_BLOCKS; i++)
487
    {
488
4096
    nand_block_diag[i].erases =  0;
489
1052672
    for (j = 0; j < PHYSICAL_PAGES_PER_BLOCK;j++)
490
1048576
        nand_block_diag[i].page_writes[j] = 0;
491
    }
492
493
    /* Setup pointer.  */
494
4
    pointer =  (ULONG *) &nand_memory_area[0];
495
496
    /* Loop to erase block.  */
497
4
    words =  sizeof(nand_memory_area)/(sizeof(ULONG));
498
138412036
    while (words--)
499
    {
500
501
        /* Erase word of block.  */
502
138412032
        *pointer++ =  (ULONG) 0xFFFFFFFF;
503
    }
504
505
4
    return(LX_SUCCESS);
506
}
507
508
509
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
510
UINT  _lx_nand_flash_simulator_block_erased_verify(LX_NAND_FLASH *nand_flash, ULONG block)
511
#else
512
UINT  _lx_nand_flash_simulator_block_erased_verify(ULONG block)
513
#endif
514
{
515
516
ULONG   *word_ptr;
517
ULONG   words;
518
519
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
520
    LX_PARAMETER_NOT_USED(nand_flash);
521
#endif
522
523
    /* Determine if the block is completely erased.  */
524
525
    /* Pickup the pointer to the first word of the block.  */
526
    word_ptr =  (ULONG *) &nand_memory_area[block];
527
528
    /* Calculate the number of words in a block.  */
529
    words =  sizeof(NAND_FLASH_BLOCK)/sizeof(ULONG);
530
531
    /* Loop to check if the block is erased.  */
532
    while (words--)
533
    {
534
535
        /* Is this word erased?  */
536
        if (*word_ptr++ != 0xFFFFFFFF)
537
            return(LX_ERROR);
538
    }
539
540
    /* Return success.  */
541
    return(LX_SUCCESS);
542
}
543
544
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
545
UINT  _lx_nand_flash_simulator_page_erased_verify(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page)
546
#else
547
UINT  _lx_nand_flash_simulator_page_erased_verify(ULONG block, ULONG page)
548
#endif
549
{
550
551
ULONG   *word_ptr;
552
ULONG   words;
553
554
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
555
    LX_PARAMETER_NOT_USED(nand_flash);
556
#endif
557
558
    /* Determine if the block is completely erased.  */
559
560
    /* Pickup the pointer to the first word of the block's page.  */
561
    word_ptr =  (ULONG *) &nand_memory_area[block].physical_pages[page];
562
563
    /* Calculate the number of words in a block.  */
564
    words =  WORDS_PER_PHYSICAL_PAGE;
565
566
    /* Loop to check if the page is erased.  */
567
    while (words--)
568
    {
569
570
        /* Is this word erased?  */
571
        if (*word_ptr++ != 0xFFFFFFFF)
572
            return(LX_ERROR);
573
    }
574
575
    /* Return success.  */
576
    return(LX_SUCCESS);
577
}
578
579
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
580
UINT  _lx_nand_flash_simulator_block_status_get(LX_NAND_FLASH *nand_flash, ULONG block, UCHAR *bad_block_byte)
581
#else
582
4101
UINT  _lx_nand_flash_simulator_block_status_get(ULONG block, UCHAR *bad_block_byte)
583
#endif
584
{
585
586
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
587
    LX_PARAMETER_NOT_USED(nand_flash);
588
#endif
589
590
    /* Pickup the bad block byte and return it.  */
591
4101
    *bad_block_byte =  nand_memory_area[block].physical_pages[0].spare[BAD_BLOCK_POSITION];
592
593
    /* Return success.  */
594
4101
    return(LX_SUCCESS);
595
}
596
597
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
598
UINT  _lx_nand_flash_simulator_block_status_set(LX_NAND_FLASH *nand_flash, ULONG block, UCHAR bad_block_byte)
599
#else
600
UINT  _lx_nand_flash_simulator_block_status_set(ULONG block, UCHAR bad_block_byte)
601
#endif
602
{
603
604
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
605
    LX_PARAMETER_NOT_USED(nand_flash);
606
#endif
607
608
    /* Set the bad block byte.  */
609
    nand_memory_area[block].physical_pages[0].spare[BAD_BLOCK_POSITION] =  bad_block_byte;
610
611
    /* Return success.  */
612
    return(LX_SUCCESS);
613
}
614
615
616
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
617
UINT  _lx_nand_flash_simulator_extra_bytes_get(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, UCHAR *destination, UINT size)
618
#else
619
1406699
UINT  _lx_nand_flash_simulator_extra_bytes_get(ULONG block, ULONG page, UCHAR *destination, UINT size)
620
#endif
621
{
622
623
UCHAR   *source;
624
625
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
626
    LX_PARAMETER_NOT_USED(nand_flash);
627
#endif
628
629
    /* Setup source pointer in the spare area.  */
630
1406699
    source =  (UCHAR *) &(nand_memory_area[block].physical_pages[page].spare[EXTRA_BYTE_POSITION]);
631
632
    /* Loop to return the extra bytes requested.  */
633
23913883
    while (size--)
634
    {
635
636
        /* Retrieve an extra byte from the spare area.  */
637
22507184
        *destination++ =  *source++;
638
    }
639
640
    /* Return success.  */
641
1406699
    return(LX_SUCCESS);
642
}
643
644
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
645
UINT  _lx_nand_flash_simulator_extra_bytes_set(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, UCHAR *source, UINT size)
646
#else
647
396827
UINT  _lx_nand_flash_simulator_extra_bytes_set(ULONG block, ULONG page, UCHAR *source, UINT size)
648
#endif
649
{
650
651
UCHAR   *destination;
652
653
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
654
    LX_PARAMETER_NOT_USED(nand_flash);
655
#endif
656
657
    /* Increment the diag info.  */
658
396827
    nand_block_diag[block].page_writes[page]++;
659
396827
    if (nand_block_diag[block].page_writes[page] > nand_block_diag[block].max_page_writes[page])
660
252824
        nand_block_diag[block].max_page_writes[page] =  nand_block_diag[block].page_writes[page];
661
662
    /* Setup destination pointer in the spare area.  */
663
396827
    destination =  (UCHAR *) &(nand_memory_area[block].physical_pages[page].spare[EXTRA_BYTE_POSITION]);
664
665
    /* Loop to set the extra bytes.  */
666
6746059
    while (size--)
667
    {
668
669
        /* Set an extra byte in the spare area.  */
670
6349232
        *destination++ =  *source++;
671
    }
672
673
    /* Return success.  */
674
396827
    return(LX_SUCCESS);
675
}
676
677
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
678
UINT  _lx_nand_flash_simulator_system_error(LX_NAND_FLASH *nand_flash, UINT error_code, ULONG block, ULONG page)
679
#else
680
UINT  _lx_nand_flash_simulator_system_error(UINT error_code, ULONG block, ULONG page)
681
#endif
682
{
683
    LX_PARAMETER_NOT_USED(error_code);
684
    LX_PARAMETER_NOT_USED(block);
685
    LX_PARAMETER_NOT_USED(page);
686
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
687
    LX_PARAMETER_NOT_USED(nand_flash);
688
#endif
689
690
    /* Custom processing goes here...  all errors except for LX_NAND_ERROR_CORRECTED are fatal.  */
691
    return(LX_ERROR);
692
}
693
694
695