Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencache.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
1.7.6.1
|