www.pudn.com > File_SD_OS.rar > ZLG_FFS.c


/****************************************Copyright (c)************************************************** 
**                               Guangzou ZLG-MCU Development Co.,LTD. 
**                                      graduate school 
**                                 http://www.zlgmcu.com 
** 
**--------------File Info------------------------------------------------------------------------------- 
** File name:			ZLG_FFS.c 
** Last modified Date:  2004-11-08 
** Last Version:		1.0 
** Descriptions:		k9f2808 driver 
** 
**------------------------------------------------------------------------------------------------------ 
** Created by:			Chenmingji 
** Created date:		2004-11-08 
** Version:				1.0 
** Descriptions:		The original version 
** 
**------------------------------------------------------------------------------------------------------ 
** Modified by: 
** Modified date: 
** Version: 
** Descriptions: 
** 
********************************************************************************************************/ 
#define IN_ZLG_FFS 
 
#include "config.h" 
#include  
 
#define  BAD_BLOCK       0 
#define  FREE_BLOCK      1 
#define  USR_BLOCK       2 
 
#define  USR_BLOCK_ADD   0x20 
 
/********************************************************************************************************* 
        设置坏块 
*********************************************************************************************************/ 
        static uint8 FFSSetBadBlock(FFSDisk *Index, uint16 BlockIndex) 
{ 
    uint8 *bufa; 
    const FlashDriver *Drive; 
    unsigned int BytsPerSec; 
     
    if (Index != NULL) 
    { 
        Drive = Index->Drive; 
        bufa = (uint8 *)(Drive->BufA); 
        BytsPerSec = Drive->BytsPerSec; 
        if (Drive->SectorRead(Drive->Index, bufa, BlockIndex / (BytsPerSec * 8)) == TRUE) 
        { 
            bufa[BlockIndex % BytsPerSec] &= ~(1 << (BlockIndex % 8)); 
            Index->BlockState[BlockIndex] = BAD_BLOCK; 
            Index->BlockEaseSum[BlockIndex] = ~0; 
            return Drive->SectorWrite(Drive->Index, bufa, BlockIndex / (BytsPerSec * 8)); 
        } 
    } 
    return FALSE; 
} 
 
/* 扇区扩展数据结构:                                   */ 
/* buf[0..3]:  块索引,0x00000000和0xffffffff为空闲    */ 
/* buf[4..4]:  有效标志:'Z'                            */ 
/* buf[5..5]:  使用标志:0:已经使用                     */ 
/* buf[5..7]:  保留原始状态                            */ 
/* buf[8..11]: 擦除次数,低字节在前                    */ 
/* buf[12..15]:保留                                    */ 
 
/********************************************************************************************************* 
        擦除块 
*********************************************************************************************************/ 
        static uint8 FFSBlockErase(FFSDisk *Index, uint16 BlockIndex) 
{ 
    const FlashDriver *Drive; 
    uint32 temp1, temp2; 
    uint8 *BufA; 
     
    Drive = Index->Drive; 
    BufA = Drive->BufA; 
    if (Drive->ExSectorRead(Drive->Index, BufA, BlockIndex * (Drive->SecsPreBlock)) == FALSE) 
    { 
        goto err; 
    } 
    BufA[0] = 0xff; 
    BufA[1] = 0xff; 
    BufA[2] = 0xff; 
    BufA[3] = 0xff; 
 
    temp1 = (BufA[11] << 8) | BufA[10]; 
    temp1 = temp1 << 16; 
    temp1 |= ((BufA[9] << 8) | BufA[8]); 
 
    if (BufA[4] == 'Z') 
    { 
        temp1++; 
    } 
    else 
    { 
        temp1 = 0; 
    } 
    Drive->BufA[4] = 'Z'; 
    Drive->BufA[5] = 0xff; 
     
    BufA[8] = temp1; 
    BufA[9] = temp1 >> 8; 
    BufA[10] = temp1 >> 16; 
    BufA[11] = temp1 >> 24; 
 
    Index->BlockEaseSum[BlockIndex] = temp1; 
    Index->BlockState[BlockIndex] = FREE_BLOCK; 
    if (Drive->BlockErase(Drive->Index, BlockIndex * Drive->SecsPreBlock) == FALSE) 
    { 
        goto err; 
    } 
     
    temp1 = Drive->SecsPreBlock; 
    temp2 = BlockIndex * temp1; 
 
    do 
    { 
        if (Drive->ExSectorWrite(Drive->Index, BufA, temp2) == FALSE) 
        { 
            goto err; 
        } 
        if (Drive->ExSectorCheck(Drive->Index, BufA, temp2) == FALSE) 
        { 
            goto err; 
        } 
 
    /* 校验 */     
        if ((Drive->ExSectorRead(Drive->Index, BufA, temp2++)) == FALSE) 
        { 
            goto err; 
        } 
        if (BufA[0] != 0xff) 
        { 
            goto err; 
        } 
        if (BufA[1] != 0xff) 
        { 
            goto err; 
        } 
        if (BufA[2] != 0xff) 
        { 
            goto err; 
        } 
        if (BufA[3] != 0xff) 
        { 
            goto err; 
        } 
 
        if (BufA[4] != 'Z') 
        { 
            goto err; 
        } 
 
        if (BufA[5] != 0xff) 
        { 
            goto err; 
        } 
    } while (--temp1 != 0); 
 
    return TRUE; 
err: 
    return FFSSetBadBlock(Index, BlockIndex); 
} 
 
 
/********************************************************************************************************* 
 
*********************************************************************************************************/ 
 
const static uint8 logo[16] = {'Z', 'L', 'G', '\\', 'F', 'F', 'S', 0, 
                        'V',  0,   1,   0,   1,   0,   0,   0 }; 
const static uint8 logo1[16] = {0xb3, 0xc2, 0xc3, 0xf7, 0xbc, 0xc6, 0, 0, 
                         '2', '0', '0', '4', '1', '1',  0,   0 }; 
 
        static uint8 NFFormatA(FFSDisk *Index) 
{ 
    uint32 i, temp; 
    unsigned int j, k; 
    const FlashDriver *Drive; 
    uint8 *bufa; 
 
    Drive = Index->Drive; 
    temp = Drive->BlockPreDisk; 
    /* 设置坏块表 */ 
    Drive->BlockErase(Drive->Index, 0); 
    bufa = Drive->BufA; 
 
    j = Drive->BytsPerSec; 
    do 
    { 
        *bufa++ = 0xff; 
    } while ( --j != 0); 
     
    bufa = Drive->BufA; 
    for (i = 1; i < Drive->BlockPreDisk; i++) 
    { 
         
        if ((Drive->BlockCheck(Drive->Index, i)) != TRUE) 
        { 
            bufa[(i / 8) % (Drive->BytsPerSec)] &= ~(1 << (i % 8)); 
        } 
        if ((i % (Drive->BytsPerSec * 8)) == 0) 
        { 
            bufa = Drive->BufA; 
            Drive->SectorWrite(Drive->Index, bufa, i / (Drive->BytsPerSec * 8)); 
 
            j = Drive->BytsPerSec; 
            do 
            { 
                *bufa++ = 0xff; 
            } while (--j != 0); 
            bufa = Drive->BufA; 
        } 
    } 
    /* 设置logo */ 
    Drive->ExSectorWrite(Drive->Index, (uint8 *)logo, 0); 
    Drive->ExSectorWrite(Drive->Index, (uint8 *)logo, Drive->SecsPreBlock - 1); 
 
    /* 初始化扇区 */ 
     
    k = 0; 
    bufa = Drive->BufA; 
    Drive->SectorRead(Drive->Index, bufa, 0); 
    for (i = 1; i < Drive->BlockPreDisk; i++) 
    { 
        if ((i % (Drive->BytsPerSec * 8)) == 0) 
        { 
            k++; 
            Drive->SectorRead(Drive->Index, bufa, k); 
        } 
        if ((bufa[i % (Drive->BytsPerSec)] & (1 << (i % 8))) != 0) 
        { 
            FFSBlockErase(Index, i); 
            Drive->SectorRead(Drive->Index, bufa, k); 
        } 
    } 
 
    /* 初始化第0扇区 */ 
     
    k = 0; 
    bufa = Drive->BufA; 
    Drive->SectorRead(Drive->Index, bufa, 0); 
    for (i = 1; i < Drive->BlockPreDisk; i++) 
    { 
        if ((i % (Drive->BytsPerSec * 8)) == 0) 
        { 
            k++; 
            Drive->SectorRead(Drive->Index, bufa, k); 
        } 
        if ((bufa[(i / 8) % (Drive->BytsPerSec)] & (1 << (i % 8))) != 0) 
        { 
            temp = (Drive->SecsPreBlock) * i; 
            Drive->ExSectorRead(Drive->Index, bufa, temp); 
            bufa[0] = 0x01; 
            bufa[1] = 0x00; 
            bufa[2] = 0x00; 
            bufa[3] = 0x00; 
            if (Drive->ExSectorWrite(Drive->Index, bufa, temp) ==FALSE) 
            { 
                FFSSetBadBlock(Drive->Index, temp / Drive->SecsPreBlock); 
                break; 
            } 
            if (Drive->ExSectorCheck(Drive->Index, bufa, temp) ==FALSE) 
            { 
                FFSSetBadBlock(Drive->Index, temp / Drive->SecsPreBlock); 
                break; 
            } 
            break; 
        } 
    } 
    return TRUE; 
} 
      
     static uint8 NFFormatB(FFSDisk *Index)         
{ 
    uint32 i, BlockPreDisk; 
    unsigned int BytsPerSec; 
    unsigned int k; 
    const FlashDriver *Drive; 
    uint8 *bufa; 
 
    if (Index == NULL) 
    { 
        return FALSE; 
    } 
     
    Drive = Index->Drive; 
    bufa = Drive->BufA; 
    BytsPerSec = Drive->BytsPerSec; 
    BlockPreDisk = Drive->BlockPreDisk; 
 
    /* 初始化扇区 */ 
    k = 0; 
    Drive->SectorRead(Drive->Index, bufa, 0); 
    for (i = 1; i < BlockPreDisk; i++) 
    { 
        if ((i % (BytsPerSec * 8)) == 0) 
        { 
            k++; 
            Drive->SectorRead(Drive->Index, bufa, k); 
        } 
        if ((bufa[(i / 8) % BytsPerSec] & (1 << (i % 8))) != 0) 
        { 
            FFSBlockErase(Index, i); 
            Drive->SectorRead(Drive->Index, bufa, k); 
        } 
    } 
    /* 初始化第0扇区 */ 
     
    k = 0; 
    bufa = Drive->BufA; 
    Drive->SectorRead(Drive->Index, bufa, 0); 
    for (i = 1; i < Drive->BlockPreDisk; i++) 
    { 
        if ((i % (Drive->BytsPerSec * 8)) == 0) 
        { 
            k++; 
            Drive->SectorRead(Drive->Index, bufa, k); 
        } 
        if ((bufa[i % (Drive->BytsPerSec)] & (1 << (i % 8))) != 0) 
        { 
            i = (Drive->SecsPreBlock) * i; 
            Drive->ExSectorRead(Drive->Index, bufa, i); 
            bufa[0] = 0x01; 
            bufa[1] = 0x00; 
            bufa[2] = 0x00; 
            bufa[3] = 0x00; 
            if (Drive->ExSectorWrite(Drive->Index, bufa, i) == FALSE) 
            { 
                FFSSetBadBlock(Drive->Index, i / Drive->SecsPreBlock); 
                break; 
            } 
            if (Drive->ExSectorCheck(Drive->Index, bufa, i) == FALSE) 
            { 
                FFSSetBadBlock(Drive->Index, i / Drive->SecsPreBlock ); 
                break; 
            } 
            break; 
        } 
    }     
    return TRUE; 
} 
 
        static uint8 NFFormat(FFSDisk *Index) 
{ 
    uint8 *buf; 
     
    buf = Index->Drive->BufA; 
    if (Index != NULL) 
    if (Index->Drive->ExSectorRead(Index->Drive->Index, buf, 0) == TRUE) 
    { 
        if (buf[0] != 'Z'  || 
            buf[1] != 'L'  || 
            buf[2] != 'G'  || 
            buf[3] != '\\' || 
            buf[4] != 'F'  || 
            buf[5] != 'F'  || 
            buf[6] != 'S'  || 
            buf[7] != 0) 
        { 
            return NFFormatA(Index); 
        } 
        else 
        { 
            return NFFormatB(Index); 
        } 
    } 
    return FALSE; 
} 
 
/********************************************************************************************************* 
        初始化 
*********************************************************************************************************/ 
        static uint8 FFSDiskInit(FFSDisk *Index) 
{ 
    uint32 i, temp, temp1, temp2, temp3; 
    unsigned int j, k, m, n, BytsPerSec; 
    const FlashDriver *Drive; 
    uint8 *bufa; 
    uint32 *VBlockInfo; 
     
 
    /* 检查参数有效性 */ 
    if (Index == NULL) 
    { 
        return DISK_INIT_NOT_OK; 
    } 
    Drive = Index->Drive; 
 
    if (Drive == NULL || 
        Drive->SectorRead == NULL    || 
        Drive->ExSectorRead == NULL  || 
        Drive->SectorWrite == NULL   || 
        Drive->ExSectorWrite == NULL || 
        Drive->BlockErase == NULL    || 
        //Drive->SecCopy == NULL       || 
        Drive->SectorCheck == NULL   || 
        Drive->ExSectorCheck == NULL 
        ) 
    { 
        return DISK_INIT_NOT_OK; 
    } 
 
    bufa = Drive->BufA; 
 
    if (Drive->ExSectorRead(Drive->Index, bufa, 0) == FALSE) 
    { 
        return DISK_INIT_NOT_OK; 
    } 
 
    /* 没有低级格式化就低级格式化  */ 
    if (bufa[0] != 'Z'  || 
        bufa[1] != 'L'  || 
        bufa[2] != 'G'  || 
        bufa[3] != '\\' || 
        bufa[4] != 'F'  || 
        bufa[5] != 'F'  || 
        bufa[6] != 'S'  || 
        bufa[7] != 0) 
    { 
        NFFormatA(Index); 
    } 
 
    /* 获取必须的内存空间 */ 
    i = Drive->BlockPreDisk; 
    bufa = malloc(i * sizeof(uint8)); 
    if (bufa == NULL) 
    { 
        return DISK_INIT_NOT_OK; 
    } 
    Index->BlockState = bufa; 
 
    /* 初始化内存空间 */ 
    do 
    { 
        *bufa++ = BAD_BLOCK; 
    } while (--i != 0); 
 
    /* 获取必须的内存空间 */ 
    i = Drive->BlockPreDisk; 
    VBlockInfo = malloc(i * sizeof(uint32)); 
    if (VBlockInfo == NULL) 
    { 
        free(Index->BlockState); 
        Index->BlockState = NULL; 
        return DISK_INIT_NOT_OK; 
    } 
    Index->BlockEaseSum = VBlockInfo; 
 
    /* 初始化内存空间 */ 
    do 
    { 
        *VBlockInfo++ = ~1; 
    } while (--i != 0); 
 
    /* 获得有效块数  */ 
    bufa = Drive->BufA; 
    j = Drive->BlockPreDisk; 
    i = 0; 
    k = 0; 
    temp = 0; 
    BytsPerSec = Drive->BytsPerSec; 
    Drive->SectorRead(Drive->Index, bufa, 0); 
    
    do 
    { 
        if ((bufa[(i / 8) % BytsPerSec] & (1 << (i % 8))) != 0) 
        { 
            temp++; 
        } 
        i++; 
        if ((i % (BytsPerSec * 8)) == 0) 
        { 
            k++; 
            Drive->ExSectorRead(Index, bufa, k); 
        } 
    } while (--j != 0) ; 
 
    if (temp <= 1) 
    { 
        return DISK_INIT_NOT_OK; 
    } 
 
    /* 获取必须的内存空间 */ 
    temp--;                                                  /* 1个保留块 */ 
    Index->BlockSum = temp; 
    VBlockInfo = malloc(temp * sizeof(uint32)); 
    if (VBlockInfo == NULL) 
    { 
        free(Index->BlockState); 
        Index->BlockState = NULL; 
        free(Index->BlockEaseSum); 
        Index->BlockEaseSum = NULL; 
        return DISK_INIT_NOT_OK; 
    } 
    Index->VBlockInfo = VBlockInfo; 
 
    /* 初始化内存空间 */ 
    do 
    { 
        *VBlockInfo++ = 0; 
    } while (--temp != 0); 
     
    /* 获取虚拟块与物理块的映射表、物理块擦除计数表和物理块状态表 */ 
    VBlockInfo = (Index->VBlockInfo) - 1; 
    bufa = Drive->BufA; 
    k = 0; 
    j = Index->BlockSum; 
     
    Drive->SectorRead(Drive->Index, bufa, 0); 
    for (i = 1; i < j; i++) 
    { 
        if ((i % (BytsPerSec * 8)) == 0) 
        { 
            k++; 
            Drive->ExSectorRead(Drive->Index, bufa, k); 
        } 
 
        if ((bufa[(i / 8) % BytsPerSec] & (1 << (i % 8))) != 0) 
        { 
            Index->BlockState[i] = FREE_BLOCK; 
 
            m = Drive->SecsPreBlock; 
            n = m * i; 
            temp2 = 0; 
            temp1 = 0; 
            do 
            { 
                Drive->ExSectorRead(Drive->Index, bufa, n++); 
                temp = bufa[2] | bufa[3] << 8; 
                temp = temp << 16; 
                temp |= (bufa[0] | bufa[1] << 8); 
 
                temp3 = bufa[10] | bufa[11] << 8; 
                temp3 = temp3 << 16; 
                temp3 |= (bufa[8] | bufa[9] << 8); 
                if (temp3 != ~0) 
                { 
                    temp1 = temp3; 
                } 
             
                if (temp < j && temp != 0) 
                { 
                    VBlockInfo[temp] = i; 
                    Index->BlockState[i] = USR_BLOCK; 
                    temp2 = USR_BLOCK_ADD; 
                    break; 
                } 
            } while (--m != 0); 
            Index->BlockEaseSum[i] = temp1 + temp2; 
            Drive->SectorRead(Drive->Index, bufa, k); 
        } 
    } 
    return DISK_INIT_OK; 
} 
 
/********************************************************************************************************* 
        关闭 
*********************************************************************************************************/ 
        static uint8 FFSDiskClose(FFSDisk *Index) 
{ 
    if (Index != NULL) 
    { 
        if (Index->BlockState != NULL) 
        { 
            free(Index->BlockState); 
        } 
        Index->BlockState = NULL; 
        if (Index->BlockEaseSum != NULL) 
        { 
            free(Index->BlockEaseSum); 
        } 
        Index->BlockEaseSum = NULL; 
        if (Index->VBlockInfo != NULL) 
        { 
            free(Index->VBlockInfo); 
        } 
        Index->VBlockInfo = NULL; 
        Index->BlockSum = 0; 
    } 
    return DISK_RETURN_OK; 
} 
 
/********************************************************************************************************* 
        释放扇区 
*********************************************************************************************************/ 
        static uint8 FFSFreeSector(FFSDisk *Index, uint32 SecIndex) 
{ 
    uint32 VBlockIndex, BlockIndex; 
    unsigned int i; 
    const FlashDriver *Drive; 
    uint8 *Buf; 
 
    Drive = Index->Drive; 
    VBlockIndex = SecIndex / Drive->SecsPreBlock; 
    Buf = Drive->BufA; 
    if (Index != NULL) 
    if (Drive != NULL) 
    if (VBlockIndex < Index->BlockSum) 
    { 
        BlockIndex = Index->VBlockInfo[VBlockIndex];                /* 获得物理块号     */ 
        if (BlockIndex < Index->BlockSum) 
        if (BlockIndex != 0) 
        { 
            SecIndex = SecIndex % Drive->SecsPreBlock;              /* 获得块内偏移     */ 
            SecIndex = SecIndex + BlockIndex * Drive->SecsPreBlock; /* 获得物理扇区号   */ 
            if (Drive->ExSectorRead(Drive->Index, Buf, SecIndex) == TRUE) 
            { 
                if (Buf[0] != 0xff || 
                    Buf[1] != 0xff || 
                    Buf[2] != 0xff || 
                    Buf[3] != 0xff) 
                { 
                    Buf[0] = 0x00; 
                    Buf[1] = 0x00; 
                    Buf[2] = 0x00; 
                    Buf[3] = 0x00; 
                     
                    if (Drive->ExSectorWrite(Drive->Index, Buf, SecIndex) != TRUE) 
                    { 
                        goto err; 
                    } 
                    if (Drive->ExSectorCheck(Drive->Index, Buf, SecIndex) != TRUE) 
                    { 
                        goto err; 
                    } 
                } 
                SecIndex = BlockIndex * Drive->SecsPreBlock; 
                i = Drive->SecsPreBlock; 
                do 
                { 
                    if (Drive->ExSectorRead(Drive->Index, Buf, SecIndex) == FALSE) 
                    { 
                        goto err; 
                    } 
                    if (Buf[0] == 0x00 && 
                        Buf[1] == 0x00 && 
                        Buf[2] == 0x00 && 
                        Buf[3] == 0x00) 
                    { 
                        SecIndex++; 
                        continue; 
                    } 
                    if (Buf[0] == 0xff && 
                        Buf[1] == 0xff && 
                        Buf[2] == 0xff && 
                        Buf[3] == 0xff) 
                    { 
                        SecIndex++; 
                        continue; 
                    } 
                    break; 
                } while (--i != 0); 
                if (i == 0) 
                { 
                    Index->VBlockInfo[VBlockIndex] = 0x00000000; 
                    Index->BlockState[BlockIndex] = FREE_BLOCK; 
                    if (FFSBlockErase(Index, BlockIndex) != TRUE) 
                    { 
                        FFSSetBadBlock(Index, BlockIndex); 
                        return FALSE; 
                    } 
                } 
            } 
        } 
    } 
    return TRUE; 
err: 
    Index->VBlockInfo[VBlockIndex] = 0x00000000; 
    FFSSetBadBlock(Index, BlockIndex); 
    return FALSE; 
} 
 
