www.pudn.com > File_SD_OS.rar > RWSec.C


/****************************************Copyright (c)************************************************** 
**                               广州周立功单片机发展有限公司 
**                                     研    究    所 
**                                        ARM开发组 
** 
**                                 http://www.zlgmcu.com 
** 
**--------------文件信息-------------------------------------------------------------------------------- 
**文   件   名: rwsec.c 
**创   建   人: 陈明计 
**最后修改日期: 2004年3月11日 
**描        述: FAT文件系统关于cache管理的部分 
**               
**--------------历史版本信息---------------------------------------------------------------------------- 
** 创建人: 陈明计 
** 版  本: V1.0 
** 日 期: 2003年9月3日 
** 描 述: 原始版本 
** 
**--------------当前版本修订------------------------------------------------------------------------------ 
** 修改人: 陈明计 
** 日 期: 2004年4月10日 
** 描 述: 增加注释 
** 
**------------------------------------------------------------------------------------------------------ 
********************************************************************************************************/ 
#define IN_RWSEC 
#include "config.h" 
Disk_cache DiskCache[MAX_DISK_CACHES];      /* 磁盘cache */ 
 
/********************************************************************************************************* 
** 函数名称: CacheInit 
** 功能描述: 初始化磁盘cache 
** 
** 输 入: 无 
** 
** 输 出: 无 
**          
** 全局变量: DiskCache 
** 调用模块: 无 
** 
** 作 者: 陈明计 
** 日 期: 2003年9月3日 
**------------------------------------------------------------------------------------------------------- 
** 修改人: 陈明计 
** 日 期: 2004年4月10日 
**------------------------------------------------------------------------------------------------------ 
********************************************************************************************************/ 
        void CacheInit(void) 
{ 
    unsigned int i; 
     
    for (i = 0; i < MAX_DISK_CACHES; i++) 
    { 
        DiskCache[i].Drive = EMPTY_DRIVE;   /* cache空闲 */ 
        DiskCache[i].Flag = 0;              /* 扇区无需回写 */ 
        DiskCache[i].RW_ID = (uint16)(~0);  /* 访问纪录 */ 
        DiskCache[i].SecIndex = 0;          /* 缓冲的扇区号  */ 
    } 
} 
 
 
/********************************************************************************************************* 
** 函数名称: CloseSec 
** 功能描述: 解锁指定cache(允许切换出内存) 
** 
** 输 入: Drive:逻辑驱动器号 
**        Index:缓冲的扇区号 
** 输 出: 无 
**          
** 全局变量: DiskCache 
** 调用模块: 无 
** 
** 作 者: 陈明计 
** 日 期: 2003年9月3日 
**------------------------------------------------------------------------------------------------------- 
** 修改人: 陈明计 
** 日 期: 2004年4月10日 
**------------------------------------------------------------------------------------------------------ 
********************************************************************************************************/ 
        void CloseSec(uint8 Drive, uint32 Index) 
{ 
    Drive = Drive; 
    Index = Index; 
} 
 
/********************************************************************************************************* 
** 函数名称: CacheWriteBack2 
** 功能描述: 把指定扇区写回逻辑盘 
** 
** 输 入: Index:cache索引 
** 
** 输 出: 无 
**          
** 全局变量: DiskCache 
** 调用模块: GetDiskInfo2 
** 
** 作 者: 陈明计 
** 日 期: 2003年9月3日 
**------------------------------------------------------------------------------------------------------- 
** 修改人: 陈明计 
** 日 期: 2004年4月10日 
**------------------------------------------------------------------------------------------------------ 
** 修改人: 严寒亮 
** 日 期: 2004年11月10日 
** 说  明: 在回写cache时,判断该扇区是否为FAT表,如果是,将该扇区覆盖到各个备份FAT表,实现同步。 
**------------------------------------------------------------------------------------------------------ 
 
 
 
********************************************************************************************************/ 
        void CacheWriteBack2(uint16 Index) 
{ 
    Disk_RW_Parameter Pa; 
    Disk_Info * Disk; 
    int i; 
 
    Disk = GetDiskInfo2(DiskCache[Index].Drive);             /*  获取逻辑盘信息 */ 
    if (Disk != NULL) 
    if (Disk->DiakCommand != NULL) 
    { 
        DiskCache[Index].Flag &= ~CACHE_WRITED;             /*  cache 不再需要回写 */ 
         
        i = 1; 
        if(DiskCache[Index].SecIndex >= Disk->FATStartSec)  /* 判断写入扇区是否为主FAT表的空间 */ 
        if(DiskCache[Index].SecIndex < Disk->FATStartSec + Disk->FATSecCnt) 
        { 
            i = Disk->NumFATs;                              /* 需要同步的FAT表个数 */ 
        } 
         
        /* 传递参数 */ 
        Pa.SectorIndex = DiskCache[Index].SecIndex + Disk->SecOffset; 
        Pa.RsvdForLow = Disk->RsvdForLow; 
        Pa.Buf = DiskCache[Index].buf;               
         
        do                                              /* 循环写入各FAT表,如果为普通扇区则只有一次 */ 
        { 
            Disk->DiakCommand(DISK_WRITE_SECTOR, &Pa);  /* 调用底层驱动写扇区 */  
            Pa.SectorIndex += Disk->FATSecCnt; 
        } while (--i > 0); 
    } 
} 
 
/********************************************************************************************************* 
** 函数名称: CacheWriteBack 
** 功能描述: 把指定cache写回逻辑盘 
** 
** 输 入: Drive:逻辑驱动器号 
**        Index:缓冲的扇区号 
** 输 出: 无 
**          
** 全局变量: DiskCache 
** 调用模块: CacheWriteBack2 
** 
** 作 者: 陈明计 
** 日 期: 2003年9月3日 
**------------------------------------------------------------------------------------------------------- 
** 修改人: 陈明计 
** 日 期: 2004年4月10日 
**------------------------------------------------------------------------------------------------------ 
********************************************************************************************************/ 
       void CacheWriteBack(uint8 Drive, uint32 Index) 
{ 
    unsigned int i; 
    unsigned int temp; 
     
    temp = Index & ((1 << BASE_CACHE_NUM) - 1); 
    for (i = 0; i < (1 << BASE_CACHE_NUM); i++) 
    { 
        if (DiskCache[temp].Drive == Drive) 
        if (DiskCache[temp].SecIndex == Index) 
        { 
            if ((DiskCache[temp].Flag & CACHE_WRITED) != 0) 
            { 
                CacheWriteBack2(temp); 
            } 
            break; 
        } 
        temp += MAX_DISK_CACHES >> BASE_CACHE_NUM; 
    } 
} 
 
/********************************************************************************************************* 
** 函数名称: AllCacheWriteBack 
** 功能描述: 把所有已改变的扇区写回逻辑盘 
** 
** 输 入: 无 
** 
** 输 出: 无 
**          
** 全局变量: DiskCache 
** 调用模块: CacheWriteBack2 
** 
** 作 者: 陈明计 
** 日 期: 2003年9月3日 
**------------------------------------------------------------------------------------------------------- 
** 修改人: 陈明计 
** 日 期: 2004年4月10日 
**------------------------------------------------------------------------------------------------------ 
********************************************************************************************************/ 
       void AllCacheWriteBack(void) 
{ 
    unsigned int i; 
 
    for (i = 0; i < MAX_DISK_CACHES; i++) 
    { 
        if ((DiskCache[i].Flag & CACHE_WRITED) != 0) 
        { 
            CacheWriteBack2(i); 
        } 
    } 
} 
 
/********************************************************************************************************* 
** 函数名称: GetCache 
** 功能描述: 获取一个cache 
** 
** 输 入: 无 
** 
** 输 出: cache索引 
**          
** 全局变量: DiskCache 
** 调用模块: 无 
** 
** 作 者: 陈明计 
** 日 期: 2003年9月3日 
**------------------------------------------------------------------------------------------------------- 
** 修改人: 陈明计 
** 日 期: 2004年4月10日 
**------------------------------------------------------------------------------------------------------ 
********************************************************************************************************/ 
        static uint16 GetCache(uint32 Index) 
{ 
    unsigned int Max; 
    unsigned int i, j; 
    unsigned int temp; 
     
    Max = 0; 
    j = ~0; 
    temp = Index & ((1 << BASE_CACHE_NUM) - 1); 
    for (i = 0; i < (1 << BASE_CACHE_NUM); i++) 
    { 
        if (Max <= DiskCache[temp].RW_ID) 
        { 
            Max = DiskCache[temp].RW_ID; 
            j = temp; 
        } 
        if (Max == ~0) 
        { 
            break; 
        } 
        temp += MAX_DISK_CACHES >> BASE_CACHE_NUM; 
    } 
    if (j < MAX_DISK_CACHES) 
    { 
        if (DiskCache[j].Drive != EMPTY_DRIVE) 
        if ((DiskCache[j].Flag & CACHE_WRITED) != 0) 
        { 
            CacheWriteBack2(j); 
        } 
    } 
    return j; 
} 
 
/********************************************************************************************************* 
** 函数名称: OpenSec 
** 功能描述: 为逻辑盘上的一个扇区打开一个cache并锁定 
** 
** 输 入: Drive:磁盘号 
**        Index:扇区号 
** 输 出: 指向指定扇区数据的指针 
**          
** 全局变量: DiskCache 
** 调用模块: 无 
** 
** 作 者: 陈明计 
** 日 期: 2003年9月3日 
**------------------------------------------------------------------------------------------------------- 
** 修改人: 陈明计 
** 日 期: 2004年4月10日 
**------------------------------------------------------------------------------------------------------ 
********************************************************************************************************/ 
        uint8 *OpenSec(uint8 Drive, uint32 Index) 
{ 
    unsigned int i; 
    uint8 *Rt; 
    Disk_Info *Disk; 
    unsigned int temp; 
     
    /* 增加访问间隔 */ 
    temp = Index & ((1 << BASE_CACHE_NUM) - 1); 
    for (i = 0; i < (1 << BASE_CACHE_NUM); i++) 
    {    
        if (DiskCache[temp].Drive != EMPTY_DRIVE) 
        { 
            if (DiskCache[temp].RW_ID < (uint16)(~0)) 
            { 
                DiskCache[temp].RW_ID++; 
            } 
        } 
        temp += MAX_DISK_CACHES >> BASE_CACHE_NUM; 
    } 
 
    /* 看扇区是否已经缓存 */ 
    Rt = NULL; 
    temp = Index & ((1 << BASE_CACHE_NUM) - 1); 
    for (i = 0; i < (1 << BASE_CACHE_NUM); i++) 
    {    
        if (DiskCache[temp].Drive == Drive ) 
        if (DiskCache[temp].SecIndex == Index) 
        { 
            Rt = DiskCache[temp].buf; 
            DiskCache[temp].RW_ID = 0; 
            break; 
        } 
        temp += MAX_DISK_CACHES >> BASE_CACHE_NUM; 
    } 
     
    /* Rt == NULL则未缓存 */ 
    if (Rt == NULL) 
    { 
        Disk = GetDiskInfo2(Drive); 
        if (Disk != NULL) 
        if (Disk->SecPerDisk > Index) 
        { 
            i = GetCache(Index);                     /* 获取cache */ 
            if (i < MAX_DISK_CACHES) 
            { 
                /* 初始化cache  */ 
                DiskCache[i].Drive = Drive;      
                DiskCache[i].RW_ID = 0; 
                DiskCache[i].Flag = 0; 
                DiskCache[i].SecIndex = Index; 
                Rt = DiskCache[i].buf; 
                for (i = 0; i < Disk->BytsPerSec; i++) 
                { 
                    Rt[i] = 0; 
                } 
            } 
        } 
    } 
    return Rt; 
} 
 
/********************************************************************************************************* 
** 函数名称: ReadSec 
** 功能描述: 从逻辑盘读扇区 
** 
** 输 入: Disk:逻辑盘信息 
**        Index:扇区号 
** 输 出: TRUE:成功 
**         FALSE:失败 
** 全局变量: DiskCache 
** 调用模块: GetDiskInfo2 
** 
** 作 者: 陈明计 
** 日 期: 2003年9月5日 
**------------------------------------------------------------------------------------------------------- 
** 修改人: 陈明计 
** 日 期: 2004年4月10日 
**------------------------------------------------------------------------------------------------------ 
 
 
 
********************************************************************************************************/ 
        uint8 ReadSec(uint8 Drive, uint32 Index) 
{ 
    unsigned int i; 
    Disk_RW_Parameter Pa; 
    Disk_Info *Disk; 
    unsigned int Rt; 
    unsigned int temp; 
     
    temp = Index & ((1 << BASE_CACHE_NUM) - 1); 
    for (i = 0; i < (1 << BASE_CACHE_NUM); i++) 
    {    
        if (DiskCache[temp].Drive == Drive) 
        if (DiskCache[temp].SecIndex == Index) 
        { 
            if ((DiskCache[temp].Flag & CACHE_READED) != 0) 
            { 
                return RETURN_OK; 
            } 
            break; 
        } 
        temp += MAX_DISK_CACHES >> BASE_CACHE_NUM; 
    } 
    Rt = SECTOR_NOT_IN_CACHE; 
    if (temp < MAX_DISK_CACHES) 
    { 
        Disk = GetDiskInfo2(Drive);     
 
        DiskCache[temp].Flag |= CACHE_READED; 
 
        /* 从磁盘读取扇区数据 */ 
        Pa.SectorIndex = Index + Disk->SecOffset; 
        Pa.RsvdForLow = Disk->RsvdForLow; 
        Pa.Buf = DiskCache[temp].buf; 
        Rt = NOT_FIND_DISK; 
        if (Disk->DiakCommand != NULL) 
        { 
            Rt = SECTOR_READ_ERR; 
            if (Disk->DiakCommand(DISK_READ_SECTOR, &Pa) == DISK_READ_OK) 
            { 
                return RETURN_OK; 
            } 
        } 
    } 
    return Rt; 
} 
 
