766 lines
20 KiB
C
766 lines
20 KiB
C
/*++
|
||
|
||
Copyright (c) 1997 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
intrface.c
|
||
|
||
Abstract:
|
||
|
||
Routines for implementing the AGP_BUS_INTERFACE_STANDARD interface
|
||
|
||
Author:
|
||
|
||
John Vert (jvert) 10/26/1997
|
||
|
||
Revision History:
|
||
|
||
Elliot Shmukler (elliots) 3/24/1999 - Added support for "favored" memory
|
||
ranges for AGP physical memory allocation,
|
||
fixed some bugs.
|
||
|
||
--*/
|
||
|
||
#if 0 // NUGOOP
|
||
|
||
#define INITGUID 1
|
||
#include "videoprt.h"
|
||
|
||
ULONG AgpStopLevel;
|
||
ULONG AgpLogLevel;
|
||
PAGP_FLUSH_PAGES AgpFlushPages = NULL; // not implemented
|
||
|
||
VOID
|
||
AgpLibFlushDcacheMdl(
|
||
PMDL Mdl
|
||
);
|
||
|
||
VOID
|
||
AgpInterfaceReference(
|
||
IN PVIDEO_DEVICE_EXTENSION Extension
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
References an interface. Currently a NOP.
|
||
|
||
Arguments:
|
||
|
||
Extension - Supplies the device extension
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
}
|
||
|
||
|
||
VOID
|
||
AgpInterfaceDereference(
|
||
IN PVIDEO_DEVICE_EXTENSION Extension
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Dereferences an interface. Currently a NOP.
|
||
|
||
Arguments:
|
||
|
||
Extension - Supplies the device extension
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
AgpInterfaceReserveMemory(
|
||
IN PVIDEO_DEVICE_EXTENSION Extension,
|
||
IN ULONG NumberOfPages,
|
||
IN MEMORY_CACHING_TYPE MemoryType,
|
||
OUT PVOID *MapHandle,
|
||
OUT OPTIONAL PHYSICAL_ADDRESS *PhysicalAddress
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Reserves memory in the specified aperture
|
||
|
||
Arguments:
|
||
|
||
Extension - Supplies the device extension where physical address space should be reserved.
|
||
|
||
NumberOfPages - Supplies the number of pages to reserve.
|
||
|
||
MemoryType - Supplies the memory caching type.
|
||
|
||
MapHandle - Returns the mapping handle to be used on subsequent calls.
|
||
|
||
PhysicalAddress - If present, returns the physical address in the aperture of the reserved
|
||
space
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS
|
||
|
||
--*/
|
||
|
||
{
|
||
PVOID AgpContext;
|
||
NTSTATUS Status;
|
||
PAGP_RANGE Range;
|
||
|
||
PAGED_CODE();
|
||
|
||
AgpContext = GET_AGP_CONTEXT_FROM_MASTER(Extension);
|
||
|
||
Range = ExAllocatePoolWithTag(PagedPool,
|
||
sizeof(AGP_RANGE),
|
||
'RpgA');
|
||
if (Range == NULL) {
|
||
return(STATUS_INSUFFICIENT_RESOURCES);
|
||
}
|
||
Range->CommittedPages = 0;
|
||
Range->NumberOfPages = NumberOfPages;
|
||
Range->Type = MemoryType;
|
||
|
||
LOCK_MASTER(Extension);
|
||
Status = AgpReserveMemory(AgpContext,
|
||
Range);
|
||
UNLOCK_MASTER(Extension);
|
||
if (!NT_SUCCESS(Status)) {
|
||
AGPLOG(AGP_CRITICAL,
|
||
("AgpInterfaceReserveMemory - reservation of %x pages of type %d failed %08lx\n",
|
||
NumberOfPages,
|
||
MemoryType,
|
||
Status));
|
||
} else {
|
||
AGPLOG(AGP_NOISE,
|
||
("AgpInterfaceReserveMemory - reserved %x pages of type %d at %I64X\n",
|
||
NumberOfPages,
|
||
MemoryType,
|
||
Range->MemoryBase.QuadPart));
|
||
}
|
||
|
||
*MapHandle = Range;
|
||
if (ARGUMENT_PRESENT(PhysicalAddress)) {
|
||
*PhysicalAddress = Range->MemoryBase;
|
||
}
|
||
return(Status);
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
AgpInterfaceReleaseMemory(
|
||
IN PVIDEO_DEVICE_EXTENSION Extension,
|
||
IN PVOID MapHandle
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Releases memory in the specified aperture that was previously reserved by
|
||
AgpInterfaceReserveMemory
|
||
|
||
Arguments:
|
||
|
||
Extension - Supplies the device extension where physical address space should be reserved.
|
||
|
||
MapHandle - Supplies the mapping handle returned from AgpInterfaceReserveMemory
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS
|
||
|
||
--*/
|
||
|
||
{
|
||
PAGP_RANGE Range;
|
||
PVOID AgpContext;
|
||
NTSTATUS Status;
|
||
|
||
PAGED_CODE();
|
||
|
||
AgpContext = GET_AGP_CONTEXT_FROM_MASTER(Extension);
|
||
Range = (PAGP_RANGE)MapHandle;
|
||
|
||
LOCK_MASTER(Extension);
|
||
//
|
||
// Make sure the range is empty
|
||
//
|
||
ASSERT(Range->CommittedPages == 0);
|
||
if (Range->CommittedPages != 0) {
|
||
AGPLOG(AGP_CRITICAL,
|
||
("AgpInterfaceReleaseMemory - Invalid attempt to release non-empty range %08lx\n",
|
||
Range));
|
||
UNLOCK_MASTER(Extension);
|
||
return(STATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
AGPLOG(AGP_NOISE,
|
||
("AgpInterfaceReleaseMemory - releasing range %08lx, %lx pages at %08lx\n",
|
||
Range,
|
||
Range->NumberOfPages,
|
||
Range->MemoryBase.QuadPart));
|
||
Status = AgpReleaseMemory(AgpContext,
|
||
Range);
|
||
if (!NT_SUCCESS(Status)) {
|
||
AGPLOG(AGP_CRITICAL,
|
||
("AgpInterfaceReleaseMemory - release failed %08lx\n",
|
||
Status));
|
||
}
|
||
UNLOCK_MASTER(Extension);
|
||
ExFreePool(Range);
|
||
return(Status);
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
AgpInterfaceCommitMemory(
|
||
IN PVIDEO_DEVICE_EXTENSION Extension,
|
||
IN PVOID MapHandle,
|
||
IN ULONG NumberOfPages,
|
||
IN ULONG OffsetInPages,
|
||
IN OUT PMDL Mdl OPTIONAL,
|
||
OUT PHYSICAL_ADDRESS *MemoryBase
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Commits memory into the specified aperture that was previously reserved by
|
||
AgpInterfaceReserveMemory
|
||
|
||
Arguments:
|
||
|
||
Extension - Supplies the device extension where physical address space should
|
||
be committed.
|
||
|
||
MapHandle - Supplies the mapping handle returned from AgpInterfaceReserveMemory
|
||
|
||
NumberOfPages - Supplies the number of pages to be committed.
|
||
|
||
OffsetInPages - Supplies the offset, in pages, into the aperture reserved by
|
||
AgpInterfaceReserveMemory
|
||
|
||
Mdl - Returns the MDL describing the pages of memory committed.
|
||
|
||
MemoryBase - Returns the physical memory address of the committed memory.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS
|
||
|
||
--*/
|
||
|
||
{
|
||
PAGP_RANGE Range = (PAGP_RANGE)MapHandle;
|
||
PMDL NewMdl;
|
||
PVOID AgpContext;
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
ULONG RunLength, RunOffset;
|
||
ULONG CurrentLength, CurrentOffset;
|
||
PMDL FirstMdl=NULL;
|
||
|
||
PAGED_CODE();
|
||
|
||
AgpContext = GET_AGP_CONTEXT_FROM_MASTER(Extension);
|
||
|
||
ASSERT(NumberOfPages <= Range->NumberOfPages);
|
||
ASSERT(NumberOfPages > 0);
|
||
ASSERT((Mdl == NULL) || (Mdl->ByteCount == PAGE_SIZE * NumberOfPages));
|
||
|
||
CurrentLength = NumberOfPages;
|
||
CurrentOffset = OffsetInPages;
|
||
|
||
LOCK_MASTER(Extension);
|
||
do {
|
||
|
||
//
|
||
// Find the first free run in the supplied range.
|
||
//
|
||
AgpFindFreeRun(AgpContext,
|
||
Range,
|
||
CurrentLength,
|
||
CurrentOffset,
|
||
&RunLength,
|
||
&RunOffset);
|
||
|
||
if (RunLength > 0) {
|
||
ASSERT(RunLength <= CurrentLength);
|
||
ASSERT(RunOffset >= CurrentOffset);
|
||
ASSERT(RunOffset < CurrentOffset + CurrentLength);
|
||
ASSERT(RunOffset + RunLength <= CurrentOffset + CurrentLength);
|
||
|
||
//
|
||
// Compute the next offset and length
|
||
//
|
||
CurrentLength -= (RunOffset - CurrentOffset) + RunLength;
|
||
CurrentOffset = RunOffset + RunLength;
|
||
|
||
//
|
||
// Get an MDL from memory management big enough to map the
|
||
// requested range.
|
||
//
|
||
|
||
NewMdl = AgpLibAllocatePhysicalMemory(AgpContext, RunLength * PAGE_SIZE);
|
||
|
||
//
|
||
// This can fail in two ways, either no memory is available at all (NewMdl == NULL)
|
||
// or some pages were available, but not enough. (NewMdl->ByteCount < Length)
|
||
//
|
||
if (NewMdl == NULL) {
|
||
AGPLOG(AGP_CRITICAL,
|
||
("AgpInterfaceReserveMemory - Couldn't allocate pages for %lx bytes\n",
|
||
RunLength));
|
||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
break;
|
||
} else if (BYTES_TO_PAGES(NewMdl->ByteCount) < RunLength) {
|
||
AGPLOG(AGP_CRITICAL,
|
||
("AgpInterfaceCommitMemory - Only allocated enough pages for %lx of %lx bytes\n",
|
||
NewMdl->ByteCount,
|
||
RunLength));
|
||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
MmFreePagesFromMdl(NewMdl);
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Now that we have our MDL, we can map this into the specified
|
||
// range.
|
||
//
|
||
if (AgpFlushPages != NULL) {
|
||
(AgpFlushPages)(AgpContext, NewMdl);
|
||
} else {
|
||
AgpLibFlushDcacheMdl(NewMdl);
|
||
}
|
||
Status = AgpMapMemory(AgpContext,
|
||
Range,
|
||
NewMdl,
|
||
RunOffset,
|
||
MemoryBase);
|
||
if (!NT_SUCCESS(Status)) {
|
||
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 PVIDEO_DEVICE_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) {
|
||
|
||
// @@BEGIN_DDKSPLIT
|
||
//
|
||
// 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.
|
||
// BUGBUG John Vert (jvert) 11/11/1997
|
||
// implement this
|
||
//
|
||
// @@END_DDKSPLIT
|
||
|
||
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 PVIDEO_DEVICE_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;
|
||
|
||
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.
|
||
|
||
--*/
|
||
{
|
||
PAGED_CODE();
|
||
|
||
AGPLOG(AGP_NOISE, ("AGPLIB: Attempting to allocate memory = %u pages.\n",
|
||
BYTES_TO_PAGES(TotalBytes)));
|
||
|
||
return MmAllocatePagesForMdl(0,
|
||
MAXULONG_PTR,
|
||
TotalBytes);
|
||
}
|
||
|
||
|
||
PVOID
|
||
AgpLibAllocateMappedPhysicalMemory(IN PVOID AgpContext, IN ULONG TotalBytes)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Same as AgpLibAllocatePhysicalMemory, except this function will
|
||
also map the allocated memory to a virtual address.
|
||
|
||
Arguments:
|
||
|
||
Same as AgpLibAllocatePhysicalMemory.
|
||
|
||
Return Value:
|
||
|
||
A virtual address of the allocated memory or NULL if unsuccessful.
|
||
|
||
--*/
|
||
{
|
||
PMDL Mdl;
|
||
PVOID Ret;
|
||
|
||
PAGED_CODE();
|
||
|
||
AGPLOG(AGP_NOISE,
|
||
("AGPLIB: Attempting to allocate mapped memory = %u.\n", TotalBytes));
|
||
|
||
//
|
||
// Call the real memory allocator.
|
||
//
|
||
|
||
Mdl = AgpLibAllocatePhysicalMemory(AgpContext, TotalBytes);
|
||
|
||
// Two possible failures
|
||
|
||
// 1. MDL is NULL. No memory could be allocated.
|
||
|
||
if (Mdl == NULL) {
|
||
|
||
AGPLOG(AGP_WARNING, ("AGPMAP: Could not allocate anything.\n"));
|
||
|
||
return NULL;
|
||
}
|
||
|
||
// 2. MDL has some pages allocated but not enough.
|
||
|
||
if (Mdl->ByteCount < TotalBytes) {
|
||
|
||
AGPLOG(AGP_WARNING, ("AGPMAP: Could not allocate enough.\n"));
|
||
|
||
MmFreePagesFromMdl(Mdl);
|
||
ExFreePool(Mdl);
|
||
return NULL;
|
||
}
|
||
|
||
// Ok. Our allocation succeeded. Map it to a virtual address.
|
||
|
||
// Step 1: Map the locked Pages. (will return NULL if failed)
|
||
|
||
Mdl->MdlFlags |= MDL_PAGES_LOCKED;
|
||
Ret = MmMapLockedPagesSpecifyCache (Mdl, MmNonCached);
|
||
|
||
// Don't need the Mdl anymore, whether we succeeded or failed.
|
||
|
||
ExFreePool(Mdl);
|
||
|
||
if (Ret == NULL) {
|
||
AGPLOG(AGP_WARNING, ("AGPMAP: Could not map.\n"));
|
||
}
|
||
|
||
return Ret;
|
||
}
|
||
|
||
#if defined (_X86_)
|
||
#define FLUSH_DCACHE(Mdl) __asm{ wbinvd }
|
||
#else
|
||
#define FLUSH_DCACHE(Mdl) \
|
||
AGPLOG(AGP_CRITICAL, \
|
||
("AgpLibFlushDcacheMdl - NEED TO IMPLEMENT DCACHE FLUSH FOR THIS ARCHITECTURE!!\n"))
|
||
#endif
|
||
|
||
|
||
VOID
|
||
AgpLibFlushDcacheMdl(
|
||
PMDL Mdl
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Flushes the specified MDL from the D-caches of all processors
|
||
in the system.
|
||
|
||
Current algorithm is to set the current thread's affinity to each
|
||
processor in turn and flush the dcache. This could be made a lot
|
||
more efficient if this turns out to be a hot codepath
|
||
|
||
Arguments:
|
||
|
||
Mdl - Supplies the MDL to be flushed.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
FLUSH_DCACHE(Mdl);
|
||
}
|
||
|
||
#endif 0
|