📄 intrface.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.
--*/
#define INITGUID 1
#include "agplib.h"
VOID
AgpLibFlushDcacheMdl(
PMDL Mdl
);
VOID
ApFlushDcache(
IN PKDPC Dpc,
IN PKEVENT Event,
IN PMDL Mdl,
IN PVOID SystemArgument2
);
PMDL
AgpCombineMdlList(IN PMDL MdlList);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, AgpInterfaceReference)
#pragma alloc_text(PAGE, AgpInterfaceDereference)
#pragma alloc_text(PAGE, AgpInterfaceReserveMemory)
#pragma alloc_text(PAGE, AgpInterfaceReleaseMemory)
#pragma alloc_text(PAGE, AgpInterfaceSetRate)
#pragma alloc_text(PAGE, AgpInterfaceCommitMemory)
#pragma alloc_text(PAGE, AgpInterfaceFreeMemory)
#pragma alloc_text(PAGE, AgpLibFlushDcacheMdl)
#pragma alloc_text(PAGE, AgpLibAllocatePhysicalMemory)
#pragma alloc_text(PAGE, AgpLibAllocateMappedPhysicalMemory)
#pragma alloc_text(PAGE, AgpCombineMdlList)
#endif
VOID
AgpInterfaceReference(
IN PMASTER_EXTENSION Extension
)
/*++
Routine Description:
References an interface. Currently a NOP.
Arguments:
Extension - Supplies the device extension
Return Value:
None
--*/
{
PAGED_CODE();
InterlockedIncrement(&Extension->InterfaceCount);
}
VOID
AgpInterfaceDereference(
IN PMASTER_EXTENSION Extension
)
/*++
Routine Description:
Dereferences an interface. Currently a NOP.
Arguments:
Extension - Supplies the device extension
Return Value:
None
--*/
{
PAGED_CODE();
InterlockedDecrement(&Extension->InterfaceCount);
}
NTSTATUS
AgpInterfaceReserveMemory(
IN PMASTER_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;
PHYSICAL_ADDRESS MemoryBase;
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 PMASTER_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;
PHYSICAL_ADDRESS MemoryBase;
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 PMASTER_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 {
//
// Save ourselves the trouble...
//
if (!(CurrentLength > 0)) {
break;
}
//
// 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) {
if (!NT_SUCCESS((AgpFlushPages)(AgpContext, NewMdl))) {
Status = STATUS_INSUFFICIENT_RESOURCES;
MmFreePagesFromMdl(NewMdl);
break;
}
} else {
AgpLibFlushDcacheMdl(NewMdl);
}
Status = AgpMapMemory(AgpContext,
Range,
NewMdl,
RunOffset,
MemoryBase);
if (!NT_SUCCESS(Status)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -