📄 intrface.c
字号:
AGPLOG(AGP_CRITICAL,
("AgpInterfaceCommitMemory - AgpMapMemory for Mdl %08lx in range %08lx failed %08lx\n",
NewMdl,
Range,
Status));
MmFreePagesFromMdl(NewMdl);
break;
}
Range->CommittedPages += RunLength;
//
// Add this MDL to our list of allocated MDLs for cleanup
// If we need to cleanup, we will also need to know the page offset
// so that we can unmap the memory. Stash that value in the ByteOffset
// field of the MDL (ByteOffset is always 0 for our MDLs)
//
NewMdl->ByteOffset = RunOffset;
NewMdl->Next = FirstMdl;
FirstMdl = NewMdl;
}
} while (RunLength > 0);
//
// Cleanup the MDLs. If the allocation failed, we need to
// unmap them and free the pages and the MDL itself. If the
// operation completed successfully, we just need to free the
// MDL.
//
while (FirstMdl) {
NewMdl = FirstMdl;
FirstMdl = NewMdl->Next;
if (!NT_SUCCESS(Status)) {
//
// Unmap the memory that was mapped. The ByteOffset field
// of the MDL is overloaded here to store the offset in pages
// into the range.
//
AgpUnMapMemory(AgpContext,
Range,
NewMdl->ByteCount / PAGE_SIZE,
NewMdl->ByteOffset);
NewMdl->ByteOffset = 0;
Range->CommittedPages -= NewMdl->ByteCount / PAGE_SIZE;
MmFreePagesFromMdl(NewMdl);
}
ExFreePool(NewMdl);
}
if (NT_SUCCESS(Status)) {
if (Mdl) {
//
// Get the MDL that describes the entire mapped range.
//
AgpGetMappedPages(AgpContext,
Range,
NumberOfPages,
OffsetInPages,
Mdl);
}
MemoryBase->QuadPart = Range->MemoryBase.QuadPart + OffsetInPages * PAGE_SIZE;
}
UNLOCK_MASTER(Extension);
return(Status);
}
NTSTATUS
AgpInterfaceFreeMemory(
IN PMASTER_EXTENSION Extension,
IN PVOID MapHandle,
IN ULONG NumberOfPages,
IN ULONG OffsetInPages
)
/*++
Routine Description:
Frees memory previously committed by AgpInterfaceCommitMemory
Arguments:
Extension - Supplies the device extension where physical address space should
be freed.
MapHandle - Supplies the mapping handle returned from AgpInterfaceReserveMemory
NumberOfPages - Supplies the number of pages to be freed.
OffsetInPages - Supplies the start of the range to be freed.
Return Value:
NTSTATUS
--*/
{
PAGP_RANGE Range = (PAGP_RANGE)MapHandle;
PVOID AgpContext;
NTSTATUS Status;
PMDL FreeMdl;
PAGED_CODE();
AgpContext = GET_AGP_CONTEXT_FROM_MASTER(Extension);
ASSERT(OffsetInPages < Range->NumberOfPages);
ASSERT(OffsetInPages + NumberOfPages <= Range->NumberOfPages);
//
// Make sure the supplied address is within the reserved range
//
if ((OffsetInPages >= Range->NumberOfPages) ||
(OffsetInPages + NumberOfPages > Range->NumberOfPages)) {
AGPLOG(AGP_WARNING,
("AgpInterfaceFreeMemory - Invalid free of %x pages at offset %x from range %I64X (%x pages)\n",
NumberOfPages,
OffsetInPages,
Range->MemoryBase.QuadPart,
Range->NumberOfPages));
return(STATUS_INVALID_PARAMETER);
}
//
// Allocate an MDL big enough to contain the pages to be unmapped.
//
FreeMdl = MmCreateMdl(NULL, 0, NumberOfPages * PAGE_SIZE);
if (FreeMdl == NULL) {
//
// This is kind of a sticky situation. We can't allocate the memory
// that we need to free up some memory! I guess we could have a small
// MDL on our stack and free things that way.
//
// John Vert (jvert) 11/11/1997
// implement this
//
// ISSUE-2000/09/06-enelson I've tried several AGP video cards, and
// not one of them uses AgpInterfaceCommit/FreeMemory, hence I'm
// loathe to change this at this point...
//
ASSERT(FreeMdl != NULL);
return(STATUS_INSUFFICIENT_RESOURCES);
}
LOCK_MASTER(Extension);
//
// Get the MDL that describes the entire mapped range
//
AgpGetMappedPages(AgpContext,
Range,
NumberOfPages,
OffsetInPages,
FreeMdl);
//
// Unmap the memory
//
Status = AgpUnMapMemory(AgpContext,
Range,
NumberOfPages,
OffsetInPages);
UNLOCK_MASTER(Extension);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_CRITICAL,
("AgpInterfaceFreeMemory - UnMapMemory for %x pages at %I64X failed %08lx\n",
NumberOfPages,
Range->MemoryBase.QuadPart + OffsetInPages * PAGE_SIZE,
Status));
} else {
//
// Free the pages
//
MmFreePagesFromMdl(FreeMdl);
ASSERT(Range->CommittedPages >= NumberOfPages);
Range->CommittedPages -= NumberOfPages;
}
//
// Free the MDL we allocated.
//
ExFreePool(FreeMdl);
return(Status);
}
NTSTATUS
AgpInterfaceGetMappedPages(
IN PMASTER_EXTENSION Extension,
IN PVOID MapHandle,
IN ULONG NumberOfPages,
IN ULONG OffsetInPages,
OUT PMDL Mdl
)
/*++
Routine Description:
Returns the list of physical pages mapped backing the specified range.
Arguments:
Extension - Supplies the device extension where physical address space should
be freed.
MapHandle - Supplies the mapping handle returned from AgpInterfaceReserveMemory
NumberOfPages - Supplies the number of pages to be returned
OffsetInPages - Supplies the start of the rangion
Return Value:
NTSTATUS
--*/
{
PAGP_RANGE Range = (PAGP_RANGE)MapHandle;
PVOID AgpContext;
NTSTATUS Status;
PAGED_CODE();
AgpContext = GET_AGP_CONTEXT_FROM_MASTER(Extension);
ASSERT(NumberOfPages <= Range->NumberOfPages);
ASSERT(NumberOfPages > 0);
ASSERT(OffsetInPages < Range->NumberOfPages);
ASSERT(OffsetInPages + NumberOfPages <= Range->NumberOfPages);
ASSERT(Mdl->ByteCount == PAGE_SIZE * NumberOfPages);
//
// Make sure the supplied address is within the reserved range
//
if ((OffsetInPages >= Range->NumberOfPages) ||
(OffsetInPages + NumberOfPages > Range->NumberOfPages)) {
AGPLOG(AGP_WARNING,
("AgpInterfaceGetMappedPages - Invalid 'get' of %x pages at offset %x from range %I64X (%x pages)\n",
NumberOfPages,
OffsetInPages,
Range->MemoryBase.QuadPart,
Range->NumberOfPages));
return(STATUS_INVALID_PARAMETER);
}
//
// Get the MDL that describes the entire mapped range
//
LOCK_MASTER(Extension);
AgpGetMappedPages(AgpContext,
Range,
NumberOfPages,
OffsetInPages,
Mdl);
UNLOCK_MASTER(Extension);
return(STATUS_SUCCESS);
}
PMDL
AgpLibAllocatePhysicalMemory(IN PVOID AgpContext, IN ULONG TotalBytes)
/*++
Routine Description:
Allocates a set of physical memory pages for use by the AGP driver.
This routine uses MmAllocatePagesForMdl to attempt to allocate
as many of the pages as possible within favored AGP memory
ranges (if any).
Arguments:
AgpContext - The AgpContext
TotalBytes - The total amount of bytes to allocate.
Return Value:
An MDL that describes the allocated physical pages or NULL
if this function is unsuccessful.
NOTE: Just like MmAllocatePagesForMdl, this function can return
an MDL that describes an allocation smaller than TotalBytes in size.
--*/
{
PHYSICAL_ADDRESS ZeroAddress, MaxAddress;
PMDL MdlList = NULL, NewMdl = NULL;
PTARGET_EXTENSION Extension;
ULONG i, PagesNeeded;
PAGED_CODE();
AGPLOG(AGP_NOISE, ("AGPLIB: Attempting to allocate memory = %u pages.\n",
BYTES_TO_PAGES(TotalBytes)));
// Initialize some stuff
ZeroAddress.QuadPart = 0;
MAX_MEM(MaxAddress.QuadPart);
AGPLOG(AGP_NOISE, ("AGPLIB: Max memory set to %I64x.\n", MaxAddress.QuadPart));
GET_TARGET_EXTENSION(Extension, AgpContext);
// How many pages do we need?
PagesNeeded = BYTES_TO_PAGES(TotalBytes);
//
// Loop through each favored range, attempting to allocate
// as much as possible from that range within the bounds
// of what we actually need.
//
for (i = 0; i < Extension->FavoredMemory.NumRanges; i++) {
AGPLOG(AGP_NOISE,
("AGPLIB: Trying to allocate %u pages from range %I64x - %I64x.\n",
PagesNeeded,
Extension->FavoredMemory.Ranges[i].Lower,
Extension->FavoredMemory.Ranges[i].Upper));
NewMdl = MmAllocatePagesForMdl(Extension->FavoredMemory.Ranges[i].Lower,
Extension->FavoredMemory.Ranges[i].Upper,
ZeroAddress,
PagesNeeded << PAGE_SHIFT);
if (NewMdl) {
AGPLOG(AGP_NOISE, ("AGPLIB: %u pages allocated in range.\n",
NewMdl->ByteCount >> PAGE_SHIFT));
PagesNeeded -= (NewMdl->ByteCount >> PAGE_SHIFT);
//
// Build a list of the MDls used
// for each range-based allocation
//
NewMdl->Next = MdlList;
MdlList = NewMdl;
// Stop allocating if we are finished.
if (PagesNeeded == 0) break;
} else {
AGPLOG(AGP_NOISE, ("AGPLIB: NO pages allocated in range.\n"));
}
}
//
// Attempt to allocate from ALL of physical memory
// if we could not complete our allocation with only
// the favored memory ranges.
//
if (PagesNeeded > 0) {
AGPLOG(AGP_NOISE, ("AGPLIB: Global Memory allocation for %u pages.\n",
PagesNeeded));
NewMdl = MmAllocatePagesForMdl(ZeroAddress,
MaxAddress,
ZeroAddress,
PagesNeeded << PAGE_SHIFT);
if (NewMdl) {
AGPLOG(AGP_NOISE, ("AGPLIB: Good Global Memory Alloc for %u pages.\n",
NewMdl->ByteCount >> PAGE_SHIFT));
//
// Add this MDL to the list as well
//
NewMdl->Next = MdlList;
MdlList = NewMdl;
} else {
AGPLOG(AGP_NOISE, ("AGPLIB: Failed Global Memory Alloc.\n"));
}
}
// We now have a list of Mdls in MdlList that give us the best
// possible memory allocation taking favored ranges into account.
// What we now need to do is combine this Mdl list into one mdl.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -