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

📄 rtfiles.c

📁 MTK平台绝密核心代码之文件驱动,希望对大家有用
💻 C
📖 第 1 页 / 共 5 页
字号:
   }
}

/*-----------------------------------*/
static void INTERN FreeBuffer(RTFDevice * Dev)
// this is called only by UnlockDevice and GetBuffer
{
   if (Dev->DevData.B)
   {
      Dev->DevData.B->Flags &= ~B_INUSE;
      Dev->DevData.B = NULL;
   }
}

/*-----------------------------------*/
static void INTERN DiscardOtherBuffer(RTFBuffer * B)
{
#ifdef __FS_DEBUG__
   if (B->Flags & B_DIRTY)
      BufferStat.DirtyBuffers--;
#endif
/* Guarantee fixed disk access, Karen Hsu, 2005/05/19, ADD START */
   if (B->Flags & B_SINGLE)
      B->Flags = B_SINGLE;
   else
/* Guarantee fixed disk access, Karen Hsu, 2005/05/19, ADD END */
   B->Flags = 0;
   B->recoverable_flag = RTF_NORMAL_WRITE;
   ToTail(B);
}

/*-----------------------------------*/
static void INTERN DiscardBuffer(RTFDevice * Dev)
// this frees a buffer
{
#ifdef DEBUG
   if (Dev->DevData.B == NULL)
      RTFSYSErrorExit("Can't discard non-current buffer", 1);
#endif
   DiscardOtherBuffer(Dev->DevData.B);
   Dev->DevData.B = NULL;
}

/*-----------------------------------*/
static void INTERN AllocBuffers(void)
{
   RTFBuffer * B;
   UINT i;

   if (FirstBuffer)
      return;

/* Guarantee fixed disk access, Karen Hsu, 2005/05/19, ADD START */
#ifdef __FS_EMERGENT_NOR_BUFFER_SUPPORT__
   g_Emergent_NOR_Buffer.Flags |= B_SINGLE;
   g_Emergent_NOR_Buffer.recoverable_flag = RTF_NORMAL_WRITE;
   g_Emergent_NOR_Buffer.Data = g_Emergent_NOR_BufferData;
#endif

#ifdef __FS_EMERGENT_NAND_BUFFER_SUPPORT__
   g_Emergent_NAND_Buffer.Flags |= B_SINGLE;
   g_Emergent_NAND_Buffer.recoverable_flag = RTF_NORMAL_WRITE;
   g_Emergent_NAND_Buffer.Data = g_Emergent_NAND_BufferData;
#endif
/* Guarantee fixed disk access, Karen Hsu, 2005/05/19, ADD END */

   //if (gFS_Data.Version != RTFILE_VER)
      //RTFSYSErrorExit("gFS_Data version mismatch", 1);

#ifdef __FS_DEBUG__
   BufferStat.TotalBuffers = FS_MAX_BUFFERS;
#endif

   if ((RTF_MIN_BUFFER_SIZE > RTF_MAX_BUFFER_SIZE) ||
       !PowerTwo(RTF_MIN_BUFFER_SIZE))
      RTFSYSErrorExit("Invalid RTF_BUFFER_SIZE", 1);

   if (FS_MAX_FILES > FMAX)
      RTFSYSErrorExit("Too many file handles", 1);

   if (((DWORD) gFS_Data.BufferTable) % 4)
      RTFSYSErrorExit("Cache buffer not properly aligned", 1);

   for (i=0; i<FS_MAX_BUFFERS; i++)
   {
      B = gFS_Data.BufferTable + i;
      B->Num = i;
      B->recoverable_flag = RTF_NORMAL_WRITE;
      B->Data = gFS_Data.BufferData + (i*RTF_MIN_BUFFER_SIZE);
      B->Next = B + 1;
      B->Prev = B - 1;
   }

   FirstBuffer = gFS_Data.BufferTable;

   FirstBuffer->Prev = FirstBuffer + FS_MAX_BUFFERS - 1;
   FirstBuffer->Prev->Next = FirstBuffer;
}

#ifdef __FS_DEBUG__

/*-----------------------------------*/
void RTFAPI RTFBufferInfo(RTFBufferStatistic * BufferInfo)
{
   RTFBuffer * B;

#ifdef DEBUG
   UINT Test = 0;
#endif

   if (FirstBuffer == 0)
      AllocBuffers();

   *BufferInfo = BufferStat;

   BufferInfo->CacheHits = BufferInfo->PhysicalBufferReads ? 100 * (BufferInfo->CachedBufferReads) / (BufferInfo->PhysicalBufferReads + BufferInfo->CachedBufferReads) : 0;

   BufferInfo->ValidBuffers = 0;

   B = FirstBuffer;
   do
   {
      if (B->Flags & B_VALID)
         BufferInfo->ValidBuffers++;
#ifdef DEBUG
      if (B->Flags & B_DIRTY)
         Test++;
#endif
      B = B->Next;
   } while (B != FirstBuffer);
#ifdef DEBUG
   if (Test != BufferStat.DirtyBuffers)
      RTFSYSErrorExit("DirtyBuffers incorrect", 0);
#endif
}

#endif

/*-----------------------------------*/
static void INTERN ReadBuffer(RTFBuffer * B)
{
   int fs_block_type = FS_BLOCK_ENUM; /* Fix multi-access bug, Karen Hsu, 2004/07/08, ADD */

   XTRY
      case XCODE:
         B->Flags |= B_BUSY;
         ReadSectors(B->Dev, B->Data, B->Sector, 1, 0);

         // set the recoverable_flag according to the TLS setting
         fs_block_type = (int)RTFSYSGetTLS(TLSBlockIndex);
         if (fs_block_type == FS_BLOCK_PROTECTION_ENUM)
           B->recoverable_flag = RTF_RECOVERABLE_WRITE;
         else
           B->recoverable_flag = RTF_NORMAL_WRITE;

#ifdef __FS_DEBUG__
         BufferStat.PhysicalBufferReads++;
#endif
         B->Flags |= B_VALID;
         break;
      default:
         ToTail(B);
         B->Flags &= ~B_INUSE;
         break;
      case XFINALLY:
         B->Flags &= ~B_BUSY;
         break;
   XENDX
}

/*-----------------------------------*/
static void INTERN WriteBuffer(RTFBuffer * B)
{
#ifdef DEBUG
   if (B->Flags != (B_INUSE | B_VALID | B_DIRTY))
      RTFSYSErrorExit("Attempt to write none inuse/valid/dirty buffer", 0);
#endif
   XTRY
      case XCODE:
         B->Flags |= B_BUSY;

         // recoverable_flag indicates if it has to use recoverablewritesector or not
         if (B->recoverable_flag == RTF_RECOVERABLE_WRITE)
           WriteSectors(B->Dev, B->Data, B->Sector, 1, 0, RTF_RECOVERABLE_WRITE);
         else
           WriteSectors(B->Dev, B->Data, B->Sector, 1, 0, RTF_NORMAL_WRITE);
          // clear the recoverable_flag
         B->recoverable_flag = RTF_NORMAL_WRITE;

         B->Flags &= ~B_DIRTY;
#ifdef __FS_DEBUG__
         BufferStat.PhysicalBufferWrites++;
         BufferStat.AsynchBufferFlushs += (B->FirstDirtyTime != B->Dev->DevData.AccessCount);
         BufferStat.DirtyBuffers--;
#endif
         // check if this is a FAT sector and we have to
         // take care of other FATs
         // We will ignore any errors here, but we do want
         // critical errors.

         {
            int i, FATs;

            if ((B->FATSectorInfo) && ((B->Dev->DeviceFlags & RTF_DEVICE_SINGLE_FAT) == 0))
               FATs = B->FATSectorInfo->FATCount;
            else
               FATs = 1;

            if (FATs > 1)
            {
               B->Flags = B_VALID | B_INUSE | B_BUSY;
               for (i=1; i<FATs; i++)
               {
                  WriteSectors(B->Dev, B->Data, B->Sector + i * B->FATSectorInfo->SectorsPerFAT, 1, NO_RAISE, RTF_NORMAL_WRITE);
#ifdef __FS_DEBUG__
                  BufferStat.PhysicalBufferWrites++;
                  BufferStat.AsynchBufferFlushs += B->FirstDirtyTime != B->Dev->DevData.AccessCount;
#endif
               }
               B->Flags = B_VALID | B_INUSE;
            }
         }
         break;
      default: // only the first FAT can raise exceptions
         B->Flags &= ~B_INUSE;
         break;
      case XFINALLY:
         B->Flags &= ~B_BUSY;
         break;
   XENDX
}

/*-----------------------------------*/
static void * INTERN SearchBuffer(RTFDevice * Dev, RTFSector Sector)
{
   RTFBuffer * B;    // selected buffer

   #ifdef DEBUG
   if (!RTFSYSOwnMutex(RTFLock))
      RTFSYSErrorExit("Attempt access buffers without locking", 1);
   #endif

   if (Dev->DevData.B && (Dev->DevData.B->Sector == Sector))
      return Dev->DevData.B->Data;

/* Guarantee fixed disk access, Karen Hsu, 2005/05/19, ADD START */
#ifdef __FS_EMERGENT_NOR_BUFFER_SUPPORT__
   B = &g_Emergent_NOR_Buffer;
   if (B->Flags & B_VALID)
   {
      if ((B->Sector == Sector) && (B->Dev == Dev))
      {
         B->Flags |= B_INUSE;
         FreeBuffer(Dev);
         Dev->DevData.B = B;
         return B->Data;
      }
   }
#endif

#ifdef __FS_EMERGENT_NAND_BUFFER_SUPPORT__
   B = &g_Emergent_NAND_Buffer;
   if (B->Flags & B_VALID)
   {
      if ((B->Sector == Sector) && (B->Dev == Dev))
      {
         B->Flags |= B_INUSE;
         FreeBuffer(Dev);
         Dev->DevData.B = B;
         return B->Data;
      }
   }
#endif
/* Guarantee fixed disk access, Karen Hsu, 2005/05/19, ADD END */

   // search forward for the sector in question

   B = FirstBuffer;
   do
   {
      if (B->Flags & B_VALID)
      {
         if ((B->Sector == Sector) && (B->Dev == Dev))
         {
            #ifdef DEBUG
            if (B->Flags & (B_INUSE | B_BUSY))  // double allocation
               RTFSYSErrorExit("Buffer allocated twice", 0);
            #endif
            UpFront(B);
            B->Flags |= B_INUSE;
            FreeBuffer(Dev);
            Dev->DevData.B = B;
            return B->Data;
         }
      }
      else
         return NULL;
      B = B->Next;
   } while (B != FirstBuffer);
   return NULL;
}

/*-----------------------------------*/
static void * INTERN GetBuffer(RTFDevice * Dev, RTFSector Sector, UINT Flags)
{
   RTFBuffer * B;    // selected buffer

   #ifdef DEBUG
   if (!RTFSYSOwnMutex(RTFLock))
      RTFSYSErrorExit("Attempt access buffers without locking", 1);
   if (Dev->DevData.AltBuffer)
      RTFSYSErrorExit("AltBuffer not freed", 1);
   #endif

   if ((Flags & ALT_BUFFER) == 0)
      if (Dev->DevData.B)
	  {
         if (Dev->DevData.B->Sector == Sector)
            return Dev->DevData.B->Data;
         else
            FreeBuffer(Dev);
	  }
   // search forward for the sector in question or an invalid (free) buffer

   B = FirstBuffer;
   do
   {
      if (B->Flags != 0)
      {
         if ((B->Sector == Sector) && (B->Dev == Dev))
         {
            #ifdef DEBUG
            if (B->Flags & (B_INUSE | B_BUSY))  // double allocation
               RTFSYSErrorExit("Buffer allocated twice", 0);
            if ((B->Flags & B_VALID) == 0)
               RTFSYSErrorExit("allocating invalid buffer", 0);
            #endif
#ifdef __FS_DEBUG__
            BufferStat.CachedBufferReads++;
#endif
            B->Flags |= B_INUSE;
            goto SaveAndExit;
         }
      }
      else // not allocated buffers follow the first unallocated buffer
      {
         #ifdef DEBUG
         {
            RTFBuffer * B1 = B;
            do
            {
               if (B1->Flags != 0)
                  RTFSYSErrorExit("Buffer with flags after last valid buffer", 0);
               B1 = B1->Next;
            }
            while (B1 != FirstBuffer);
         }
         #endif
         goto ReadAndExit;
      }
      B = B->Next;
   } while (B != FirstBuffer);

#ifdef __FS_DEBUG__
   BufferStat.BuffersDiscarded++; // we have to discard one
#endif
   // now search backwards (oldest first) for a buffer to discard:
   // for any buffer on the same device
   // or for a clean buffer

   B = FirstBuffer->Prev;
   do
   {
      if (((B->Flags & B_INUSE) == 0) &&                     // it's not in use and
          ((B->Dev == Dev) ||                                //  it's on this device or
           ((B->Flags & B_DIRTY) == 0)))                     //  it's not dirty
      {
         #ifdef DEBUG
         if (B->Flags & B_BUSY)
            RTFSYSErrorExit("can't discard a busy buffer", 0);
         #endif
         if (B->Flags & B_DIRTY)
         {
            #ifdef DEBUG
            if (B->Dev != Dev)
               RTFSYSErrorExit("can'd discard foreighn dirty buffer", 0);
            #endif
            B->Flags        |= B_INUSE;
            WriteBuffer(B);
         }
         goto ReadAndExit;
      }
      B = B->Prev;
   } while (B != FirstBuffer->Prev);

/* Guarantee fixed disk access, Karen Hsu, 2005/05/19, ADD START */
#ifdef __FS_EMERGENT_NOR_BUFFER_SUPPORT__
   if(Dev->DeviceFlags & MT_DEVICE_NOR_FLASH)
   {
      B = &g_Emergent_NOR_Buffer;
      B->Flags |= B_INUSE;
      if ((B->Sector == Sector) && (B->Dev == Dev))
         goto SaveAndExit;
      else
         goto ReadAndExit;
   }
#endif

#ifdef __FS_EMERGENT_NAND_BUFFER_SUPPORT__
   if(Dev->DeviceFlags & MT_DEVICE_NAND_FLASH)
   {
      B = &g_Emergent_NAND_Buffer;
      B->Flags |= B_INUSE;
      if ((B->Sector == Sector) && (B->Dev == Dev))
         goto SaveAndExit;
      else
         goto ReadAndExit;
   }
#endif
/* Guarantee fixed disk access, Karen Hsu, 2005/05/19, ADD END */

#ifdef __FS_TRACE_SUPPORT__
   if(g_TraceFlag & MT_TRACE_ERROR)
   {
      if(Dev->DeviceFlags & MT_DEVICE_NOR_FLASH)
         kal_sprintf(TraceTmpBuf, "Dev:NOR, Sector: %d", Sector);
      else if(Dev->DeviceFlags & MT_DEVICE_NAND_FLASH)
         kal_sprintf(TraceTmpBuf, "Dev:NAND, Sector: %d", Sector);
      else
         kal_sprintf(TraceTmpBuf, "Dev:Card, Sector: %d", Sector);
      memset(TraceTmpBuf+strlen((char *)TraceTmpBuf)+1, 0, 2);
      MTTraceFS((DWORD)kal_get_current_thread_ID(), 1, __LINE__, RTF_OUT_OF_BUFFERS, NULL, (BYTE *)TraceTmpBuf);
   }
#endif
   XRAISE(RTF_OUT_OF_BUFFERS);

ReadAndExit:
   B->Dev           = Dev;
   B->Sector        = Sector;
   B->FATSectorInfo = NULL;
/* Guarantee fixed disk access, Karen Hsu, 2005/05/19, ADD START */
   if (B->Flags & B_SINGLE)
   {
      B->Flags = (B_SINGLE | B_INUSE);
   }
   else
/* Guarantee fixed disk access, Karen Hsu, 2005/05/19, ADD END */
   B->Flags         = B_INUSE;
   B->recoverable_flag = RTF_NORMAL_WRITE;

   if (Flags & NO_LOAD)
      B->Flags |= B_VALID;
   else
      ReadBuffer(B);

SaveAndExit:
   UpFront(B);
   if (Flags & ALT_BUFFER)
      Dev->DevData.AltBuffer = B;
   else
      Dev->DevData.B = B;
   return B->Data;
}

/*-----------------------------------*/
#ifdef __FS_DEBUG__
static void INTERN FlushOldest(RTFDevice * Dev)
{

⌨️ 快捷键说明

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