/********************************************************************************************************* 
** 函数名称: WriteSec 
** 功能描述: 说明指定逻辑盘的指定一个扇区被改写 
** 
** 输 入: Drive:逻辑盘号 
**        Index:扇区号 
** 输 出: 无 
**          
** 全局变量: DiskCache 
** 调用模块: 无 
** 
** 作 者: 陈明计 
** 日 期: 2003年9月3日 
**------------------------------------------------------------------------------------------------------- 
** 修改人: 陈明计 
** 日 期: 2004年4月10日 
**------------------------------------------------------------------------------------------------------ 
********************************************************************************************************/ 
        void WriteSec(uint8 Drive, uint32 Index) 
{ 
    unsigned int i; 
    unsigned int temp; 
     
    temp = Index & ((1 << BASE_CACHE_NUM) - 1); 
    for (i = 0; i < (1 << BASE_CACHE_NUM); i++) 
    {    
        if (DiskCache[temp].Drive == Drive) 
        if (DiskCache[temp].SecIndex == Index) 
        { 
            DiskCache[temp].Flag |= (CACHE_WRITED | CACHE_READED); 
            break; 
        } 
        temp += MAX_DISK_CACHES >> BASE_CACHE_NUM; 
    } 
} 
 
/********************************************************************************************************* 
** 函数名称: FreeDriveCache 
** 功能描述: 释放指定逻辑盘的扇区 
** 
** 输 入: Drive:逻辑盘号 
** 
** 输 出: 无 
**          
** 作 者: 陈明计 
** 日 期: 2004年2月2日 
**------------------------------------------------------------------------------------------------------- 
** 修改人:  
** 日 期:  
**------------------------------------------------------------------------------------------------------ 
********************************************************************************************************/ 
        void FreeDriveCache(uint8 Drive) 
{ 
    unsigned int i; 
     
    for (i = 0; i < MAX_DISK_CACHES; i++) 
    { 
        if (DiskCache[i].Drive == Drive) 
        { 
            if ((DiskCache[i].Flag & CACHE_WRITED) != 0) 
            { 
                CacheWriteBack2(i); 
            } 
            DiskCache[i].Drive = EMPTY_DRIVE; 
            DiskCache[i].RW_ID = (uint16)(~0); 
        } 
    } 
} 
 
/********************************************************************************************************* 
** 函数名称: FreeCache 
** 功能描述: 释放指定的扇区 
** 
** 输 入: Drive:逻辑盘号 
** 
** 输 出: 无 
**          
** 作 者: 陈明计 
** 日 期: 2004年2月2日 
**------------------------------------------------------------------------------------------------------- 
** 修改人:  
** 日 期:  
**------------------------------------------------------------------------------------------------------ 
********************************************************************************************************/ 
        void FreeCache(uint8 Drive, uint32 Index) 
{ 
    unsigned int i; 
    unsigned int temp; 
     
    temp = Index & ((1 << BASE_CACHE_NUM) - 1); 
    for (i = 0; i < (1 << BASE_CACHE_NUM); i++) 
    { 
        temp += MAX_DISK_CACHES >> BASE_CACHE_NUM; 
 
        if (DiskCache[temp].Drive == Drive) 
        if (DiskCache[temp].SecIndex == Index) 
        { 
            if ((DiskCache[temp].Flag & CACHE_WRITED) != 0) 
            { 
                CacheWriteBack2(temp); 
            } 
            DiskCache[temp].Drive = EMPTY_DRIVE;  
            DiskCache[temp].RW_ID = (uint16)(~0); 
            break; 
        } 
    } 
} 
 
/********************************************************************************************************* 
**                            End Of File 
********************************************************************************************************/