GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lx_nand_flash_simulator.c Lines: 125 157 79.6 %
Date: 2024-03-11 05:20:25 Branches: 47 68 69.1 %

Line Branch Exec Source
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
142
9
UINT  _lx_nand_flash_simulator_initialize(LX_NAND_FLASH *nand_flash)
143
{
144
145
    /* Setup the buffer pointer.  */
146
9
    nand_flash_memory = (ULONG *) &nand_memory_area[0];
147
148
    /* Setup geometry of the NAND flash.  */
149
9
    nand_flash -> lx_nand_flash_total_blocks =                  TOTAL_BLOCKS;
150
9
    nand_flash -> lx_nand_flash_pages_per_block =               PHYSICAL_PAGES_PER_BLOCK;
151
9
    nand_flash -> lx_nand_flash_bytes_per_page =                BYTES_PER_PHYSICAL_PAGE;
152
153
    /* Setup function pointers for the NAND flash services.  */
154
9
    nand_flash -> lx_nand_flash_driver_read =                   _lx_nand_flash_simulator_read;
155
9
    nand_flash -> lx_nand_flash_driver_write =                  _lx_nand_flash_simulator_write;
156
9
    nand_flash -> lx_nand_flash_driver_block_erase =            _lx_nand_flash_simulator_block_erase;
157
9
    nand_flash -> lx_nand_flash_driver_block_erased_verify =    _lx_nand_flash_simulator_block_erased_verify;
158
9
    nand_flash -> lx_nand_flash_driver_page_erased_verify =     _lx_nand_flash_simulator_page_erased_verify;
159
9
    nand_flash -> lx_nand_flash_driver_block_status_get =       _lx_nand_flash_simulator_block_status_get;
160
9
    nand_flash -> lx_nand_flash_driver_block_status_set =       _lx_nand_flash_simulator_block_status_set;
161
9
    nand_flash -> lx_nand_flash_driver_extra_bytes_get =        _lx_nand_flash_simulator_extra_bytes_get;
162
9
    nand_flash -> lx_nand_flash_driver_extra_bytes_set =        _lx_nand_flash_simulator_extra_bytes_set;
163
9
    nand_flash -> lx_nand_flash_driver_system_error =           _lx_nand_flash_simulator_system_error;
164
165
9
    nand_flash -> lx_nand_flash_driver_pages_read =             _lx_nand_flash_simulator_pages_read;
166
9
    nand_flash -> lx_nand_flash_driver_pages_write =            _lx_nand_flash_simulator_pages_write;
167
9
    nand_flash -> lx_nand_flash_driver_pages_copy =             _lx_nand_flash_simulator_pages_copy;
168
169
9
    nand_flash -> lx_nand_flash_spare_data1_offset =            SPARE_DATA1_OFFSET;
170
9
    nand_flash -> lx_nand_flash_spare_data1_length =            SPARE_DATA1_LENGTH;
171
172
9
    nand_flash -> lx_nand_flash_spare_data2_offset =            SPARE_DATA2_OFFSET;
173
9
    nand_flash -> lx_nand_flash_spare_data2_length =            SPARE_DATA2_LENGTH;
174
175
9
    nand_flash -> lx_nand_flash_spare_total_length =            SPARE_BYTES_PER_PAGE;
176
177
    /* Return success.  */
178
9
    return(LX_SUCCESS);
179
}
180
407470
UINT _lx_nand_flash_simulator_page_ecc_check(ULONG block, ULONG page)
181
{
182
183
UINT    i;
184
407470
INT     ecc_pos = 0;
185
407470
UINT    ecc_status = LX_SUCCESS;
186
UINT    status;
187
188
189
1222410
    for (i = 0; i < BYTES_PER_PHYSICAL_PAGE; i += 256)
190
    {
191
814940
        status = lx_nand_flash_256byte_ecc_check((UCHAR*)&nand_memory_area[block].physical_pages[page].memory[i / sizeof(ULONG)],
192
814940
            &nand_memory_area[block].physical_pages[page].spare[ECC_BYTE_POSITION + ecc_pos]);
193
194
814940
        if (status == LX_NAND_ERROR_NOT_CORRECTED)
195
        {
196
            ecc_status = LX_NAND_ERROR_NOT_CORRECTED;
197
            break;
198
        }
199
814940
        else if (status == LX_NAND_ERROR_CORRECTED)
200
        {
201
            ecc_status = LX_NAND_ERROR_CORRECTED;
202
        }
203
204
814940
        ecc_pos += 3;
205
    }
206
207
407470
    if (ecc_status == LX_NAND_ERROR_CORRECTED)
208
    {
209
210
        return(LX_ERROR);
211
    }
212
407470
    else if (ecc_status == LX_NAND_ERROR_NOT_CORRECTED)
213
    {
214
215
        return(LX_ERROR);
216
    }
217
407470
    return ecc_status;
218
}
219
220
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
221
UINT  _lx_nand_flash_simulator_read(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, ULONG *destination, ULONG words)
222
#else
223
407470
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
407470
    status = _lx_nand_flash_simulator_page_ecc_check(block, page);
