ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

cache.c
Go to the documentation of this file.
00001 /*
00002  *  FreeLoader
00003  *  Copyright (C) 1998-2003  Brian Palmer  <brianp@sginet.com>
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License along
00016  *  with this program; if not, write to the Free Software Foundation, Inc.,
00017  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00018  */
00019 
00020 #include <freeldr.h>
00021 #include <debug.h>
00022 
00023 DBG_DEFAULT_CHANNEL(CACHE);
00024 
00026 //
00027 // Internal data
00028 //
00030 CACHE_DRIVE     CacheManagerDrive;
00031 BOOLEAN         CacheManagerInitialized = FALSE;
00032 BOOLEAN         CacheManagerDataInvalid = FALSE;
00033 ULONG           CacheBlockCount = 0;
00034 SIZE_T          CacheSizeLimit = 0;
00035 SIZE_T          CacheSizeCurrent = 0;
00036 
00037 BOOLEAN CacheInitializeDrive(UCHAR DriveNumber)
00038 {
00039     PCACHE_BLOCK    NextCacheBlock;
00040     GEOMETRY    DriveGeometry;
00041 
00042     // If we already have a cache for this drive then
00043     // by all means lets keep it, unless it is a removable
00044     // drive, in which case we'll invalidate the cache
00045     if ((CacheManagerInitialized == TRUE) &&
00046         (DriveNumber == CacheManagerDrive.DriveNumber) &&
00047         (DriveNumber >= 0x80) &&
00048         (CacheManagerDataInvalid != TRUE))
00049     {
00050         return TRUE;
00051     }
00052 
00053     CacheManagerDataInvalid = FALSE;
00054 
00055     //
00056     // If we have already been initialized then free
00057     // the old data
00058     //
00059     if (CacheManagerInitialized)
00060     {
00061         CacheManagerInitialized = FALSE;
00062 
00063         TRACE("CacheBlockCount: %d\n", CacheBlockCount);
00064         TRACE("CacheSizeLimit: %d\n", CacheSizeLimit);
00065         TRACE("CacheSizeCurrent: %d\n", CacheSizeCurrent);
00066         //
00067         // Loop through and free the cache blocks
00068         //
00069         while (!IsListEmpty(&CacheManagerDrive.CacheBlockHead))
00070         {
00071             NextCacheBlock = CONTAINING_RECORD(RemoveHeadList(&CacheManagerDrive.CacheBlockHead),
00072                                                CACHE_BLOCK,
00073                                                ListEntry);
00074 
00075             MmHeapFree(NextCacheBlock->BlockData);
00076             MmHeapFree(NextCacheBlock);
00077         }
00078     }
00079 
00080     // Initialize the structure
00081     RtlZeroMemory(&CacheManagerDrive, sizeof(CACHE_DRIVE));
00082     InitializeListHead(&CacheManagerDrive.CacheBlockHead);
00083     CacheManagerDrive.DriveNumber = DriveNumber;
00084     if (!MachDiskGetDriveGeometry(DriveNumber, &DriveGeometry))
00085     {
00086         return FALSE;
00087     }
00088     CacheManagerDrive.BytesPerSector = DriveGeometry.BytesPerSector;
00089 
00090     // Get the number of sectors in each cache block
00091     CacheManagerDrive.BlockSize = MachDiskGetCacheableBlockCount(DriveNumber);
00092 
00093     CacheBlockCount = 0;
00094     CacheSizeLimit = TotalPagesInLookupTable / 8 * MM_PAGE_SIZE;
00095     CacheSizeCurrent = 0;
00096     if (CacheSizeLimit < (64 * 1024))
00097     {
00098         CacheSizeLimit = (64 * 1024);
00099     }
00100 
00101     CacheManagerInitialized = TRUE;
00102 
00103     TRACE("Initializing BIOS drive 0x%x.\n", DriveNumber);
00104     TRACE("BytesPerSector: %d.\n", CacheManagerDrive.BytesPerSector);
00105     TRACE("BlockSize: %d.\n", CacheManagerDrive.BlockSize);
00106     TRACE("CacheSizeLimit: %d.\n", CacheSizeLimit);
00107 
00108     return TRUE;
00109 }
00110 
00111 VOID CacheInvalidateCacheData(VOID)
00112 {
00113     CacheManagerDataInvalid = TRUE;
00114 }
00115 
00116 BOOLEAN CacheReadDiskSectors(UCHAR DiskNumber, ULONGLONG StartSector, ULONG SectorCount, PVOID Buffer)
00117 {
00118     PCACHE_BLOCK    CacheBlock;
00119     ULONG               StartBlock;
00120     ULONG               SectorOffsetInStartBlock;
00121     ULONG               CopyLengthInStartBlock;
00122     ULONG               EndBlock;
00123     ULONG               SectorOffsetInEndBlock;
00124     ULONG               BlockCount;
00125     ULONG               Idx;
00126 
00127     TRACE("CacheReadDiskSectors() DiskNumber: 0x%x StartSector: %I64d SectorCount: %d Buffer: 0x%x\n", DiskNumber, StartSector, SectorCount, Buffer);
00128 
00129     // If we aren't initialized yet then they can't do this
00130     if (CacheManagerInitialized == FALSE)
00131     {
00132         return FALSE;
00133     }
00134 
00135     //
00136     // Caculate which blocks we must cache
00137     //
00138     StartBlock = (ULONG)(StartSector / CacheManagerDrive.BlockSize);
00139     SectorOffsetInStartBlock = (ULONG)(StartSector % CacheManagerDrive.BlockSize);
00140     CopyLengthInStartBlock = (ULONG)((SectorCount > (CacheManagerDrive.BlockSize - SectorOffsetInStartBlock)) ? (CacheManagerDrive.BlockSize - SectorOffsetInStartBlock) : SectorCount);
00141     EndBlock = (ULONG)((StartSector + (SectorCount - 1)) / CacheManagerDrive.BlockSize);
00142     SectorOffsetInEndBlock = (ULONG)(1 + (StartSector + (SectorCount - 1)) % CacheManagerDrive.BlockSize);
00143     BlockCount = (EndBlock - StartBlock) + 1;
00144     TRACE("StartBlock: %d SectorOffsetInStartBlock: %d CopyLengthInStartBlock: %d EndBlock: %d SectorOffsetInEndBlock: %d BlockCount: %d\n", StartBlock, SectorOffsetInStartBlock, CopyLengthInStartBlock, EndBlock, SectorOffsetInEndBlock, BlockCount);
00145 
00146     //
00147     // Read the first block into the buffer
00148     //
00149     if (BlockCount > 0)
00150     {
00151         //
00152         // Get cache block pointer (this forces the disk sectors into the cache memory)
00153         //
00154         CacheBlock = CacheInternalGetBlockPointer(&CacheManagerDrive, StartBlock);
00155         if (CacheBlock == NULL)
00156         {
00157             return FALSE;
00158         }
00159 
00160         //
00161         // Copy the portion requested into the buffer
00162         //
00163         RtlCopyMemory(Buffer,
00164             (PVOID)((ULONG_PTR)CacheBlock->BlockData + (SectorOffsetInStartBlock * CacheManagerDrive.BytesPerSector)),
00165             (CopyLengthInStartBlock * CacheManagerDrive.BytesPerSector));
00166         TRACE("1 - RtlCopyMemory(0x%x, 0x%x, %d)\n", Buffer, ((ULONG_PTR)CacheBlock->BlockData + (SectorOffsetInStartBlock * CacheManagerDrive.BytesPerSector)), (CopyLengthInStartBlock * CacheManagerDrive.BytesPerSector));
00167 
00168         //
00169         // Update the buffer address
00170         //
00171         Buffer = (PVOID)((ULONG_PTR)Buffer + (CopyLengthInStartBlock * CacheManagerDrive.BytesPerSector));
00172 
00173         //
00174         // Update the block count
00175         //
00176         BlockCount--;
00177     }
00178 
00179     //
00180     // Loop through the middle blocks and read them into the buffer
00181     //
00182     for (Idx=StartBlock+1; BlockCount>1; Idx++)
00183     {
00184         //
00185         // Get cache block pointer (this forces the disk sectors into the cache memory)
00186         //
00187         CacheBlock = CacheInternalGetBlockPointer(&CacheManagerDrive, Idx);
00188         if (CacheBlock == NULL)
00189         {
00190             return FALSE;
00191         }
00192 
00193         //
00194         // Copy the portion requested into the buffer
00195         //
00196         RtlCopyMemory(Buffer,
00197             CacheBlock->BlockData,
00198             CacheManagerDrive.BlockSize * CacheManagerDrive.BytesPerSector);
00199         TRACE("2 - RtlCopyMemory(0x%x, 0x%x, %d)\n", Buffer, CacheBlock->BlockData, CacheManagerDrive.BlockSize * CacheManagerDrive.BytesPerSector);
00200 
00201         //
00202         // Update the buffer address
00203         //
00204         Buffer = (PVOID)((ULONG_PTR)Buffer + (CacheManagerDrive.BlockSize * CacheManagerDrive.BytesPerSector));
00205 
00206         //
00207         // Update the block count
00208         //
00209         BlockCount--;
00210     }
00211 
00212     //
00213     // Read the last block into the buffer
00214     //
00215     if (BlockCount > 0)
00216     {
00217         //
00218         // Get cache block pointer (this forces the disk sectors into the cache memory)
00219         //
00220         CacheBlock = CacheInternalGetBlockPointer(&CacheManagerDrive, EndBlock);
00221         if (CacheBlock == NULL)
00222         {
00223             return FALSE;
00224         }
00225 
00226         //
00227         // Copy the portion requested into the buffer
00228         //
00229         RtlCopyMemory(Buffer,
00230             CacheBlock->BlockData,
00231             SectorOffsetInEndBlock * CacheManagerDrive.BytesPerSector);
00232         TRACE("3 - RtlCopyMemory(0x%x, 0x%x, %d)\n", Buffer, CacheBlock->BlockData, SectorOffsetInEndBlock * CacheManagerDrive.BytesPerSector);
00233 
00234         //
00235         // Update the buffer address
00236         //
00237         Buffer = (PVOID)((ULONG_PTR)Buffer + (SectorOffsetInEndBlock * CacheManagerDrive.BytesPerSector));
00238 
00239         //
00240         // Update the block count
00241         //
00242         BlockCount--;
00243     }
00244 
00245     return TRUE;
00246 }
00247 
00248 #if 0
00249 BOOLEAN CacheForceDiskSectorsIntoCache(UCHAR DiskNumber, ULONGLONG StartSector, ULONG SectorCount)
00250 {
00251     PCACHE_BLOCK    CacheBlock;
00252     ULONG               StartBlock;
00253     ULONG               EndBlock;
00254     ULONG               BlockCount;
00255     ULONG               Idx;
00256 
00257     TRACE("CacheForceDiskSectorsIntoCache() DiskNumber: 0x%x StartSector: %d SectorCount: %d\n", DiskNumber, StartSector, SectorCount);
00258 
00259     // If we aren't initialized yet then they can't do this
00260     if (CacheManagerInitialized == FALSE)
00261     {
00262         return FALSE;
00263     }
00264 
00265     //
00266     // Caculate which blocks we must cache
00267     //
00268     StartBlock = StartSector / CacheManagerDrive.BlockSize;
00269     EndBlock = (StartSector + SectorCount) / CacheManagerDrive.BlockSize;
00270     BlockCount = (EndBlock - StartBlock) + 1;
00271 
00272     //
00273     // Loop through and cache them
00274     //
00275     for (Idx=StartBlock; Idx<(StartBlock+BlockCount); Idx++)
00276     {
00277         //
00278         // Get cache block pointer (this forces the disk sectors into the cache memory)
00279         //
00280         CacheBlock = CacheInternalGetBlockPointer(&CacheManagerDrive, Idx);
00281         if (CacheBlock == NULL)
00282         {
00283             return FALSE;
00284         }
00285 
00286         //
00287         // Lock the sectors into the cache
00288         //
00289         CacheBlock->LockedInCache = TRUE;
00290     }
00291 
00292     return TRUE;
00293 }
00294 #endif
00295 
00296 BOOLEAN CacheReleaseMemory(ULONG MinimumAmountToRelease)
00297 {
00298     ULONG               AmountReleased;
00299 
00300     TRACE("CacheReleaseMemory() MinimumAmountToRelease = %d\n", MinimumAmountToRelease);
00301 
00302     // If we aren't initialized yet then they can't do this
00303     if (CacheManagerInitialized == FALSE)
00304     {
00305         return FALSE;
00306     }
00307 
00308     // Loop through and try to free the requested amount of memory
00309     for (AmountReleased=0; AmountReleased<MinimumAmountToRelease; )
00310     {
00311         // Try to free a block
00312         // If this fails then break out of the loop
00313         if (!CacheInternalFreeBlock(&CacheManagerDrive))
00314         {
00315             break;
00316         }
00317 
00318         // It succeeded so increment the amount of memory we have freed
00319         AmountReleased += CacheManagerDrive.BlockSize * CacheManagerDrive.BytesPerSector;
00320     }
00321 
00322     // Return status
00323     return (AmountReleased >= MinimumAmountToRelease);
00324 }

Generated on Sat May 26 2012 04:16:05 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.