nf_unusual.c File Reference

#include "config.h"
#include "conf_nf.h"
#include "nf.h"
#include "nf_drv.h"
#include "nf_mngt.h"
#include "lib_mcu/debug.h"

Include dependency graph for nf_unusual.c:

Go to the source code of this file.

Defines

#define _TRACE_   (DISABLE)
#define OFST   (2*(i_dev + u16_tmp*NF_N_DEVICES))

Functions

__no_init volatile
xdata Byte
nf_send_cmd 
At (0x3900)
__no_init volatile
xdata Byte
nf_send_add 
At (0x3A00)
__no_init volatile
xdata Byte nf_data 
At (0x3800)
static void ut_nfc_erase_all (void)
static void nf_init_buffer (void)
 Clears the internal buffer.
static Status_bool nf_scan (void)
 Scan the memory and looks for sub-LUT, free-blocks block and recovery blocks.
static Status_bool nf_rebuild (void)
static Bool is_nf_invalid (void)
static U16 nf_fetch_free_block (U8 i_dev)
 Returns the first free block seen, scanning downstream.
static U8 nf_refine_index (U16 block_addr, U8 inc, U8 pattern)
 Refines the position of the 'block' index according to a particular pattern.
void nf_init (void)
 Initializes the nand flash memory driver.
Status_bool nf_verify_resume (void)
 Ensure that the memory is in a good state before starting to use it.
void nf_cleanup_memory (void)
 Cleanup the memory by erasing all the management blocks.

Variables

_MEM_TYPE_SLOW_ U8 g_n_zones
_MEM_TYPE_SLOW_ U16 g_n_blocks
_MEM_TYPE_SLOW_ U8 g_page_buffer [((2048)+(2048)/32)]
_MEM_TYPE_BIT_ bit g_nf_init
_MEM_TYPE_SLOW_ U16 g_last_sub_lut_log_sz
_MEM_TYPE_SLOW_ U16 g_sub_lut_log_sz
Bool g_is_found_lut
Bool g_is_found_fbb
Bool g_fatal
_MEM_TYPE_SLOW_ U8 g_n_real_sub_lut
_MEM_TYPE_SLOW_ U16 g_curr_block_addr [NF_N_DEVICES]
_MEM_TYPE_SLOW_ U8 g_byte [16]
_MEM_TYPE_SLOW_ U8 g_n_sub_lut
_MEM_TYPE_SLOW_ U16 g_lut_block_addr [(NF_N_DEVICES *(8 *1024)/(512/2))]
_MEM_TYPE_SLOW_ U8 g_lut_block_index [(NF_N_DEVICES *(8 *1024)/(512/2))]
static _MEM_TYPE_SLOW_ U8 s_nfd_rev
_MEM_TYPE_SLOW_ U16 g_nf_first_block
static _MEM_TYPE_SLOW_ U8 s_n_quarantine_blocks [NF_N_DEVICES]
static
_MEM_TYPE_SLOW_ U16 
s_n_invalid_blocks [NF_N_DEVICES]
_MEM_TYPE_SLOW_ U16 g_n_export_blocks
_MEM_TYPE_SLOW_ U16 g_n_free_blocks
_MEM_TYPE_SLOW_ U16 g_fbb_block_addr
_MEM_TYPE_SLOW_ U8 g_fbb_block_index
_MEM_TYPE_SLOW_ U32 g_last_log_sector
_MEM_TYPE_SLOW_ U32 g_copy_src
_MEM_TYPE_SLOW_ U16 g_block_to_kill [NF_N_DEVICES]
_MEM_TYPE_FAST_ U32 g_phys_page_addr [NF_N_DEVICES]
_MEM_TYPE_FAST_ U8 g_curr_dev_id
_MEM_TYPE_MEDFAST_ U16 g_log_block_id
_MEM_TYPE_SLOW_ Cache_lut g_cache_lut
_MEM_TYPE_SLOW_ Cache_fbb g_cache_fbb


Detailed Description

This file contains the high level management for nand-flash memory devices which are rarely used. The code is put in a bank in order to save code space.

Author:
Atmel Corporation: http://www.atmel.com
Support and FAQ: http://support.atmel.no/

Definition in file nf_unusual.c.


Define Documentation

#define _TRACE_   (DISABLE)

Definition at line 52 of file nf_unusual.c.

#define OFST   (2*(i_dev + u16_tmp*NF_N_DEVICES))

Referenced by nf_rebuild().


Function Documentation

__no_init volatile xdata Byte nf_send_cmd At ( 0x3900   ) 

__no_init volatile xdata Byte nf_send_add At ( 0x3A00   ) 

__no_init volatile xdata Byte nf_data At ( 0x3800   ) 

static void ut_nfc_erase_all ( void   )  [static]

Definition at line 920 of file nf_unusual.c.

References _MEM_TYPE_SLOW_, FALSE, G_N_BLOCKS, NF_N_DEVICES, NF_SHIFT_BLOCK_PAGE, NFC_ACT_DEV_SELECT, Nfc_action, and nfc_erase_block().

Referenced by nf_verify_resume().

00921 {
00922    _MEM_TYPE_SLOW_ U8   i_dev  =0;
00923    _MEM_TYPE_SLOW_ U16  i_block=0;
00924    _MEM_TYPE_SLOW_ U32  page_addr;
00925 
00926    for( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ )
00927    {
00928       // Select the devices
00929       //
00930       Nfc_action(NFC_ACT_DEV_SELECT, i_dev);
00931 
00932       for( i_block=g_nf_first_block ; i_block<G_N_BLOCKS ; i_block++ )
00933       {
00934          page_addr= (U32)i_block<<NF_SHIFT_BLOCK_PAGE;
00935          nfc_erase_block( page_addr, FALSE ) ;
00936       }
00937    }
00938 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void nf_init_buffer ( void   )  [static]

Clears the internal buffer.

Returns:
nothing

Definition at line 130 of file nf_unusual.c.

References NF_FULL_PAGE_BUFFER_SIZE.

Referenced by nf_rebuild().

00131 {
00132    U16 u16_tmp;
00133    for ( u16_tmp=NF_FULL_PAGE_BUFFER_SIZE ; u16_tmp!=0 ; u16_tmp-=2 )
00134    {
00135       g_page_buffer[u16_tmp-1]=0xFF;
00136       g_page_buffer[u16_tmp-2]=0xFF;
00137    }
00138 }

Here is the caller graph for this function:

static Status_bool nf_scan ( void   )  [static]

Scan the memory and looks for sub-LUT, free-blocks block and recovery blocks.

Parameters:
none 
Returns:
a status: PASS if the scan has been succesfully executed; FAIL if the scan encountered any problem

Definition at line 303 of file nf_unusual.c.

References FAIL, FALSE, G_N_BLOCKS, G_OFST_BLK_STATUS, LSB, MSB, nf_block_2_page(), NF_N_DEVICES, nf_refine_index(), NF_SUBLUT_SIZE, NFC_ACT_DEV_SELECT, Nfc_action, NFC_BLK_ID_DATA, NFC_BLK_ID_FBB, NFC_BLK_ID_QUARANTINE, NFC_BLK_ID_SUBLUT, NFC_OFST_6_FBB_VALID, nfc_read_spare_byte(), NFC_SPARE_OFST_1_BLK_ID, NFC_SPARE_OFST_2_BYTE_2, NFC_SPARE_OFST_3_BYTE_3, NFC_SPARE_OFST_4_BYTE_4, NFC_SPARE_OFST_6_LBA, NFC_SPARE_OFST_EXPORT, PASS, S_MNGT_DEV, trace(), trace_hex(), trace_hex16(), trace_nl(), trace_u32(), and TRUE.

Referenced by nf_verify_resume().

00304 {
00305    U8          i_dev  =0;
00306    U16         i_block=0;
00307    U8          n_quarantine_blocks=0;
00308    U16         n_invalid_blocks=0;
00309 
00310    g_last_sub_lut_log_sz =(U16)-1;
00311    g_sub_lut_log_sz      =(U16)NF_SUBLUT_SIZE/NF_N_DEVICES;
00312 
00313 
00314    // Initialize the recovery structure. This should be done by the startup !
00315    //
00316    g_is_found_lut  =FALSE;
00317    g_is_found_fbb  =FALSE;
00318    g_fatal         =FALSE;
00319    g_n_real_sub_lut=0;
00320 
00321    // Scan all the devices and looks for:
00322    // - the sub-LUT blocks
00323    // - the recovery block
00324    // - the free-blocks block
00325    //
00326    for( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ )
00327    {
00328       n_invalid_blocks   = 0;
00329       n_quarantine_blocks= 0;
00330       g_curr_block_addr[i_dev]= G_N_BLOCKS -1; // points on the last block
00331 
00332       trace("Device "); trace_hex(i_dev); trace("\n\r");
00333       Nfc_action(NFC_ACT_DEV_SELECT, i_dev);
00334 
00335       for( i_block=g_nf_first_block ; i_block<G_N_BLOCKS ; i_block++ )
00336       {
00337          nfc_read_spare_byte( g_byte, 16, nf_block_2_page(i_block) );
00338          if ( g_byte[G_OFST_BLK_STATUS]!=0xFF )
00339          {
00340             n_invalid_blocks +=1 ;
00341             trace_hex16(i_block); trace(" ("); trace_u32(i_block); trace("): bad Block\n\r");
00342             continue; // The block is bad
00343          }
00344 
00345          if(( g_byte[NFC_SPARE_OFST_1_BLK_ID]!=NFC_BLK_ID_SUBLUT     )
00346          && ( g_byte[NFC_SPARE_OFST_1_BLK_ID]!=NFC_BLK_ID_FBB        )
00347          && ( g_byte[NFC_SPARE_OFST_1_BLK_ID]!=NFC_BLK_ID_QUARANTINE )
00348          && ( g_byte[NFC_SPARE_OFST_1_BLK_ID]!=NFC_BLK_ID_DATA       ))
00349          {
00350             n_invalid_blocks +=1;
00351             trace_hex16(i_block); trace(" ("); trace_u32(i_block); trace("): Unknown\n\r");
00352             continue;
00353          }
00354          else if ( g_byte[NFC_SPARE_OFST_1_BLK_ID]==NFC_BLK_ID_QUARANTINE )
00355          {
00356             n_quarantine_blocks +=1;
00357             trace_hex16(i_block); trace(" ("); trace_u32(i_block); trace("): Quarantine\n\r");
00358             continue;
00359          }
00360          else if ( g_byte[NFC_SPARE_OFST_1_BLK_ID]==NFC_BLK_ID_SUBLUT )
00361          {
00362             n_invalid_blocks +=1;
00363             if ( i_dev==S_MNGT_DEV )
00364             {
00365                U8 sub_lut_id                   = g_byte[NFC_SPARE_OFST_2_BYTE_2];
00366                g_n_sub_lut                     = g_byte[NFC_SPARE_OFST_4_BYTE_4];
00367                g_is_found_lut = TRUE;
00368                g_n_real_sub_lut++;
00369                g_lut_block_addr[sub_lut_id] = i_block;
00370                if ( sub_lut_id==(g_n_sub_lut-1) )
00371                {
00372                   MSB(g_last_sub_lut_log_sz)= g_byte[NFC_SPARE_OFST_6_LBA  ];
00373                   LSB(g_last_sub_lut_log_sz)= g_byte[NFC_SPARE_OFST_6_LBA+1];
00374                }
00375                g_lut_block_index[sub_lut_id]= nf_refine_index(i_block, 1, NFC_BLK_ID_SUBLUT);
00376                trace_hex16(i_block); trace(" ("); trace_u32(i_block); trace("): SUB-LUT (id ");trace_hex(sub_lut_id);trace(" ofst "); trace_hex(g_lut_block_index[sub_lut_id]); trace(")\n\r");
00377                continue ;
00378             }
00379             else
00380             {  // LUT found on bad NF
00381                g_fatal=TRUE;
00382                break;
00383             }
00384          }
00385 
00386          else if ( g_byte[NFC_SPARE_OFST_1_BLK_ID]==NFC_BLK_ID_FBB )
00387          {
00388             n_invalid_blocks +=1;
00389             if ( i_dev==S_MNGT_DEV )
00390             {
00391                if ( TRUE==g_is_found_fbb )
00392                {
00393                   g_fatal=TRUE; // already found
00394                   break;
00395                }
00396                g_fbb_block_addr  = i_block;
00397                g_fbb_block_index = nf_refine_index(i_block, 1, NFC_BLK_ID_FBB);
00398                nfc_read_spare_byte( g_byte, 16, nf_block_2_page(i_block) + (U32)g_fbb_block_index );     // Reload
00399                if( NFC_OFST_6_FBB_VALID!=g_byte[NFC_SPARE_OFST_6_LBA] )
00400                {
00401                   g_fatal=TRUE; // FBB not valid. Force rebuild
00402                   break;
00403                }
00404 
00405                MSB(g_n_free_blocks)   = g_byte[NFC_SPARE_OFST_2_BYTE_2];
00406                LSB(g_n_free_blocks)   = g_byte[NFC_SPARE_OFST_3_BYTE_3];
00407                s_nfd_rev              = g_byte[NFC_SPARE_OFST_4_BYTE_4];
00408                MSB(g_n_export_blocks) = g_byte[NFC_SPARE_OFST_EXPORT];
00409                LSB(g_n_export_blocks) = g_byte[NFC_SPARE_OFST_EXPORT+1];
00410                trace("      g_n_free_blocks="); trace_hex16(g_n_free_blocks); trace_nl();
00411                trace("      g_n_export_blocks="); trace_hex16(g_n_export_blocks); trace_nl();
00412                g_is_found_fbb=TRUE;
00413                trace_hex16(i_block); trace(" ("); trace_u32(i_block); trace("): FBB (ofst "); trace_hex( g_fbb_block_index ); trace(")\n\r");
00414                continue ;
00415             }
00416             else
00417             {
00418                g_fatal=TRUE;
00419                break;
00420             }
00421          }
00422       } // for ( i_block
00423 
00424       // A fatal error on one device is enough to cleanup all the devices !
00425       //
00426       s_n_invalid_blocks[   i_dev]= n_invalid_blocks;
00427       s_n_quarantine_blocks[i_dev]= n_quarantine_blocks;
00428 
00429       if ( TRUE==g_fatal ) { break; }
00430    } // for ( i_dev
00431 
00432    return (g_fatal==TRUE) ? FAIL: PASS;
00433 } // nf_scan

Here is the call graph for this function:

Here is the caller graph for this function:

static Status_bool nf_rebuild ( void   )  [static]

Rebuild the memory and create LUT, Recovery and Free-blocks blocks.

TBD

It uses s_n_invalid_blocks (number of invalid blocks) and g_curr_block_addr (current block address of each device).

Returns:
a status: PASS if there are no error; FAIL a programmation error occured: the block is marked as bad. The function must be recall.

Definition at line 490 of file nf_unusual.c.

References _MEM_TYPE_SLOW_, Align_down, Assert, FAIL, FALSE, G_N_BLOCKS, G_OFST_BLK_STATUS, LSB, Max, MSB, N_SUBLUT, nf_block_2_page(), nf_copy_tail(), nf_fetch_free_block(), nf_init_buffer(), NF_LOW_N_FREE_THRESHOLD, NF_N_DEVICES, NF_PAGE_BUFFER_SIZE, NF_SHIFT_PAGE_BYTE, NF_SHIFT_SUBLUT_PHYS, NF_SPARE_POS, NF_SUBLUT_SIZE, nf_write_fbb(), nf_write_lut(), NFC_ACT_DEV_SELECT, Nfc_action, NFC_BLK_ID_DATA, nfc_erase_block(), nfc_mark_bad_block(), NFC_OFST_3_DATA_DST, nfc_open_page_read(), Nfc_rd_data_fetch_next, nfc_read_spare_byte(), NFC_SPARE_OFST_1_BLK_ID, NFC_SPARE_OFST_3_BYTE_3, NFC_SPARE_OFST_6_LBA, OFST, PASS, S_MNGT_DEV, S_SHIFT_LOG_BLOCK_SECTOR, SIZE_BLOCK_PAGE, SIZE_PAGE_SECTOR, trace(), trace_hex(), trace_hex16(), trace_hex32(), trace_nl(), and TRUE.

Referenced by nf_verify_resume().

00491 {
00492    Status_bool status_bool=PASS;
00493    Bool        b_duplicate;
00494    U8   i_sub_lut;
00495    U8   i_dev  =0;
00496    _MEM_TYPE_SLOW_ U16  i_block=0;
00497    _MEM_TYPE_SLOW_ U16  u16_tmp;
00498    _MEM_TYPE_SLOW_ U16  sub_lut_log_sz;
00499    _MEM_TYPE_SLOW_ U16  log_block_addr;
00500    _MEM_TYPE_SLOW_ U16  log_block_addr_min;
00501    _MEM_TYPE_SLOW_ U16  log_block_addr_max;
00502 
00503    // Refine the computation
00504    //
00505    s_n_invalid_blocks[S_MNGT_DEV] +=
00506       1                                        // Need a block for the Free-blocks block
00507    +  (G_N_BLOCKS*NF_N_DEVICES)/NF_SUBLUT_SIZE // and one for each sub-LUT
00508    ;
00509 
00510    // Take the max number of invalid blocks of each devices
00511    //
00512    u16_tmp=s_n_invalid_blocks[0] ;
00513    for ( i_dev=1 ; i_dev<NF_N_DEVICES ; i_dev++ )
00514    {
00515       u16_tmp=Max( u16_tmp, s_n_invalid_blocks[i_dev] );
00516    }
00517 
00518    // Take the max number of quarantine blocks of each devices
00519    //
00520    i_sub_lut=s_n_quarantine_blocks[0] ;
00521    for ( i_dev=1 ; i_dev<NF_N_DEVICES ; i_dev++ )
00522    {
00523       i_sub_lut=Max( i_sub_lut, s_n_quarantine_blocks[i_dev] );
00524    }
00525 
00526    sub_lut_log_sz = (U16)NF_N_DEVICES*(G_N_BLOCKS -g_nf_first_block -u16_tmp);
00527 
00528    // Finally compute the number of exportable physical blocks and free blocks
00529    //
00530    Assert( u16_tmp<(G_N_BLOCKS -g_nf_first_block) );
00531    g_n_export_blocks= (U16)( ((U32)( (U32)sub_lut_log_sz ) * 1000) / 1024);
00532    g_n_export_blocks= Align_down( g_n_export_blocks, NF_N_DEVICES);
00533 
00534    g_n_free_blocks  = (U16)sub_lut_log_sz - g_n_export_blocks;
00535    g_n_free_blocks -= (U16)NF_N_DEVICES*i_sub_lut;
00536 
00537    if( g_n_free_blocks<=NF_LOW_N_FREE_THRESHOLD )
00538    {
00539       while(1); // TBD
00540    }
00541 
00542    Assert( g_n_free_blocks>0 );
00543    Assert( g_n_free_blocks<(1L<<NF_SHIFT_PAGE_BYTE) ); // limit the free blocks in order to fit in 1 page
00544 
00545    // Compute the number of needed sub-LUT
00546    // Affect to each management block a free block address
00547    //
00548    Nfc_action(NFC_ACT_DEV_SELECT, S_MNGT_DEV);
00549    g_fbb_block_addr = nf_fetch_free_block(S_MNGT_DEV);
00550    nfc_erase_block( nf_block_2_page( g_fbb_block_addr ), TRUE );
00551    g_n_sub_lut= 0;
00552    u16_tmp    = g_n_export_blocks;
00553 //#error il faut positionner les index(LUT, FBB, RCV...)
00554    while(1)
00555    {
00556       Assert( g_n_sub_lut<N_SUBLUT );
00557       g_lut_block_addr [g_n_sub_lut]=nf_fetch_free_block(S_MNGT_DEV);
00558       g_lut_block_index[g_n_sub_lut]=0;
00559       nfc_erase_block( nf_block_2_page( g_lut_block_addr [g_n_sub_lut] ), TRUE );
00560       g_n_sub_lut++;
00561       if( u16_tmp>NF_SUBLUT_SIZE )  u16_tmp-=NF_SUBLUT_SIZE;
00562       else                          break;
00563    }
00564    g_last_sub_lut_log_sz=u16_tmp/NF_N_DEVICES;
00565 
00566    // Build the sub-LUTs
00567    //
00568    for ( i_sub_lut=0 ; i_sub_lut<g_n_sub_lut ;  )
00569    {
00570       U8  n_sublut_in_buf = g_n_sub_lut - i_sub_lut; // Count remaining sublut to build
00571 
00572       log_block_addr_max =
00573       log_block_addr_min = (U16)i_sub_lut<<(NF_SHIFT_SUBLUT_PHYS-NF_SHIFT_N_DEVICES); // first included
00574 
00575       if( n_sublut_in_buf>(NF_PAGE_BUFFER_SIZE/(2*NF_SUBLUT_SIZE)) )
00576       {
00577          n_sublut_in_buf = NF_PAGE_BUFFER_SIZE/(2*NF_SUBLUT_SIZE);
00578          log_block_addr_max += ((U16)n_sublut_in_buf)*g_sub_lut_log_sz; // last not included
00579       }
00580       else
00581       {
00582          log_block_addr_max += ((U16)n_sublut_in_buf-1)*g_sub_lut_log_sz +g_last_sub_lut_log_sz; // last not included
00583       }
00584 
00585       nf_init_buffer();
00586 
00587       // Report affected logical blocks
00588       //
00589       u16_tmp=g_n_export_blocks/NF_N_DEVICES; // Number of logical blocks used for the mass storage
00590 
00591       b_duplicate=FALSE;
00592 
00593       for ( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ )
00594       {
00595          Nfc_action(NFC_ACT_DEV_SELECT, i_dev);
00596 
00597          g_block_to_kill[i_dev]=0xFFFF;
00598 
00599          for ( i_block=g_nf_first_block ; i_block<G_N_BLOCKS ; i_block++ )
00600          {
00601             nfc_read_spare_byte( g_byte, 8, nf_block_2_page(i_block) );
00602             if(( 0xFF           !=g_byte[G_OFST_BLK_STATUS          ] ) // The block is bad
00603             || ( NFC_BLK_ID_DATA!=g_byte[NFC_SPARE_OFST_1_BLK_ID    ] ) // or is not a data block
00604             || (  ( 0xFF        ==g_byte[NFC_SPARE_OFST_6_LBA       ] ) // or is not affected
00605                && ( 0xFF        ==g_byte[NFC_SPARE_OFST_6_LBA+1     ] )
00606                )
00607             ) {
00608                continue;
00609             }
00610 
00611             MSB(log_block_addr) = g_byte[NFC_SPARE_OFST_6_LBA  ];
00612             LSB(log_block_addr) = g_byte[NFC_SPARE_OFST_6_LBA+1];
00613 
00614             if( log_block_addr>=u16_tmp )
00615             {  // The LBA seems bad: it does not fit in any LUT. This happens when unplugging the player.
00616                // Block is erased.
00617                // Anyway, stay in the loop to track similar problems.
00618                nfc_erase_block( nf_block_2_page(i_block), TRUE );
00619                status_bool=FAIL;
00620             }
00621 
00622             if(( log_block_addr>=log_block_addr_min )
00623             && ( log_block_addr< log_block_addr_max ))
00624             {
00625                U16 ofst=2*((U16)i_dev + (log_block_addr%((U16)NF_PAGE_BUFFER_SIZE/2/NF_N_DEVICES))*NF_N_DEVICES) ;
00626                if(
00627                   ( 0xFF==g_page_buffer[ ofst    ] )
00628                && ( 0xFF==g_page_buffer[ ofst +1 ] )
00629                )
00630                {  // no redundant phys blocks
00631                   Assert(      ( ofst +1 ) < NF_PAGE_BUFFER_SIZE );
00632                   g_page_buffer[ ofst    ] = MSB(i_block);
00633                   g_page_buffer[ ofst +1 ] = LSB(i_block);
00634                }
00635                else
00636                {  // A duplicated logical block is detected. This happens when unplugging the player.
00637                   // Anyway, stay in the loop to track any other redundant blocks, for that sub-LUT.
00638                   _MEM_TYPE_SLOW_ U16 tmp_addr;
00639                   MSB(tmp_addr)=g_page_buffer[ ofst    ];
00640                   LSB(tmp_addr)=g_page_buffer[ ofst +1 ];
00641                   //trace("Dupl "); trace_hex32(tmp_addr); trace("-"); trace_hex32(i_block);; trace("\n\r");
00642 
00643                   if(0xFFFF!=g_block_to_kill[i_dev])
00644                   {  // !!! There are more than 1 duplicated block on the device. This should never happen...
00645                      nfc_erase_block( nf_block_2_page(g_block_to_kill[i_dev]), TRUE );
00646                      return FAIL;
00647                   }
00648 
00649                   b_duplicate=TRUE;
00650                   g_log_block_id=log_block_addr;
00651 
00652                   nfc_open_page_read(
00653                      nf_block_2_page(i_block)
00654                   ,  NF_SPARE_POS+NFC_SPARE_OFST_3_BYTE_3
00655                   );
00656                   if( NFC_OFST_3_DATA_DST!=Nfc_rd_data_fetch_next() )
00657                   {
00658                      trace("1. Src block="); trace_hex16(i_block); trace_nl();
00659                      trace("1. Dst block="); trace_hex16(tmp_addr); trace_nl();
00660                      //nfc_print_block(i_block, 0);
00661                      //nfc_print_block(tmp_addr, 0);
00662                      //while(1);
00663                      g_block_to_kill[i_dev]=i_block;                        // source block
00664                      g_phys_page_addr[i_dev] = nf_block_2_page( tmp_addr ); // recipient block
00665                   }
00666                   else
00667                   {
00668                      trace("2. Src block="); trace_hex16(tmp_addr); trace_nl();
00669                      trace("2. Dst block="); trace_hex16(i_block); trace_nl();
00670                      //nfc_print_block(tmp_addr, 0);
00671                      //nfc_print_block(i_block, 0);
00672                      //while(1);
00673                      g_block_to_kill[i_dev]= tmp_addr ;                     // source block
00674                      g_page_buffer[ ofst    ]=MSB(i_block);
00675                      g_page_buffer[ ofst +1 ]=LSB(i_block);
00676                      g_phys_page_addr[i_dev] = nf_block_2_page( i_block );  // recipient block
00677                   }
00678                }
00679             }
00680          } // for ( i_block ../..
00681       } // for ( i_dev ../..
00682 
00683       if( b_duplicate )
00684       {
00685          U8 i_page;
00686          U8 i_sect;
00687 
00688          trace("recovery\n\r");
00689          // Test that recovery can be done
00690          for ( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ )
00691          {
00692             if( 0xFFFF==g_block_to_kill[i_dev] )
00693             {  // !Ooops... we can not recover from that case since there are duplication
00694                // only on on device
00695                for ( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ )
00696                {
00697                   if( 0xFFFF!=g_block_to_kill[i_dev] )
00698                   {
00699                      nfc_erase_block( nf_block_2_page(g_block_to_kill[i_dev]), TRUE );
00700                   }
00701                }
00702                return FAIL;
00703             }
00704          }
00705 
00706          // Initialize variable for nf_copy_tail
00707          g_curr_dev_id=0;
00708          g_last_log_sector= ((U32)g_log_block_id) << S_SHIFT_LOG_BLOCK_SECTOR;
00709 
00710          // Look for last written sector
00711          for( i_page=0 ; i_page<SIZE_BLOCK_PAGE ; i_page++ )
00712          {
00713             Nfc_action(NFC_ACT_DEV_SELECT, g_curr_dev_id);  // open the current device
00714             for( i_sect=0 ; i_sect<SIZE_PAGE_SECTOR ; i_sect++ )
00715             {
00716                nfc_open_page_read(
00717                   g_phys_page_addr[g_curr_dev_id]
00718                ,  NF_SPARE_POS + (((U16)i_sect)*16) + NFC_SPARE_OFST_6_LBA
00719                );
00720                if(( 0xFF==Nfc_rd_data_fetch_next() )
00721                && ( 0xFF==Nfc_rd_data_fetch_next() ))
00722                   goto recovery_exit;
00723                else
00724                {
00725                   g_last_log_sector++;
00726                   trace("g_last_log_sector="); trace_hex32(g_last_log_sector); trace_nl();
00727                }
00728             }
00729             g_phys_page_addr[g_curr_dev_id]++;                                                   // update the current physical page of the current device
00730             g_curr_dev_id++;                                                                     // update the current device
00731             if( g_curr_dev_id==NF_N_DEVICES ) { g_curr_dev_id=0; }
00732             trace("g_curr_dev_id="); trace_hex(g_curr_dev_id); trace_nl();
00733             trace("g_phys_page_addr="); trace_hex32(g_phys_page_addr[g_curr_dev_id]); trace_nl();
00734          }
00735 recovery_exit:
00736          trace("recovery stop on g_last_log_sector="); trace_hex32(g_last_log_sector); trace_nl();
00737          trace("g_curr_dev_id="); trace_hex(g_curr_dev_id); trace_nl();
00738          trace("g_phys_page_addr="); trace_hex32(g_phys_page_addr[g_curr_dev_id]); trace_nl();
00739          //while(1);
00740          nf_copy_tail();
00741          return FAIL;
00742       }
00743 
00744       // At least one redundant have been found: the LUT must be rebuilt since the fetch of free block
00745       // may not have seen that affected block (redundant) are in fact free.
00746       if( PASS!=status_bool ) { return FAIL; }
00747 
00748       // Affect a free physical block to the logical block
00749       //
00750       for( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ )
00751       {
00752          Nfc_action(NFC_ACT_DEV_SELECT, i_dev);
00753 
00754          for(u16_tmp=0
00755          ;   u16_tmp<(log_block_addr_max-log_block_addr_min)
00756          ;   u16_tmp++ )
00757          {
00758             U16 ofst=2*((U16)i_dev + u16_tmp*NF_N_DEVICES);
00759             if(( 0xFF==g_page_buffer[ofst  ] )
00760             && ( 0xFF==g_page_buffer[ofst+1] ))
00761             {
00762                i_block=nf_fetch_free_block(i_dev);
00763                Assert(       ofst+1<NF_PAGE_BUFFER_SIZE);
00764                g_page_buffer[ofst  ] = MSB(i_block);
00765                g_page_buffer[ofst+1] = LSB(i_block);
00766             }
00767          }
00768       } // for ( i_dev ../..
00769 
00770       // Each sub-LUT will fit in a physical page and will be of the same size
00771       // except the last one which contains less
00772       //
00773       for( ; n_sublut_in_buf!=0 ; n_sublut_in_buf--, i_sub_lut++ )
00774       {
00775          sub_lut_log_sz= ( i_sub_lut==(g_n_sub_lut-1) ) ? g_last_sub_lut_log_sz : g_sub_lut_log_sz ;
00776 
00777          // Write the sub-LUT in the page
00778          //
00779          status_bool = nf_write_lut(i_sub_lut%(NF_PAGE_BUFFER_SIZE/(2*NF_SUBLUT_SIZE)), i_sub_lut, sub_lut_log_sz);
00780          if ( PASS!=status_bool )
00781          {
00782             nfc_mark_bad_block( nf_block_2_page( g_lut_block_addr[i_sub_lut] ) );
00783             return FAIL;
00784          }
00785       }
00786    }
00787 
00788 //#error: si recovery, il faut effacer la lut en question. Il faut donc la reconstruire.
00789 //        Pour cela, il faut trouver des blocs libres.
00790 // 1ere methode: effacer aussi le free-blocks block et le reconstruire, ainsi que la sub-LUT
00791 // 2eme methode: marquer les free block pour les reconnaitre et reconstruire la sub lut
00792 
00793    // Build the free-blocks block
00794    // First, fill the internal buffer with the free blocks
00795    //
00796    for ( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ )
00797    {
00798       Nfc_action(NFC_ACT_DEV_SELECT, i_dev);
00799 
00800       for ( u16_tmp=0 ; u16_tmp<(g_n_free_blocks/NF_N_DEVICES) ; u16_tmp++ )
00801       {
00802          // This define is better than using a variable that holds the expression...
00803          #define OFST   (2*(i_dev + u16_tmp*NF_N_DEVICES))
00804          i_block=nf_fetch_free_block(i_dev);
00805          nfc_erase_block( nf_block_2_page(i_block), TRUE );
00806          Assert(       OFST   <NF_PAGE_BUFFER_SIZE);
00807          Assert(       OFST +1<NF_PAGE_BUFFER_SIZE);
00808          Assert( i_block>=g_nf_first_block );
00809          Assert( i_block< G_N_BLOCKS       );
00810          g_page_buffer[OFST   ] = MSB(i_block);
00811          g_page_buffer[OFST +1] = LSB(i_block);
00812          #undef OFST
00813       }
00814    }
00815 
00816    // Then write the buffer in the free-blocks block
00817    // Note that the list of free-blocks holds on one page only; the
00818    // algo is thus made for both 512B and 2kB pages.
00819    //
00820    g_fbb_block_index=0;
00821    status_bool = nf_write_fbb();
00822    if ( PASS!=status_bool )
00823    {
00824       nfc_mark_bad_block( nf_block_2_page( g_fbb_block_addr ) );
00825       return FAIL;
00826    }
00827 
00828 //#error Effacer les free blocks !!!!!!
00829 //#error il faut determiner s_lut_index[all] pour les sub-lut existantes
00830 //#error si il existe un bloc de recovery, alors la lut associée n'est plus valide
00831 //#error rendre parametrable la taille du buffer (actuellement 2k). Si <512 et no partial prog: fatal error
00832 
00833    //nf_init_buffer(); // Cleanup the buffer
00834    return PASS;
00835 }

Here is the call graph for this function:

Here is the caller graph for this function:

static Bool is_nf_invalid ( void   )  [static]

Test if the memory needs to be rebuilt.

Parameters:
recovery_params internal structure used to hold the last pointer position
Returns:
a status: TRUE if the memory has to be rebuilt; FALSE if the memory holds all the management blocks

Definition at line 444 of file nf_unusual.c.

References FALSE, NFC_OFST_4_FBB_DRIVER_RELEASE, and TRUE.

Referenced by nf_verify_resume().

00445 {
00446    if( // If we do not find everything
00447       ( FALSE==g_is_found_lut )
00448    || ( FALSE==g_is_found_fbb )
00449    ) {
00450       g_fatal=TRUE;
00451    }
00452 
00453    // Test LUT coherency
00454    //
00455    if(( TRUE       ==g_is_found_lut   )
00456    && ( g_n_sub_lut!=g_n_real_sub_lut ))
00457    {
00458       g_fatal=TRUE;
00459    }
00460 
00461 //#error se proteger si le nombre de devices changent alors que lut, recovery et free blocs sont déjà créés sur le bloc MNGT.
00462    if ( (U16)-1==g_n_export_blocks     ) { g_fatal=TRUE; }
00463    if (       0==g_n_export_blocks     ) { g_fatal=TRUE; }
00464    if ( (U16)-1==g_last_sub_lut_log_sz ) { g_fatal=TRUE; }
00465 
00466    // Test Nand Flash driver release.
00467    //
00468    if ( s_nfd_rev!=NFC_OFST_4_FBB_DRIVER_RELEASE )
00469    {
00470       g_fatal=TRUE;
00471    }
00472 
00473    return g_fatal;
00474 }

Here is the caller graph for this function:

static U16 nf_fetch_free_block ( U8  i_dev  )  [static]

Returns the first free block seen, scanning downstream.

It uses g_curr_block_addr (current block address of each device).

Parameters:
i_dev device number on which we look for a free block
Returns:
the physical block number

Definition at line 847 of file nf_unusual.c.

References Assert, FALSE, G_OFST_BLK_STATUS, nf_block_2_page(), NFC_BLK_ID_DATA, NFC_BLK_ID_FBB, NFC_BLK_ID_SUBLUT, nfc_erase_block(), nfc_read_spare_byte(), NFC_SPARE_OFST_1_BLK_ID, NFC_SPARE_OFST_6_LBA, and TRUE.

Referenced by nf_rebuild().

00848 {
00849 
00850    U16 block_addr= g_curr_block_addr[i_dev];
00851 
00852    while ( block_addr>=g_nf_first_block )
00853    {
00854       nfc_read_spare_byte( g_byte, 8, nf_block_2_page( block_addr ) );
00855       if(( 0xFF           ==g_byte[G_OFST_BLK_STATUS          ] ) // the block is valid
00856       && ( NFC_BLK_ID_DATA==g_byte[NFC_SPARE_OFST_1_BLK_ID    ] ) // the block is a data block
00857       && ( 0xFF           ==g_byte[NFC_SPARE_OFST_6_LBA       ] ) // and is not affected
00858       && ( 0xFF           ==g_byte[NFC_SPARE_OFST_6_LBA+1     ] ))
00859       {
00860          // Since we rebuild the flash, we should not see any of these blocks
00861          //
00862          Assert( NFC_BLK_ID_SUBLUT!=g_byte[NFC_SPARE_OFST_1_BLK_ID] );
00863          Assert( NFC_BLK_ID_FBB   !=g_byte[NFC_SPARE_OFST_1_BLK_ID] );
00864 
00865          // Find a free and valid block addr. Store the current position
00866          //
00867          g_curr_block_addr[i_dev] = block_addr-1;
00868          return block_addr;
00869       }
00870       block_addr-=1 ;
00871    }
00872    // This situation is dramatic: it should never happen !
00873    // Force Rebuild on next startup
00874    nfc_erase_block( nf_block_2_page( g_fbb_block_addr ), TRUE );
00875    while(1);
00876    Assert( FALSE ) ; // Not enough free blocks: fatal error!
00877 }

Here is the call graph for this function:

Here is the caller graph for this function:

static U8 nf_refine_index ( U16  block_addr,
U8  inc,
U8  pattern 
) [static]

Refines the position of the 'block' index according to a particular pattern.

This allow to find exactely where are stored the last sub-LUT, Free_blocks or Recovery entry. The index is roughly initialized at the beginning of the block that holds the 'pattern' at the location 1 of the spare zone. The function parses the block until the pattern is no more found.

Parameters:
block_addr physical block address
inc increment
pattern pattern which is scanned
Returns:
the offset (in page) of the last valid entry in the block

Definition at line 894 of file nf_unusual.c.

References _MEM_TYPE_SLOW_, Assert, G_SHIFT_BLOCK_PAGE, nf_block_2_page(), NF_SPARE_POS, nfc_open_page_read(), Nfc_rd_data, NFC_SPARE_OFST_1_BLK_ID, and SIZE_BLOCK_PAGE.

Referenced by nf_scan().

00898 {
00899    _MEM_TYPE_SLOW_ U8 u8_tmp;
00900    _MEM_TYPE_SLOW_ U8 val=0;
00901    do
00902    {
00903       val+= inc; // Assume that the pattern has already be seen previously
00904       if( val>=SIZE_BLOCK_PAGE )
00905          { break; }
00906       nfc_open_page_read(
00907          nf_block_2_page(block_addr) + val
00908       ,  NF_SPARE_POS+NFC_SPARE_OFST_1_BLK_ID
00909       );
00910       u8_tmp = Nfc_rd_data();
00911    } while( pattern==u8_tmp );
00912    val-= inc; // come back to last valid entry
00913    Assert( val<(1<<G_SHIFT_BLOCK_PAGE) ); // The offset shall not be outside the block
00914    return val;
00915 }

Here is the call graph for this function:

Here is the caller graph for this function:

void nf_init ( void   ) 

Initializes the nand flash memory driver.

The device identification is performed to initialize the driver accordingly

Parameters:
none 
Returns:
none

Definition at line 151 of file nf_unusual.c.

References FALSE, g_n_row_cycles, g_ofst_blk_status, G_SHIFT_BLOCK_PAGE, g_shift_block_page, G_SHIFT_PAGE_BYTE, g_shift_page_byte, Is_nf_2k, Is_nf_512, NF_SHIFT_BLOCK_PAGE, NF_SHIFT_PAGE_BYTE, NF_SHIFT_SECTOR_BYTE, s_shift_log_block_sector, s_shift_log_page_sector, S_SHIFT_SECTOR_BYTE, and s_shift_sector_byte.

00152 {
00153    g_nf_init=FALSE;
00154 //   s_pending_write=FALSE;
00155 
00156 #if (NF_GENERIC_DRIVER==TRUE)
00157 #error Check this init...
00158    g_n_zones             = NF_N_ZONES;
00159    g_n_blocks            = NF_N_BLOCKS;
00160    g_shift_block_page    = NF_SHIFT_BLOCK_PAGE;
00161    g_shift_page_byte     = NF_SHIFT_PAGE_BYTE;
00162    s_shift_sector_byte   = NF_SHIFT_SECTOR_BYTE;
00163    g_n_row_cycles        = NF_N_ROW_CYCLES;
00164 
00165    if ( Is_nf_2k() ) // 2KB pages
00166    {
00167       g_ofst_blk_status     = 0;
00168    }
00169    if ( Is_nf_512() ) // 512B pages
00170    {
00171       g_ofst_blk_status     = 5;
00172    }
00173 
00174    s_shift_log_page_sector  = G_SHIFT_PAGE_BYTE - S_SHIFT_SECTOR_BYTE + NF_SHIFT_N_DEVICES;
00175    s_shift_log_block_sector = s_shift_log_page_sector + G_SHIFT_BLOCK_PAGE;
00176 #endif
00177 
00178    g_cache_lut.ctrl.valid = FALSE; g_cache_lut.ctrl.dirty = FALSE;
00179    g_cache_fbb.ctrl.valid = FALSE; g_cache_fbb.ctrl.dirty = FALSE;
00180    g_last_log_sector= 0xFFFFFFFF;
00181 }

Status_bool nf_verify_resume ( void   ) 

Ensure that the memory is in a good state before starting to use it.

The function will scan the memory, test if the memory is valid, clean it if it has to and rebuild all the management blocks. This function shall be called prior to any use of the memory after a power-up.

Parameters:
none 
Returns:
a status: PASS if the command has been succesfully executed; FAIL else

Definition at line 196 of file nf_unusual.c.

References FAIL, FALSE, is_nf_invalid(), Nf_check_fbb, Nf_check_lut, nf_cleanup_memory(), nf_rebuild(), nf_scan(), PASS, TRUE, and ut_nfc_erase_all().

00197 {
00198    U8 u8_nb_loop;
00199    Bool status_bool;
00200 
00201 
00202 #if (ERASING_ALL==ENABLE)
00203    ut_nfc_erase_all();
00204 #endif
00205    
00206    status_bool = nf_scan();
00207 
00208    if(( PASS!=status_bool )
00209    || ( is_nf_invalid()   )  // The NF is not cleanly built
00210    ) {
00211       // The NF seems not cleanly built, or not built at all.
00212       //
00213       u8_nb_loop = 0;
00214       while( 1 )
00215       {
00216          u8_nb_loop++;
00217          if( u8_nb_loop > 2 )
00218          {
00219             status_bool=FAIL;
00220             break;  // Error NF access or control
00221          }
00222          nf_cleanup_memory();
00223          if( PASS != nf_scan() )
00224             continue;
00225          if( PASS != nf_rebuild() )
00226             continue;
00227          status_bool = PASS;
00228          break;
00229       }
00230    }
00231    if (status_bool==PASS)
00232    {
00233       g_nf_init = TRUE;
00234       Nf_check_lut();
00235       Nf_check_fbb( FALSE );
00236    }
00237 
00238    return status_bool;
00239 }

Here is the call graph for this function:

void nf_cleanup_memory ( void   ) 

Cleanup the memory by erasing all the management blocks.

The sub-LUT blocks, the recovery block and the free-blocks block will be erased on any devices.

Parameters:
none 

Definition at line 250 of file nf_unusual.c.

References FAIL, G_N_BLOCKS, nf_block_2_page(), NF_N_DEVICES, NF_SPARE_POS, NFC_ACT_DEV_SELECT, Nfc_action, NFC_BLK_ID_FBB, NFC_BLK_ID_SUBLUT, nfc_check_status(), nfc_erase_block(), nfc_mark_bad_block(), nfc_open_page_read(), Nfc_rd_data, Nfc_rd_data_fetch_next, and TRUE.

00251 {
00252    U8   i_dev  =0;
00253    U16  i_block=0;
00254    U8   block_valid;
00255    U8   block_id;
00256 
00257    // Scan all the devices and looks for:
00258    // - the sub-LUT
00259    // - the recovery block
00260    // - the free-blocks block
00261    //
00262    for( i_dev=0 ; i_dev<NF_N_DEVICES ; i_dev++ )
00263    {
00264       // Select the devices
00265       //
00266       Nfc_action(NFC_ACT_DEV_SELECT, i_dev);
00267 
00268       for( i_block=g_nf_first_block ; i_block<G_N_BLOCKS ; i_block++ )
00269       {
00270 
00271          nfc_open_page_read( nf_block_2_page(i_block), NF_SPARE_POS);
00272          block_valid = Nfc_rd_data_fetch_next();
00273          block_id    = Nfc_rd_data()           ;
00274 
00275          if ( block_valid!=0xFF )
00276          {
00277             continue; // The block is bad
00278          }
00279 
00280          if(( NFC_BLK_ID_SUBLUT==block_id )
00281          || ( NFC_BLK_ID_FBB   ==block_id ))
00282          {
00283             nfc_erase_block( nf_block_2_page(i_block), TRUE ) ;
00284             if ( FAIL==nfc_check_status() )
00285             {
00286                nfc_mark_bad_block( nf_block_2_page(i_block) );
00287             }
00288          }
00289       } // for( i_block...
00290    } // for( i_dev...
00291 } // nf_cleanup_memory

Here is the call graph for this function:


Variable Documentation

_MEM_TYPE_SLOW_ U8 g_n_zones

_MEM_TYPE_SLOW_ U16 g_n_blocks

_MEM_TYPE_SLOW_ U8 g_page_buffer[((2048)+(2048)/32)]

Definition at line 133 of file nf_mngt.c.

_MEM_TYPE_BIT_ bit g_nf_init

Definition at line 141 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_last_sub_lut_log_sz

Definition at line 147 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_sub_lut_log_sz

Definition at line 146 of file nf_mngt.c.

Bool g_is_found_lut

Definition at line 82 of file nf_unusual.c.

Bool g_is_found_fbb

Definition at line 83 of file nf_unusual.c.

Bool g_fatal

Definition at line 107 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U8 g_n_real_sub_lut

Definition at line 85 of file nf_unusual.c.

_MEM_TYPE_SLOW_ U16 g_curr_block_addr[NF_N_DEVICES]

Definition at line 86 of file nf_unusual.c.

_MEM_TYPE_SLOW_ U8 g_byte[16]

Definition at line 87 of file nf_unusual.c.

_MEM_TYPE_SLOW_ U8 g_n_sub_lut

Definition at line 145 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_lut_block_addr[(NF_N_DEVICES *(8 *1024)/(512/2))]

Definition at line 150 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U8 g_lut_block_index[(NF_N_DEVICES *(8 *1024)/(512/2))]

Definition at line 151 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U8 s_nfd_rev [static]

Definition at line 91 of file nf_unusual.c.

_MEM_TYPE_SLOW_ U16 g_nf_first_block

Definition at line 117 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U8 s_n_quarantine_blocks[NF_N_DEVICES] [static]

Definition at line 93 of file nf_unusual.c.

_MEM_TYPE_SLOW_ U16 s_n_invalid_blocks[NF_N_DEVICES] [static]

Definition at line 94 of file nf_unusual.c.

_MEM_TYPE_SLOW_ U16 g_n_export_blocks

Definition at line 143 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_n_free_blocks

Definition at line 144 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_fbb_block_addr

Definition at line 148 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U8 g_fbb_block_index

Definition at line 149 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U32 g_last_log_sector

Definition at line 158 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U32 g_copy_src

Definition at line 116 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_block_to_kill[NF_N_DEVICES]

Definition at line 161 of file nf_mngt.c.

_MEM_TYPE_FAST_ U32 g_phys_page_addr[NF_N_DEVICES]

Definition at line 162 of file nf_mngt.c.

_MEM_TYPE_FAST_ U8 g_curr_dev_id

Definition at line 155 of file nf_mngt.c.

_MEM_TYPE_MEDFAST_ U16 g_log_block_id

Definition at line 142 of file nf_mngt.c.

_MEM_TYPE_SLOW_ Cache_lut g_cache_lut

Definition at line 129 of file nf_mngt.c.

_MEM_TYPE_SLOW_ Cache_fbb g_cache_fbb

Definition at line 130 of file nf_mngt.c.


Generated on Wed Sep 23 09:17:14 2009 for ATMEL by  doxygen 1.5.3