⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rwbuffer.c

📁 ST5518机顶盒系统文件系统源代码!绝对超值!
💻 C
字号:
/******************************************************************************    File Name   : rwbuffer.c    Description : Implementaion of the R/W Buffer internal API******************************************************************************//* Includes ---------------------------------------------------------------- */#include <stdlib.h>#include <stdio.h>#include <ctype.h>#include <assert.h>#include <string.h>#include "rwbuffer.h"#include "file.h"#include "hal.h"#include "sttbx.h"/* Private Types ----------------------------------------------------------- */typedef struct RWBuffer_s{    U64 LBA;    U16 Flags;    U16 ReferenceCount;    U8  Buffer[DISK_SECTOR_SIZE];}RWBuffer_t;/* Private Constants ------------------------------------------------------- */#define RWB_FLAG_STREAM         (0X0001)  /* Stream data */#define RWB_FLAG_MODIFIED       (0X0002)#define RWB_FLAG_IN_MEMORY      (0X0004)/* Private Variables ------------------------------------------------------- *//* Private Macros ---------------------------------------------------------- *//* Private Function Prototypes --------------------------------------------- *//* Functions --------------------------------------------------------------- *//******************************************************************************Function Name : stavfs_InitRWCache  Description : Initialise the R/W Cache.                Allocate space for the R/W Buffers and initialise the data.   Parameters :******************************************************************************/ST_ErrorCode_t stavfs_InitRWCache(stavfs_Device_t *Device_p){    ST_ErrorCode_t Error = ST_NO_ERROR;        Device_p->RWCache = memory_allocate(Device_p->MemoryPartition, 2*MAX_OPEN_FILES*sizeof(RWBuffer_t));        if (Device_p->RWCache == NULL)    {        Error = ST_ERROR_NO_MEMORY;    }    else    {        /* Initialise the buffers */                int i;        for (i = 0; (i < 2*MAX_OPEN_FILES); i++)        {            ((RWBuffer_t*)Device_p->RWCache)[i].Flags          = 0;            ((RWBuffer_t*)Device_p->RWCache)[i].ReferenceCount = 0;        }    }    return (Error);}/******************************************************************************Function Name : stavfs_TermRWCache  Description : Terminate the R/W Cache.                Flush data to disk and free any memory allocated.   Parameters :******************************************************************************/ST_ErrorCode_t stavfs_TermRWCache(stavfs_Device_t *Device_p){    ST_ErrorCode_t Error = ST_NO_ERROR;        assert (NULL != Device_p);        if (NULL != Device_p->HALData)    {        /* Flush any data to disk */        Error = stavfs_FlushRWCache(Device_p);    }        /* Free up any allocated space */        if (Device_p->RWCache != NULL)    {        memory_deallocate(Device_p->MemoryPartition, Device_p->RWCache);        Device_p->RWCache = NULL;    }            return (ST_NO_ERROR);}/******************************************************************************Function Name : stavfs_FlushRWCache  Description : Flush the R/W Cache.                Flush data to disk.   Parameters :******************************************************************************/ST_ErrorCode_t stavfs_FlushRWCache(stavfs_Device_t *Device_p){    ST_ErrorCode_t Error = ST_NO_ERROR;    int i;        RWBuffer_t *BufferTable = NULL;        assert (NULL != Device_p);    assert (NULL != Device_p->HALData);        BufferTable = (RWBuffer_t*)Device_p->RWCache;        if (BufferTable != NULL)    {        /* Look for modified buffers and write the to disk */        for (i = 0; (i < 2*MAX_OPEN_FILES); i++)        {            if (BufferTable[i].Flags & RWB_FLAG_MODIFIED)            {                BufferTable[i].Flags &= ~RWB_FLAG_MODIFIED;                if (ST_NO_ERROR != stavfs_HalWrite (Device_p->HALData, &(BufferTable[i].LBA), 1, (char*)BufferTable[i].Buffer, BufferTable[i].Flags & RWB_FLAG_STREAM))                {                    Error = STAVFS_ERROR_UNWRITABLE_DISK;                }            }        }    }        return (Error);}/******************************************************************************Function Name : stavfs_DiscardRWBuffer  Description : Finish with the R/W Cache Buffer.                Flush data to disk.   Parameters :******************************************************************************/ST_ErrorCode_t stavfs_DiscardRWBuffer(stavfs_Device_t *Device_p, stavfs_RWBufferRef_t *Buff){    ST_ErrorCode_t  Error  = ST_NO_ERROR;    RWBuffer_t     *Buffer = NULL;        assert (NULL != Device_p);    assert (NULL != Device_p->HALData);    assert (NULL != Buff);        Buffer = *(RWBuffer_t**)Buff;        if (NULL != Buffer)    {        /* If the Buffer is no longer used and has been modified */                if ((--(Buffer->ReferenceCount) == 0) &&            (Buffer->Flags & RWB_FLAG_MODIFIED))        {            /* Flush the buffer to disk */            Buffer->Flags &= ~RWB_FLAG_MODIFIED;                        Error = stavfs_HalWrite (Device_p->HALData, &(Buffer->LBA), 1, (char*)Buffer->Buffer, Buffer->Flags & RWB_FLAG_STREAM);        }                *(RWBuffer_t**)Buff = NULL;    }        return (Error);}/******************************************************************************Function Name : stavfs_AcquireRWBuffer  Description : Obtain a R/W Cache Buffer.                Flush data to disk.   Parameters :******************************************************************************/stavfs_RWBufferRef_t stavfs_AcquireRWBuffer(stavfs_Device_t *Device_p, U64 *Sector, BOOL Streem){    int i;    RWBuffer_t *BufferTable    = NULL;    RWBuffer_t *FreeBuffer     = NULL;    RWBuffer_t *AssignedBuffer = NULL;        assert (NULL != Device_p);    assert (NULL != Device_p->RWCache);        BufferTable = (RWBuffer_t*)Device_p->RWCache;        /* Find any existing Buffer for this Sector */        for (i = 0; (i < 2*MAX_OPEN_FILES) && (AssignedBuffer == NULL); i++)    {        if (INT_I64_AreEqual(*Sector, BufferTable[i].LBA))        {            AssignedBuffer = BufferTable+i;        }        else if (BufferTable[i].ReferenceCount == 0)        {            FreeBuffer = BufferTable+i;        }    }        /* If there is no existing buffer allocate the free buffer */        if ((AssignedBuffer == NULL) && (FreeBuffer != NULL))    {        /* Allocate the Free Buffer */                AssignedBuffer        = FreeBuffer;        AssignedBuffer->LBA   = *Sector;        AssignedBuffer->Flags = (Streem)?(RWB_FLAG_STREAM):(0);    }        if (AssignedBuffer != NULL)    {        /* Increment the reference count */        AssignedBuffer->ReferenceCount++;    }        return (AssignedBuffer);}/******************************************************************************Function Name : stavfs_SetRWBuffer  Description : Set the given buffer reference to a buffer for the given LBA.   Parameters :******************************************************************************/ST_ErrorCode_t stavfs_SetRWBuffer(stavfs_Device_t *Device_p, U64 *Sector, stavfs_RWBufferRef_t *Buff, BOOL Streem){    ST_ErrorCode_t   Error = ST_NO_ERROR;    RWBuffer_t *Buffer;        assert (NULL != Device_p);    assert (NULL != Device_p->RWCache);    assert (NULL != Sector);    assert (NULL != Buff);        Buffer = (RWBuffer_t*)(*Buff);        if (Buffer == NULL)    {        *Buff = stavfs_AcquireRWBuffer (Device_p, Sector, Streem);                if (NULL == *Buff)        {            Error = STAVFS_ERROR_CACHE_FULL;        }    }    else if (INT_I64_AreNotEqual(*Sector, Buffer->LBA))    {        if (ST_NO_ERROR != (Error = stavfs_DiscardRWBuffer (Device_p, Buff)))        {        }        else if (NULL == (*Buff = stavfs_AcquireRWBuffer (Device_p, Sector, Streem)))        {            Error = STAVFS_ERROR_CACHE_FULL;        }    }        return (Error);}/******************************************************************************Function Name : stavfs_RWCacheBlockRead  Description : Read a block of sectors from disk.   Parameters :******************************************************************************/ST_ErrorCode_t stavfs_RWCacheBlockRead(stavfs_Device_t *Device_p, U64 *FirstSector, U32 NbSectors, char *MemoryDestination, BOOL Streem){    int i;    U64 LastSector;        ST_ErrorCode_t  Error       = ST_NO_ERROR;    RWBuffer_t     *BufferTable = NULL;        assert (NULL != Device_p);    assert (NULL != Device_p->HALData);    assert (NULL != Device_p->RWCache);        BufferTable = (RWBuffer_t*)Device_p->RWCache;    Error = stavfs_HalRead (Device_p->HALData, FirstSector, NbSectors, MemoryDestination, Streem);        if (Error == ST_NO_ERROR)    {        /* Find all buffers affecting this read */         INT_I64_AddLit(*FirstSector, NbSectors, LastSector);         for (i = 0; (i < 2*MAX_OPEN_FILES); i++)        {            if (INT_I64_IsGreaterOrEqual(BufferTable[i].LBA, *FirstSector) &&                INT_I64_IsLessThan      (BufferTable[i].LBA,  LastSector))            {                if (BufferTable[i].Flags & RWB_FLAG_MODIFIED)                {                    U32 Offset;                     INT_I64_LitDiff(BufferTable[i].LBA, *FirstSector, Offset);                    Offset *= DISK_SECTOR_SIZE;                     /* Copy from the buffer */                    memcpy(MemoryDestination +Offset,                           BufferTable[i].Buffer,                           sizeof(BufferTable[i].Buffer));                }            }        }    }        return (Error);}/******************************************************************************Function Name : stavfs_RWCacheBlockWrite  Description : Write a block of sectors to disk.   Parameters :******************************************************************************/ST_ErrorCode_t stavfs_RWCacheBlockWrite(stavfs_Device_t *Device_p, U64 *FirstSector, U32 NbSectors, char const *MemoryDestination, BOOL Streem){    int i;    U64 LastSector;        ST_ErrorCode_t  Error       = ST_NO_ERROR;    RWBuffer_t     *BufferTable = NULL;        assert (NULL != Device_p);    assert (NULL != Device_p->HALData);    assert (NULL != Device_p->RWCache);    assert (0    != NbSectors);        BufferTable = (RWBuffer_t*)Device_p->RWCache;    Error = stavfs_HalWrite (Device_p->HALData, FirstSector, NbSectors, MemoryDestination, Streem);        if (Error == ST_NO_ERROR)    {        /* Find all buffers affected by this write */         INT_I64_AddLit(*FirstSector, NbSectors, LastSector);         for (i = 0; (i < 2*MAX_OPEN_FILES); i++)        {            if (INT_I64_IsGreaterOrEqual(BufferTable[i].LBA, *FirstSector) &&                INT_I64_IsLessThan      (BufferTable[i].LBA,  LastSector))            {                U32 Offset;                 INT_I64_LitDiff(BufferTable[i].LBA, *FirstSector, Offset);                Offset *= DISK_SECTOR_SIZE;                 /* Copy from the buffer */                memcpy(BufferTable[i].Buffer,                       MemoryDestination +Offset,                       sizeof(BufferTable[i].Buffer));                 BufferTable[i].Flags &= ~RWB_FLAG_MODIFIED;   /* Not Modified */                BufferTable[i].Flags |=  RWB_FLAG_IN_MEMORY;  /* Data in Memory */            }        }    }        return (Error);}/******************************************************************************Function Name : stavfs_RWBufferRead  Description : Read data from a RWBuffer.   Parameters :******************************************************************************/ST_ErrorCode_t stavfs_RWBufferRead(stavfs_Device_t *Device_p, stavfs_RWBufferRef_t Buff, U32 Offset, U32 Size, char *MemoryDestination){    ST_ErrorCode_t  Error  = ST_NO_ERROR;    RWBuffer_t     *Buffer = NULL;        assert (NULL != Buff);    assert (NULL != Device_p);    assert (NULL != Device_p->HALData);        Buffer = (RWBuffer_t*)Buff;        /* Normalise the data */        if (Size+Offset > DISK_SECTOR_SIZE)    {        Size -= Size+Offset-DISK_SECTOR_SIZE;    }        if (Offset < DISK_SECTOR_SIZE)    {        /* Load the data from disk */         if (!(Buffer->Flags & RWB_FLAG_IN_MEMORY))        {            Error = stavfs_HalRead (Device_p->HALData, &(Buffer->LBA), 1, (char*)Buffer->Buffer, Buffer->Flags & RWB_FLAG_STREAM);            Buffer->Flags |= RWB_FLAG_IN_MEMORY;        }         if (Error == ST_NO_ERROR)        {            memcpy(MemoryDestination, Buffer->Buffer+Offset, Size);        }    }        return (Error);}/******************************************************************************Function Name : stavfs_RWBufferWrite  Description : Write data to a RWBuffer.   Parameters :******************************************************************************/ST_ErrorCode_t stavfs_RWBufferWrite(stavfs_Device_t *Device_p, stavfs_RWBufferRef_t Buff, U32 Offset, U32 Size, char const *MemoryDestination, BOOL EndOfFile){    ST_ErrorCode_t  Error  = ST_NO_ERROR;    RWBuffer_t     *Buffer = NULL;        assert (NULL != Buff);    assert (NULL != Device_p);    assert (NULL != Device_p->HALData);        Buffer = (RWBuffer_t*)Buff;        /* Normalise the data */        if (Size+Offset > DISK_SECTOR_SIZE)    {        Size -= Size+Offset-DISK_SECTOR_SIZE;    }        if (Offset < DISK_SECTOR_SIZE)    {        /* Load the data from disk */                /* If this sector is beyond EOF then it is as good as whats in memory */                if (EndOfFile) Buffer->Flags |= RWB_FLAG_IN_MEMORY;         if (!(Buffer->Flags & RWB_FLAG_IN_MEMORY))        {            Error = stavfs_HalRead (Device_p->HALData, &(Buffer->LBA), 1, (char*)Buffer->Buffer, Buffer->Flags & RWB_FLAG_STREAM);            Buffer->Flags |= RWB_FLAG_IN_MEMORY;        }         if (Error == ST_NO_ERROR)        {            memcpy(Buffer->Buffer+Offset, MemoryDestination, Size);            Buffer->Flags |= RWB_FLAG_MODIFIED;        }    }        return (Error);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -