ReactOS  0.4.14-dev-390-g34947ad
cache.c
Go to the documentation of this file.
1 /*
2  * FreeLoader
3  * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #include <freeldr.h>
21 
22 #include <debug.h>
23 DBG_DEFAULT_CHANNEL(CACHE);
24 
26 //
27 // Internal data
28 //
36 
38 {
39  PCACHE_BLOCK NextCacheBlock;
40  GEOMETRY DriveGeometry;
41 
42  // If we already have a cache for this drive then
43  // by all means lets keep it, unless it is a removable
44  // drive, in which case we'll invalidate the cache
46  (DriveNumber == CacheManagerDrive.DriveNumber) &&
47  (DriveNumber >= 0x80) &&
49  {
50  return TRUE;
51  }
52 
54 
55  //
56  // If we have already been initialized then free
57  // the old data
58  //
60  {
62 
63  TRACE("CacheBlockCount: %d\n", CacheBlockCount);
64  TRACE("CacheSizeLimit: %d\n", CacheSizeLimit);
65  TRACE("CacheSizeCurrent: %d\n", CacheSizeCurrent);
66  //
67  // Loop through and free the cache blocks
68  //
70  {
73  ListEntry);
74 
75  FrLdrTempFree(NextCacheBlock->BlockData, TAG_CACHE_DATA);
76  FrLdrTempFree(NextCacheBlock, TAG_CACHE_BLOCK);
77  }
78  }
79 
80  // Initialize the structure
83  CacheManagerDrive.DriveNumber = DriveNumber;
84  if (!MachDiskGetDriveGeometry(DriveNumber, &DriveGeometry))
85  {
86  return FALSE;
87  }
89 
90  // Get the number of sectors in each cache block
92 
93  CacheBlockCount = 0;
94  CacheSizeCurrent = 0;
95  CacheSizeLimit = TotalPagesInLookupTable / 8 * MM_PAGE_SIZE;
97 
99 
100  TRACE("Initializing BIOS drive 0x%x.\n", DriveNumber);
101  TRACE("BytesPerSector: %d.\n", CacheManagerDrive.BytesPerSector);
102  TRACE("BlockSize: %d.\n", CacheManagerDrive.BlockSize);
103  TRACE("CacheSizeLimit: %d.\n", CacheSizeLimit);
104 
105  return TRUE;
106 }
107 
109 {
111 }
112 
114 {
115  PCACHE_BLOCK CacheBlock;
116  ULONG StartBlock;
117  ULONG SectorOffsetInStartBlock;
118  ULONG CopyLengthInStartBlock;
119  ULONG EndBlock;
120  ULONG SectorOffsetInEndBlock;
121  ULONG BlockCount;
122  ULONG Idx;
123 
124  TRACE("CacheReadDiskSectors() DiskNumber: 0x%x StartSector: %I64d SectorCount: %d Buffer: 0x%x\n", DiskNumber, StartSector, SectorCount, Buffer);
125 
126  // If we aren't initialized yet then they can't do this
128  {
129  return FALSE;
130  }
131 
132  //
133  // Calculate which blocks we must cache
134  //
135  StartBlock = (ULONG)(StartSector / CacheManagerDrive.BlockSize);
136  SectorOffsetInStartBlock = (ULONG)(StartSector % CacheManagerDrive.BlockSize);
137  CopyLengthInStartBlock = (ULONG)((SectorCount > (CacheManagerDrive.BlockSize - SectorOffsetInStartBlock)) ? (CacheManagerDrive.BlockSize - SectorOffsetInStartBlock) : SectorCount);
138  EndBlock = (ULONG)((StartSector + (SectorCount - 1)) / CacheManagerDrive.BlockSize);
139  SectorOffsetInEndBlock = (ULONG)(1 + (StartSector + (SectorCount - 1)) % CacheManagerDrive.BlockSize);
140  BlockCount = (EndBlock - StartBlock) + 1;
141  TRACE("StartBlock: %d SectorOffsetInStartBlock: %d CopyLengthInStartBlock: %d EndBlock: %d SectorOffsetInEndBlock: %d BlockCount: %d\n", StartBlock, SectorOffsetInStartBlock, CopyLengthInStartBlock, EndBlock, SectorOffsetInEndBlock, BlockCount);
142 
143  //
144  // Read the first block into the buffer
145  //
146  if (BlockCount > 0)
147  {
148  //
149  // Get cache block pointer (this forces the disk sectors into the cache memory)
150  //
151  CacheBlock = CacheInternalGetBlockPointer(&CacheManagerDrive, StartBlock);
152  if (CacheBlock == NULL)
153  {
154  return FALSE;
155  }
156 
157  //
158  // Copy the portion requested into the buffer
159  //
161  (PVOID)((ULONG_PTR)CacheBlock->BlockData + (SectorOffsetInStartBlock * CacheManagerDrive.BytesPerSector)),
162  (CopyLengthInStartBlock * CacheManagerDrive.BytesPerSector));
163  TRACE("1 - RtlCopyMemory(0x%x, 0x%x, %d)\n", Buffer, ((ULONG_PTR)CacheBlock->BlockData + (SectorOffsetInStartBlock * CacheManagerDrive.BytesPerSector)), (CopyLengthInStartBlock * CacheManagerDrive.BytesPerSector));
164 
165  //
166  // Update the buffer address
167  //
168  Buffer = (PVOID)((ULONG_PTR)Buffer + (CopyLengthInStartBlock * CacheManagerDrive.BytesPerSector));
169 
170  //
171  // Update the block count
172  //
173  BlockCount--;
174  }
175 
176  //
177  // Loop through the middle blocks and read them into the buffer
178  //
179  for (Idx=StartBlock+1; BlockCount>1; Idx++)
180  {
181  //
182  // Get cache block pointer (this forces the disk sectors into the cache memory)
183  //
185  if (CacheBlock == NULL)
186  {
187  return FALSE;
188  }
189 
190  //
191  // Copy the portion requested into the buffer
192  //
194  CacheBlock->BlockData,
196  TRACE("2 - RtlCopyMemory(0x%x, 0x%x, %d)\n", Buffer, CacheBlock->BlockData, CacheManagerDrive.BlockSize * CacheManagerDrive.BytesPerSector);
197 
198  //
199  // Update the buffer address
200  //
202 
203  //
204  // Update the block count
205  //
206  BlockCount--;
207  }
208 
209  //
210  // Read the last block into the buffer
211  //
212  if (BlockCount > 0)
213  {
214  //
215  // Get cache block pointer (this forces the disk sectors into the cache memory)
216  //
217  CacheBlock = CacheInternalGetBlockPointer(&CacheManagerDrive, EndBlock);
218  if (CacheBlock == NULL)
219  {
220  return FALSE;
221  }
222 
223  //
224  // Copy the portion requested into the buffer
225  //
227  CacheBlock->BlockData,
228  SectorOffsetInEndBlock * CacheManagerDrive.BytesPerSector);
229  TRACE("3 - RtlCopyMemory(0x%x, 0x%x, %d)\n", Buffer, CacheBlock->BlockData, SectorOffsetInEndBlock * CacheManagerDrive.BytesPerSector);
230 
231  //
232  // Update the buffer address
233  //
234  Buffer = (PVOID)((ULONG_PTR)Buffer + (SectorOffsetInEndBlock * CacheManagerDrive.BytesPerSector));
235 
236  //
237  // Update the block count
238  //
239  BlockCount--;
240  }
241 
242  return TRUE;
243 }
244 
245 #if 0
247 {
248  PCACHE_BLOCK CacheBlock;
249  ULONG StartBlock;
250  ULONG EndBlock;
251  ULONG BlockCount;
252  ULONG Idx;
253 
254  TRACE("CacheForceDiskSectorsIntoCache() DiskNumber: 0x%x StartSector: %d SectorCount: %d\n", DiskNumber, StartSector, SectorCount);
255 
256  // If we aren't initialized yet then they can't do this
258  {
259  return FALSE;
260  }
261 
262  //
263  // Calculate which blocks we must cache
264  //
265  StartBlock = StartSector / CacheManagerDrive.BlockSize;
266  EndBlock = (StartSector + SectorCount) / CacheManagerDrive.BlockSize;
267  BlockCount = (EndBlock - StartBlock) + 1;
268 
269  //
270  // Loop through and cache them
271  //
272  for (Idx=StartBlock; Idx<(StartBlock+BlockCount); Idx++)
273  {
274  //
275  // Get cache block pointer (this forces the disk sectors into the cache memory)
276  //
278  if (CacheBlock == NULL)
279  {
280  return FALSE;
281  }
282 
283  //
284  // Lock the sectors into the cache
285  //
286  CacheBlock->LockedInCache = TRUE;
287  }
288 
289  return TRUE;
290 }
291 #endif
292 
293 BOOLEAN CacheReleaseMemory(ULONG MinimumAmountToRelease)
294 {
295  ULONG AmountReleased;
296 
297  TRACE("CacheReleaseMemory() MinimumAmountToRelease = %d\n", MinimumAmountToRelease);
298 
299  // If we aren't initialized yet then they can't do this
301  {
302  return FALSE;
303  }
304 
305  // Loop through and try to free the requested amount of memory
306  for (AmountReleased=0; AmountReleased<MinimumAmountToRelease; )
307  {
308  // Try to free a block
309  // If this fails then break out of the loop
311  {
312  break;
313  }
314 
315  // It succeeded so increment the amount of memory we have freed
317  }
318 
319  // Return status
320  return (AmountReleased >= MinimumAmountToRelease);
321 }
#define TAG_CACHE_BLOCK
Definition: cache.h:24
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
DBG_DEFAULT_CHANNEL(CACHE)
BOOLEAN CacheInitializeDrive(UCHAR DriveNumber)
Definition: cache.c:37
BOOLEAN CacheReadDiskSectors(UCHAR DiskNumber, ULONGLONG StartSector, ULONG SectorCount, PVOID Buffer)
Definition: cache.c:113
VOID CacheInvalidateCacheData(VOID)
Definition: cache.c:108
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
ULONG CacheBlockCount
Definition: cache.c:33
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define MachDiskGetCacheableBlockCount(Drive)
Definition: machine.h:130
SIZE_T CacheSizeCurrent
Definition: cache.c:35
BOOLEAN CacheForceDiskSectorsIntoCache(UCHAR DiskNumber, ULONGLONG StartSector, ULONG SectorCount)
CACHE_DRIVE CacheManagerDrive
Definition: cache.c:30
LIST_ENTRY CacheBlockHead
Definition: cache.h:60
#define TEMP_HEAP_SIZE
Definition: mm.h:123
PCACHE_BLOCK CacheInternalGetBlockPointer(PCACHE_DRIVE CacheDrive, ULONG BlockNumber)
Definition: blocklist.c:28
unsigned char BOOLEAN
SIZE_T CacheSizeLimit
Definition: cache.c:34
smooth NULL
Definition: ftsmooth.c:416
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
Definition: bufpool.h:45
void * PVOID
Definition: retypes.h:9
PFN_NUMBER TotalPagesInLookupTable
Definition: meminit.c:27
PVOID BlockData
Definition: cache.h:43
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define MachDiskGetDriveGeometry(Drive, Geom)
Definition: machine.h:128
BOOLEAN CacheInternalFreeBlock(PCACHE_DRIVE CacheDrive)
Definition: blocklist.c:142
#define TRACE(s)
Definition: solgame.cpp:4
ULONG BlockSize
Definition: cache.h:59
uint64_t ULONGLONG
Definition: typedefs.h:65
BOOLEAN CacheManagerInitialized
Definition: cache.c:31
UCHAR DriveNumber
Definition: cache.h:56
unsigned char UCHAR
Definition: xmlstorage.h:181
ULONG SectorCount
Definition: part_xbox.c:32
ULONG_PTR SIZE_T
Definition: typedefs.h:78
ULONG BytesPerSector
Definition: disk.h:29
BOOLEAN LockedInCache
Definition: cache.h:40
BOOLEAN CacheReleaseMemory(ULONG MinimumAmountToRelease)
Definition: cache.c:293
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
Definition: disk.h:24
#define TAG_CACHE_DATA
Definition: cache.h:23
#define min(a, b)
Definition: monoChain.cc:55
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
BOOLEAN CacheManagerDataInvalid
Definition: cache.c:32
ULONG BytesPerSector
Definition: cache.h:57
FORCEINLINE VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: mm.h:186