235
236
    /* Pickup the flash address.  */
237
407470
    flash_address =  &(nand_memory_area[block].physical_pages[page].memory[0]);
238
239
    /* Loop to read flash.  */
240
52563630
    while (words--)
241
    {
242
        /* Copy word.  */
243
52156160
        *destination++ =  *flash_address++;
244
    }
245
246
407470
    return(status);
247
}
248
249
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
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
1406699
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
1406699
UINT    ecc_status = LX_SUCCESS;
259
260
261
2813398
    for (i = 0; i < pages; i++)
262
    {
263
1406699
        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
407470
            status = _lx_nand_flash_simulator_read(block, page + i, (ULONG*)(main_buffer + i * BYTES_PER_PHYSICAL_PAGE), WORDS_PER_PHYSICAL_PAGE);
270
#endif
271
407470
            if (status == LX_NAND_ERROR_CORRECTED)
272
            {
273
                ecc_status = LX_NAND_ERROR_CORRECTED;
274
            }
275
407470
            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
1406699
        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
1406699
    return (ecc_status);
288
}
289
290
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
291
UINT  _lx_nand_flash_simulator_write(LX_NAND_FLASH *nand_flash, ULONG block, ULONG page, ULONG *source, ULONG words)
292
#else
293
396827
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
396827
UINT    ecc_bytes =0;
301
UCHAR   new_ecc_buffer[24];
302
396827
UCHAR   *new_ecc_buffer_ptr = new_ecc_buffer;
303
396827
UCHAR   *ecc_buffer_ptr = new_ecc_buffer_ptr;
304
396827
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
396827
    nand_block_diag[block].page_writes[page]++;
312
396827
    if (nand_block_diag[block].page_writes[page] > nand_block_diag[block].max_page_writes[page])
313
252824
        nand_block_diag[block].max_page_writes[page] =  nand_block_diag[block].page_writes[page];
314
315
    /* Pickup the flash address.  */
316
396827
    flash_address =  &(nand_memory_area[block].physical_pages[page].memory[0]);
317
318
    /* Loop to write flash.  */
319
51190683
    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
50793856
        if ((*source & *flash_address) != *source)
325
           return(LX_INVALID_WRITE);
326
327
        /* Copy word.  */
328
50793856
        *flash_address++ =  *source++;
329
    }
330
331
    /* Loop to compute the ECC over the entire NAND flash page.  */
332
396827
    bytes_computed =  0;
333
334
1190481
    while (bytes_computed < BYTES_PER_PHYSICAL_PAGE)
335
    {
336
337
        /* Compute the ECC for this 256 byte piece of the page.  */
338
793654
        _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
793654
        bytes_computed =  bytes_computed + 256;
342
343
        /* Move the page buffer forward.  */
344
793654
        page_ptr =  page_ptr + 64;
345
346
793654
        ecc_bytes = ecc_bytes + 3;
347
348
        /* Move the ECC buffer forward, note there are 3 bytes of ECC per page. */
349
793654
        new_ecc_buffer_ptr =   new_ecc_buffer_ptr + 3;
350
    }
351
352
    /* Setup destination pointer in the spare area.  */
353
396827
    flash_spare_address =  (UCHAR *) &(nand_memory_area[block].physical_pages[page].spare[ECC_BYTE_POSITION]);
354
2777789
    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
2380962
        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
2380962
       *flash_spare_address++ =  *ecc_buffer_ptr++;
364
365
    }
366
396827
    return(LX_SUCCESS);
367
}
368
369
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
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
396827
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
396827
UINT    status = LX_SUCCESS;
378
379
380
793654
    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
396827
        _lx_nand_flash_simulator_extra_bytes_set(block, page + i, spare_buffer + i * SPARE_BYTES_PER_PAGE, SPARE_BYTES_PER_PAGE);