/********************************************************************************************************* 
        读扇区 
*********************************************************************************************************/ 
        static uint8 FFSDiskRead(FFSDisk *Index, uint8 *Buf, uint32 SecIndex) 
{ 
    uint32 BlockIndex; 
    const FlashDriver *Drive; 
    uint16 Rt; 
     
    Rt = DISK_READ_NOT_OK; 
     
    Drive = Index->Drive; 
     
    BlockIndex = SecIndex / Drive->SecsPreBlock; 
    if (Index != NULL) 
    if (Drive != NULL) 
    if (BlockIndex < Index->BlockSum) 
    { 
        Rt = DISK_READ_OK; 
        BlockIndex = Index->VBlockInfo[BlockIndex];                 /* 获得物理块号     */ 
        if (BlockIndex < Index->BlockSum) 
        if (BlockIndex != 0) 
        { 
            SecIndex = SecIndex % Drive->SecsPreBlock;              /* 获得块内偏移     */ 
            SecIndex = SecIndex + BlockIndex * Drive->SecsPreBlock; /* 获得物理扇区号   */ 
            if (Drive->SectorRead(Drive->Index, Buf, SecIndex) != TRUE) 
            { 
                Rt = DISK_READ_NOT_OK; 
            } 
        } 
    } 
    return Rt; 
} 
 
/********************************************************************************************************* 
        查找空闲块中擦除次数最少的块) 
*********************************************************************************************************/ 
        static uint32 FildBockB(FFSDisk *Index) 
{ 
    uint32 BlockIndex; 
    uint32 i, j, temp2; 
    uint32 min; 
    uint8  *BlockState, temp1; 
    uint32 *BlockEaseSum; 
    uint8 *Buf; 
 
    j = Index->Drive->BlockPreDisk; 
    Buf = Index->Drive->BufA; 
 
    min = ~0; 
    BlockIndex = 0; 
    i = j - 1; 
    BlockState = Index->BlockState + 1; 
    BlockEaseSum = Index->BlockEaseSum + 1; 
     
    do 
    { 
        temp1 = *BlockState++; 
        temp2 = *BlockEaseSum++; 
 
        if (temp1 == FREE_BLOCK) 
        if (temp2 < min) 
        { 
            min = temp2; 
            BlockIndex = j - i; 
            if (min == 0) 
            { 
                break; 
            } 
        } 
    } while (--i != 0); 
 
    if (BlockIndex < j) 
    { 
        return BlockIndex; 
    } 
    return 0; 
} 
 
/********************************************************************************************************* 
        查找擦除次数最少的块(非空闲块要加权,以尽量在空闲块重分配) 
*********************************************************************************************************/ 
        static uint32 FildBockA(FFSDisk *Index) 
{ 
    uint32 BlockIndex; 
    uint32 i, j, temp2; 
    uint32 min; 
    uint8  *BlockState, temp1; 
    uint32 *BlockEaseSum; 
    uint8 *Buf; 
 
    j = Index->Drive->BlockPreDisk; 
    Buf = Index->Drive->BufA; 
 
    min = ~0; 
    BlockIndex = 0; 
    i = j - 1; 
    BlockState = Index->BlockState + 1; 
    BlockEaseSum = Index->BlockEaseSum + 1; 
     
    do 
    { 
        temp1 = *BlockState++; 
        temp2 = *BlockEaseSum++; 
 
        if (temp1 != BAD_BLOCK) 
        if (temp2 < min) 
        { 
            min = temp2; 
            BlockIndex = j - i; 
            if (min == 0) 
            { 
                break; 
            } 
        } 
    } while (--i != 0); 
 
    if (BlockIndex < j) 
    { 
        return BlockIndex; 
    } 
    return 0; 
} 
 
/********************************************************************************************************* 
        增加虚拟块 
*********************************************************************************************************/ 
        static uint32 AddVBlock(FFSDisk *Index) 
{ 
    uint32 BlockIndex, k, temp, temp1, temp2; 
    const FlashDriver *Drive; 
    uint8 *BufA; 
    uint8 C[4]; 
 
    BlockIndex = FildBockA(Index); 
    if (BlockIndex == 0) 
    { 
        goto err; 
    } 
    if (Index->BlockState[BlockIndex] == USR_BLOCK)        /* 此块已被使用 */ 
    { 
        temp = FildBockB(Index);            /* 找空闲块  */ 
        if (temp == 0) 
        { 
            goto err; 
        } 
 
        /* 拷贝数据到空闲块  */ 
        Drive = Index->Drive; 
        k = Drive->SecsPreBlock; 
        temp1 = BlockIndex * k; 
        temp2 = temp * k; 
 
        BufA = Drive->BufA; 
        do 
        { 
            Drive->ExSectorRead(Drive->Index, BufA, temp1); 
            if (BufA[5] == 0) 
            { 
                C[0] = BufA[0]; 
                C[1] = BufA[1]; 
                C[2] = BufA[2]; 
                C[3] = BufA[3]; 
                Drive->ExSectorRead(Drive->Index, BufA, temp2); 
                if (BufA[0] != 0xff) 
                { 
                    goto err1; 
                } 
                if (BufA[1] != 0xff) 
                { 
                    goto err1; 
                } 
                if (BufA[2] != 0xff) 
                { 
                    goto err1; 
                } 
                if (BufA[3] != 0xff) 
                { 
                    goto err1; 
                } 
                if (BufA[4] != 'Z') 
                { 
                    goto err1; 
                } 
                if (BufA[5] == 0) 
                { 
                    goto err1; 
                } 
                BufA[0] = C[0]; 
                BufA[1] = C[1]; 
                BufA[2] = C[2]; 
                BufA[3] = C[3]; 
                BufA[5] = 0; 
                if (Drive->ExSectorWrite(Drive->Index, BufA, temp2) != TRUE) 
                { 
                    FFSSetBadBlock(Index, temp); 
                    goto err; 
                } 
 
                if (Drive->ExSectorCheck(Drive->Index, BufA, temp2) != TRUE) 
                { 
                    FFSSetBadBlock(Index, temp); 
                    goto err; 
                } 
 
                //if (Drive->SecCopy(Drive->Index, temp1, temp2) != TRUE) 
                //{ 
                //    FFSSetBadBlock(Index, temp); 
                //    goto err; 
                //} 
                Drive->SectorRead(Drive->Index, BufA, temp1); 
                if (Drive->SectorWrite(Drive->Index, BufA, temp2) != TRUE) 
                { 
                    FFSSetBadBlock(Index, temp); 
                    goto err; 
                } 
                if (Drive->SectorCheck(Drive->Index, BufA, temp2) != TRUE) 
                { 
                    FFSSetBadBlock(Index, temp); 
                    goto err; 
                } 
            } 
            temp1++; 
            temp2++; 
        } while (--k != 0); 
 
        k = C[2] | (C[3] << 8); 
        k = k  << 16; 
        k |= (C[0] | (C[1] << 8)); 
             
        Index->VBlockInfo[k - 1] = temp; 
        Index->BlockState[temp] = USR_BLOCK; 
        Index->BlockEaseSum[temp] += USR_BLOCK_ADD; 
                     
        /* 块擦除 */ 
        if (FFSBlockErase(Index, BlockIndex) != TRUE) 
        { 
            FFSSetBadBlock(Index, BlockIndex); 
            goto err; 
        } 
    } 
    return BlockIndex; 
err1: 
    if (FFSBlockErase(Index, BlockIndex) != TRUE) 
    { 
        FFSSetBadBlock(Index, BlockIndex); 
    } 
err: 
    return 0; 
}         
 
/********************************************************************************************************* 
        写扇区 
*********************************************************************************************************/ 
        static uint16 FFSDiskWrite(FFSDisk *Index, uint8 *Buf, uint32 SecIndex) 
{ 
    uint32 BlockIndex, VBlockIndex; 
    const FlashDriver *Drive; 
    uint32 temp, temp1, temp2; 
    unsigned int j, k, SecsPreBlock; 
    uint8 *BufA; 
     
    Drive = Index->Drive; 
     
    VBlockIndex = SecIndex / Drive->SecsPreBlock; 
    if (Index != NULL) 
    if (Drive != NULL) 
    if (VBlockIndex < Index->BlockSum) 
    { 
        BlockIndex = Index->VBlockInfo[VBlockIndex];                    /* 获得物理块号     */ 
        if (BlockIndex == 0) 
        { 
            BlockIndex = AddVBlock(Index); 
            Index->BlockEaseSum[BlockIndex] += USR_BLOCK_ADD; 
        } 
        if (BlockIndex != 0 && BlockIndex < Drive->BlockPreDisk) 
        { 
            temp1 = SecIndex % Drive->SecsPreBlock;                 /* 获得块内偏移     */ 
            temp1 = temp1 + BlockIndex * Drive->SecsPreBlock;       /* 获得物理扇区号   */ 
            BufA = Drive->BufA; 
            Drive->ExSectorRead(Drive->Index, BufA, temp1); 
            if (BufA[0] == 0xff &&                                  /* 如果可写,则直接写  */ 
                BufA[1] == 0xff && 
                BufA[2] == 0xff && 
                BufA[3] == 0xff && 
                BufA[4] == 'Z'  && 
                BufA[5] != 0x00 ) 
            { 
                VBlockIndex++; 
                BufA[0] = VBlockIndex & 0xff; 
                BufA[1] = (VBlockIndex >> 8) & 0xff; 
                BufA[2] = (VBlockIndex >> 16) & 0xff; 
                BufA[3] = (VBlockIndex >> 24) & 0xff; 
                BufA[5] = 0; 
                if (Drive->ExSectorWrite(Drive->Index, BufA, temp1) != TRUE) 
                { 
                    FFSSetBadBlock(Index, BlockIndex); 
                    goto err; 
                } 
                if (Drive->ExSectorCheck(Drive->Index, BufA, temp1) != TRUE) 
                { 
                    FFSSetBadBlock(Index, BlockIndex); 
                    goto err; 
                } 
                if (Drive->SectorWrite(Drive->Index, Buf, temp1) != TRUE) 
                { 
                    FFSSetBadBlock(Index, BlockIndex); 
                    goto err; 
                } 
                if (Drive->SectorCheck(Drive->Index, Buf, temp1) != TRUE) 
                { 
                    FFSSetBadBlock(Index, BlockIndex); 
                    goto err; 
                } 
                Index->VBlockInfo[VBlockIndex - 1] = BlockIndex; 
                Index->BlockState[BlockIndex] = USR_BLOCK; 
            } 
            else 
            { 
                /* 获取新块 */ 
                temp = AddVBlock(Index); 
                if (temp == 0) 
                { 
                    goto err; 
                } 
                 
                /* 块拷贝 */ 
                SecsPreBlock = Drive->SecsPreBlock; 
                temp1 = BlockIndex * SecsPreBlock; 
                temp2 = temp * SecsPreBlock; 
                j = SecIndex % SecsPreBlock;                    /* 获得块内偏移     */ 
                VBlockIndex++; 
                for (k = 0; k < SecsPreBlock; k++) 
                { 
                    if (k == j) 
                    { 
                        temp1++; 
                        temp2++; 
                        continue; 
                    } 
                    Drive->ExSectorRead(Drive->Index, BufA, temp1); 
                    if (BufA[5] == 0) 
                    { 
                        Drive->ExSectorRead(Drive->Index, BufA, temp2); 
                        if (BufA[0] != 0xff) 
                        { 
                            goto err1; 
                        } 
                        if (BufA[1] != 0xff) 
                        { 
                            goto err1; 
                        } 
                        if (BufA[2] != 0xff) 
                        { 
                            goto err1; 
                        } 
                        if (BufA[3] != 0xff) 
                        { 
                            goto err1; 
                        } 
                        if (BufA[4] != 'Z') 
                        { 
                            goto err1; 
                        } 
                        if (BufA[5] == 0) 
                        { 
                            goto err1; 
                        } 
                        BufA[0] = VBlockIndex & 0xff; 
                        BufA[1] = (VBlockIndex >> 8) & 0xff; 
                        BufA[2] = (VBlockIndex >> 16) & 0xff; 
                        BufA[3] = (VBlockIndex >> 24) & 0xff; 
                        BufA[5] = 0; 
                        if (Drive->ExSectorWrite(Drive->Index, BufA, temp2) != TRUE) 
                        { 
                            FFSSetBadBlock(Index, temp); 
                            goto err; 
                        } 
 
                        if (Drive->ExSectorCheck(Drive->Index, BufA, temp2) != TRUE) 
                        { 
                            FFSSetBadBlock(Index, temp); 
                            goto err; 
                        } 
                     
                        //if (Drive->SecCopy(Drive->Index, temp1, temp2) != TRUE) 
                        //{ 
                        //    FFSSetBadBlock(Index, temp); 
                        //    goto err; 
                        //} 
                        Drive->SectorRead(Drive->Index, BufA, temp1); 
                        if (Drive->SectorWrite(Drive->Index, BufA, temp2) != TRUE) 
                        { 
                            FFSSetBadBlock(Index, temp); 
                            goto err; 
                        } 
                        if (Drive->SectorCheck(Drive->Index, BufA, temp2) != TRUE) 
                        { 
                            FFSSetBadBlock(Index, temp); 
                            goto err; 
                        } 
                    } 
                    temp1++; 
                    temp2++; 
                } 
 
                /* 写新块 */ 
                temp1 = j + temp * SecsPreBlock;             /* 获得物理扇区号   */ 
                BufA = Drive->BufA; 
                Drive->ExSectorRead(Drive->Index, BufA, temp1); 
                if (BufA[0] != 0xff) 
                { 
                    goto err1; 
                } 
                if (BufA[1] != 0xff) 
                { 
                    goto err1; 
                } 
                if (BufA[2] != 0xff) 
                { 
                    goto err1; 
                } 
                if (BufA[3] != 0xff) 
                { 
                    goto err1; 
                } 
                if (BufA[4] != 'Z') 
                { 
                    goto err1; 
                } 
                if (BufA[5] == 0) 
                { 
                    goto err1; 
                } 
                BufA[0] = VBlockIndex & 0xff; 
                BufA[1] = (VBlockIndex >> 8) & 0xff; 
                BufA[2] = (VBlockIndex >> 16) & 0xff; 
                BufA[3] = (VBlockIndex >> 24) & 0xff; 
                BufA[5] = 0; 
                if (Drive->ExSectorWrite(Drive->Index, BufA, temp1) != TRUE) 
                { 
                    FFSSetBadBlock(Index, temp); 
                    goto err; 
                } 
                if (Drive->ExSectorCheck(Drive->Index, BufA, temp1) != TRUE) 
                { 
                    FFSSetBadBlock(Index, temp); 
                    goto err; 
                } 
 
                if (Drive->SectorWrite(Drive->Index, Buf, temp1) != TRUE) 
                { 
                    FFSSetBadBlock(Index, temp); 
                    goto err; 
                } 
                if (Drive->SectorCheck(Drive->Index, Buf, temp1) != TRUE) 
                { 
                    FFSSetBadBlock(Index, temp); 
                    goto err; 
                } 
 
                Index->VBlockInfo[VBlockIndex - 1] = temp; 
                Index->BlockEaseSum[temp] += USR_BLOCK_ADD; 
                Index->BlockState[temp] = USR_BLOCK; 
 
                /* 块擦除 */ 
                if (FFSBlockErase(Index, BlockIndex) != TRUE) 
                { 
                    FFSSetBadBlock(Index, BlockIndex); 
                } 
            } 
            return DISK_WRITE_OK; 
        } 
    } 
err1: 
    if (FFSBlockErase(Index, temp) != TRUE) 
    { 
        FFSSetBadBlock(Index, temp); 
    } 
err: 
    return DISK_WRITE_NOT_OK; 
} 
 
/********************************************************************************************************* 
** 函数名称: ZLG_FFS 
** 功能描述: 底层驱动程序与上层的接口程序 
** 
** 输 入: Cammand:DISK_INIT:驱动程序初始化 
**                 DISK_CLOSE:关闭驱动器(移除驱动程序)                  
**                 DISK_READ_SECTOR:读扇区 
**                 DISK_WRITE_SECTOR:写扇区 
**                 DISK_FREE_SECTOR: 释放扇区     
**        Parameter:剩余参数 
** 输 出: DISK_READ_OK:读扇区完成 
**        DISK_READ_NOT_OK:读扇区失败 
**        DISK_WRITE_OK:写扇区完成 
**        DISK_WRITE_NOT_OK:写扇区失败 
**        DISK_INIT_OK:初始化完成 
**        DISK_INIT_NOT_OK:初始化失败 
**        BAD_DISK_COMMAND:无效的命令 
** 全局变量: 无 
** 调用模块: 无 
** 
** 作 者: 陈明计 
** 日 期: 2003年9月3日 
**------------------------------------------------------------------------------------------------------- 
** 修改人: 
** 日 期: 
**------------------------------------------------------------------------------------------------------ 
********************************************************************************************************/ 
        uint16 ZLG_FFS(uint8 Cammand, void *Parameter) 
{ 
    uint16 rt; 
    Disk_RW_Parameter * Dp; 
    FFSDisk *Disk; 
     
    Dp = (Disk_RW_Parameter *)Parameter; 
    Disk = (FFSDisk *) Dp->RsvdForLow; 
     
    OS_ENTER_CRITICAL(); 
    switch (Cammand) 
    { 
        case DISK_INIT: 
            rt = FFSDiskInit(Disk); 
            break; 
        case DISK_CLOSE: 
            rt = FFSDiskClose(Disk); 
            break; 
        case DISK_READ_SECTOR: 
            rt = FFSDiskRead(Disk, Dp->Buf, Dp->SectorIndex); 
            break; 
        case DISK_WRITE_SECTOR: 
            if ((rt = FFSDiskWrite(Disk, Dp->Buf, Dp->SectorIndex)) == DISK_WRITE_NOT_OK) 
            { 
                if ((rt = FFSDiskWrite(Disk, Dp->Buf, Dp->SectorIndex)) == DISK_WRITE_NOT_OK) 
                { 
                    rt = FFSDiskWrite(Disk, Dp->Buf, Dp->SectorIndex); 
                } 
            } 
            break; 
        case DISK_DRIVER_VER: 
            Dp->SectorIndex = 110; 
            rt = DISK_RETURN_OK; 
            break; 
        case DISK_CHECK_CMD: 
            rt = DISK_FALSE; 
            if ((Dp->SectorIndex == DISK_INIT) 
               || (Dp->SectorIndex == DISK_CLOSE) 
               || (Dp->SectorIndex == DISK_READ_SECTOR) 
               || (Dp->SectorIndex == DISK_WRITE_SECTOR) 
               || (Dp->SectorIndex == DISK_DRIVER_VER) 
               || (Dp->SectorIndex == DISK_CHECK_CMD) 
               || (Dp->SectorIndex == DISK_LOW_FORMAT) 
               || (Dp->SectorIndex == DISK_FREE_SECTOR) 
               || (Dp->SectorIndex == DISK_GET_SECTOR_NUMBER) 
               || (Dp->SectorIndex == DISK_GET_BYTES_PER_SECTOR) 
               || (Dp->SectorIndex == DISK_CHECK_CHANGE) 
               ) 
            { 
                rt = DISK_TRUE; 
            } 
            break; 
        case DISK_LOW_FORMAT: 
            if (Dp->SectorIndex == 0) 
            { 
                NFFormat(Disk); 
            } 
            else 
            { 
                NFFormatA(Disk); 
            } 
            rt = DISK_RETURN_OK; 
            break; 
        case DISK_FREE_SECTOR: 
            FFSFreeSector(Disk, Dp->SectorIndex); 
            rt = DISK_RETURN_OK; 
            break; 
        case DISK_GET_SECTOR_NUMBER: 
            Dp->SectorIndex = (Disk->BlockSum) * (Disk->Drive->SecsPreBlock); 
            rt = DISK_RETURN_OK; 
            break; 
        case DISK_GET_BYTES_PER_SECTOR: 
            Dp->SectorIndex = Disk->Drive->BytsPerSec; 
            rt = DISK_RETURN_OK; 
            break; 
        case DISK_CHECK_CHANGE: 
            rt = DISK_FALSE; 
        case DISK_GET_SECTORS_PER_BLOCK: 
            rt = BAD_DISK_COMMAND; 
            break; 
        case DISK_READ_BLOCK: 
            rt = BAD_DISK_COMMAND; 
            break; 
        case DISK_WRITE_BLOCK: 
            rt = BAD_DISK_COMMAND; 
            break; 
        default: 
            rt = BAD_DISK_COMMAND; 
            break; 
    } 
    OS_EXIT_CRITICAL(); 
    return rt; 
} 
 
/********************************************************************************************************* 
**                            End Of File 
********************************************************************************************************/