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 49 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 917 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().

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

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 127 of file nf_unusual.c.

References NF_FULL_PAGE_BUFFER_SIZE.

Referenced by nf_rebuild().

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

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 300 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().

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

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

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 441 of file nf_unusual.c.

References FALSE, NFC_OFST_4_FBB_DRIVER_RELEASE, and TRUE.

Referenced by nf_verify_resume().

00442 {
00443    if( // If we do not find everything
00444       ( FALSE==g_is_found_lut )
00445    || ( FALSE==g_is_found_fbb )
00446    ) {
00447       g_fatal=TRUE;
00448    }
00449 
00450    // Test LUT coherency
00451    //
00452    if(( TRUE       ==g_is_found_lut   )
00453    && ( g_n_sub_lut!=g_n_real_sub_lut ))
00454    {
00455       g_fatal=TRUE;
00456    }
00457 
00458 //#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.
00459    if ( (U16)-1==g_n_export_blocks     ) { g_fatal=TRUE; }
00460    if (       0==g_n_export_blocks     ) { g_fatal=TRUE; }
00461    if ( (U16)-1==g_last_sub_lut_log_sz ) { g_fatal=TRUE; }
00462 
00463    // Test Nand Flash driver release.
00464    //
00465    if ( s_nfd_rev!=NFC_OFST_4_FBB_DRIVER_RELEASE )
00466    {
00467       g_fatal=TRUE;
00468    }
00469 
00470    return g_fatal;
00471 }

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 844 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().

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

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 891 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().

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

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 148 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.

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

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 193 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().

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

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 247 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.

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

_MEM_TYPE_BIT_ bit g_nf_init

Definition at line 138 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_last_sub_lut_log_sz

Definition at line 144 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_sub_lut_log_sz

Definition at line 143 of file nf_mngt.c.

Bool g_is_found_lut

Definition at line 79 of file nf_unusual.c.

Bool g_is_found_fbb

Definition at line 80 of file nf_unusual.c.

Bool g_fatal

Definition at line 104 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U8 g_n_real_sub_lut

Definition at line 82 of file nf_unusual.c.

_MEM_TYPE_SLOW_ U16 g_curr_block_addr[NF_N_DEVICES]

Definition at line 83 of file nf_unusual.c.

_MEM_TYPE_SLOW_ U8 g_byte[16]

Definition at line 84 of file nf_unusual.c.

_MEM_TYPE_SLOW_ U8 g_n_sub_lut

Definition at line 142 of file nf_mngt.c.

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

Definition at line 147 of file nf_mngt.c.

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

Definition at line 148 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U8 s_nfd_rev [static]

Definition at line 88 of file nf_unusual.c.

_MEM_TYPE_SLOW_ U16 g_nf_first_block

Definition at line 114 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U8 s_n_quarantine_blocks[NF_N_DEVICES] [static]

Definition at line 90 of file nf_unusual.c.

_MEM_TYPE_SLOW_ U16 s_n_invalid_blocks[NF_N_DEVICES] [static]

Definition at line 91 of file nf_unusual.c.

_MEM_TYPE_SLOW_ U16 g_n_export_blocks

Definition at line 140 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_n_free_blocks

Definition at line 141 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_fbb_block_addr

Definition at line 145 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U8 g_fbb_block_index

Definition at line 146 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U32 g_last_log_sector

Definition at line 155 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U32 g_copy_src

Definition at line 113 of file nf_mngt.c.

_MEM_TYPE_SLOW_ U16 g_block_to_kill[NF_N_DEVICES]

Definition at line 158 of file nf_mngt.c.

_MEM_TYPE_FAST_ U32 g_phys_page_addr[NF_N_DEVICES]

Definition at line 159 of file nf_mngt.c.

_MEM_TYPE_FAST_ U8 g_curr_dev_id

Definition at line 152 of file nf_mngt.c.

_MEM_TYPE_MEDFAST_ U16 g_log_block_id

Definition at line 139 of file nf_mngt.c.

_MEM_TYPE_SLOW_ Cache_lut g_cache_lut

Definition at line 126 of file nf_mngt.c.

_MEM_TYPE_SLOW_ Cache_fbb g_cache_fbb

Definition at line 127 of file nf_mngt.c.


Generated on Fri Oct 31 14:31:37 2008 for ATMEL by  doxygen 1.5.3