387
396827
        status = _lx_nand_flash_simulator_write(block, page + i, (ULONG*)(main_buffer + i * BYTES_PER_PHYSICAL_PAGE), WORDS_PER_PHYSICAL_PAGE);
388
#endif
389
396827
        if (status == LX_INVALID_WRITE)
390
        {
391
            break;
392
        }
393
394
    }
395
396827
    return (status);
396
}
397
398
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
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
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)
402
#endif
403
{
404
    UINT    i;
405
8731
    UINT    status = LX_SUCCESS;
406
407
408
299314
    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
290583
        status = _lx_nand_flash_simulator_pages_read(source_block, source_page + i, data_buffer, data_buffer + BYTES_PER_PHYSICAL_PAGE, 1);
414
#endif
415

290583
        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
290583
        status = _lx_nand_flash_simulator_pages_write(destination_block, destination_page + i, data_buffer, data_buffer + BYTES_PER_PHYSICAL_PAGE, 1);
423
#endif
424
290583
        if (status != LX_SUCCESS)
425
        {
426
            break;
427
        }
428
429
    }
430
8731
    return (status);
431
432
}
433
434
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
435
UINT  _lx_nand_flash_simulator_block_erase(LX_NAND_FLASH *nand_flash, ULONG block, ULONG erase_count)
436
#else
437
5514
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
5514
    nand_block_diag[block].erases++;
452
1417098
    for (i = 0; i < PHYSICAL_PAGES_PER_BLOCK;i++)
453
1411584
        nand_block_diag[block].page_writes[i] = 0;
454
455
    /* Setup pointer.  */
456
5514
    pointer =  (ULONG *) &nand_memory_area[block];
457
458
    /* Loop to erase block.  */
459
5514
    words =  sizeof(NAND_FLASH_BLOCK)/sizeof(ULONG);
460
186334602
    while (words--)
461
    {
462
463
        /* Erase word of block.  */
464
186329088
        *pointer++ =  (ULONG) 0xFFFFFFFF;
465
    }
466
467
5514
    return(LX_SUCCESS);
468
}
469
470
471
4
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
4100
    for (i = 0; i < TOTAL_BLOCKS; i++)
481
    {
482
4096
    nand_block_diag[i].erases =  0;
483
1052672
    for (j = 0; j < PHYSICAL_PAGES_PER_BLOCK;j++)
484
1048576
        nand_block_diag[i].page_writes[j] = 0;
485
    }
486
487
    /* Setup pointer.  */
488
4
    pointer =  (ULONG *) &nand_memory_area[0];
489
490
    /* Loop to erase block.  */
491
4
    words =  sizeof(nand_memory_area)/(sizeof(ULONG));
492
138412036
    while (words--)
493
    {
494
495
        /* Erase word of block.  */
496
138412032
        *pointer++ =  (ULONG) 0xFFFFFFFF;
497
    }
498
499
4
    return(LX_SUCCESS);
500
}
501
502
503
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
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
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
574
UINT  _lx_nand_flash_simulator_block_status_get(LX_NAND_FLASH *nand_flash, ULONG block, UCHAR *bad_block_byte)
575
#else
576
4101
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
4101
    *bad_block_byte =  nand_memory_area[block].physical_pages[0].spare[BAD_BLOCK_POSITION];
586
587
    /* Return success.  */
588
4101
    return(LX_SUCCESS);
589
}
590
591
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
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
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
1406699
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
1406699
    source =  (UCHAR *) &(nand_memory_area[block].physical_pages[page].spare[EXTRA_BYTE_POSITION]);
625
626
    /* Loop to return the extra bytes requested.  */
627
23913883
    while (size--)
628
    {
629
630
        /* Retrieve an extra byte from the spare area.  */
631
22507184
        *destination++ =  *source++;
632
    }
633
634
    /* Return success.  */
635
1406699
    return(LX_SUCCESS);
636
}
637
638
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
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
396827
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
396827
    nand_block_diag[block].page_writes[page]++;
653
396827
    if (nand_block_diag[block].page_writes[page] > nand_block_diag[block].max_page_writes[page])
654
252824
        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
396827
    destination =  (UCHAR *) &(nand_memory_area[block].physical_pages[page].spare[EXTRA_BYTE_POSITION]);
658
659
    /* Loop to set the extra bytes.  */
660
6746059
    while (size--)
661
    {
662
663
        /* Set an extra byte in the spare area.  */
664
6349232
        *destination++ =  *source++;
665
    }
666
667
    /* Return success.  */
668
396827
    return(LX_SUCCESS);
669
}
670
671
#ifdef LX_NAND_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
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