📄 gart.c
字号:
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
gart.c
Abstract:
Routines for querying and setting the Intel 440xx GART aperture
Author:
John Vert (jvert) 10/30/1997
Revision History:
--*/
#include "agp440.h"
//
// Local function prototypes
//
NTSTATUS
Agp440CreateGart(
IN PAGP440_EXTENSION AgpContext,
IN ULONG MinimumPages
);
PGART_PTE
Agp440FindRangeInGart(
IN PGART_PTE StartPte,
IN PGART_PTE EndPte,
IN ULONG Length,
IN BOOLEAN SearchBackward,
IN ULONG SearchState
);
NTSTATUS
Agp440SetRate(
IN PVOID AgpContext,
IN ULONG AgpRate
);
VOID
Agp440SetGTLB_Enable(
IN PAGP440_EXTENSION AgpContext,
IN BOOLEAN Enable
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, AgpDisableAperture)
#pragma alloc_text(PAGE, AgpQueryAperture)
#pragma alloc_text(PAGE, AgpReserveMemory)
#pragma alloc_text(PAGE, AgpReleaseMemory)
#pragma alloc_text(PAGE, Agp440CreateGart)
#pragma alloc_text(PAGE, AgpMapMemory)
#pragma alloc_text(PAGE, AgpUnMapMemory)
#pragma alloc_text(PAGE, Agp440FindRangeInGart)
#pragma alloc_text(PAGE, AgpFindFreeRun)
#pragma alloc_text(PAGE, AgpGetMappedPages)
#endif
#define Agp440EnableTB(_x_) Agp440SetGTLB_Enable((_x_), TRUE)
#define Agp440DisableTB(_x_) Agp440SetGTLB_Enable((_x_), FALSE)
NTSTATUS
AgpQueryAperture(
IN PAGP440_EXTENSION AgpContext,
OUT PHYSICAL_ADDRESS *CurrentBase,
OUT ULONG *CurrentSizeInPages,
OUT OPTIONAL PIO_RESOURCE_LIST *pApertureRequirements
)
/*++
Routine Description:
Queries the current size of the GART aperture. Optionally returns
the possible GART settings.
Arguments:
AgpContext - Supplies the AGP context.
CurrentBase - Returns the current physical address of the GART.
CurrentSizeInPages - Returns the current GART size.
ApertureRequirements - if present, returns the possible GART settings
Return Value:
NTSTATUS
--*/
{
ULONG ApBase;
UCHAR ApSize;
PIO_RESOURCE_LIST Requirements;
ULONG i;
ULONG Length;
PAGED_CODE();
//
// Get the current APBASE and APSIZE settings
//
Read440Config(&ApBase, APBASE_OFFSET, sizeof(ApBase));
Read440Config(&ApSize, APSIZE_OFFSET, sizeof(ApSize));
ASSERT(ApBase != 0);
CurrentBase->QuadPart = ApBase & PCI_ADDRESS_MEMORY_ADDRESS_MASK;
//
// Convert APSIZE into the actual size of the aperture
//
switch (ApSize) {
case AP_SIZE_4MB:
*CurrentSizeInPages = 4 * (1024*1024 / PAGE_SIZE);
break;
case AP_SIZE_8MB:
*CurrentSizeInPages = 8 * (1024*1024 / PAGE_SIZE);
break;
case AP_SIZE_16MB:
*CurrentSizeInPages = 16 * (1024*1024 / PAGE_SIZE);
break;
case AP_SIZE_32MB:
*CurrentSizeInPages = 32 * (1024*1024 / PAGE_SIZE);
break;
case AP_SIZE_64MB:
*CurrentSizeInPages = 64 * (1024*1024 / PAGE_SIZE);
break;
case AP_SIZE_128MB:
*CurrentSizeInPages = 128 * (1024*1024 / PAGE_SIZE);
break;
case AP_SIZE_256MB:
*CurrentSizeInPages = 256 * (1024*1024 / PAGE_SIZE);
break;
default:
AGPLOG(AGP_CRITICAL,
("AGP440 - AgpQueryAperture - Unexpected value %x for ApSize!\n",
ApSize));
ASSERT(FALSE);
AgpContext->ApertureStart.QuadPart = 0;
AgpContext->ApertureLength = 0;
return(STATUS_UNSUCCESSFUL);
}
//
// Remember the current aperture settings
//
AgpContext->ApertureStart.QuadPart = CurrentBase->QuadPart;
AgpContext->ApertureLength = *CurrentSizeInPages * PAGE_SIZE;
if (pApertureRequirements != NULL) {
ULONG VendorId;
//
// 440 supports 7 different aperture sizes, all must be
// naturally aligned. Start with the largest aperture and
// work downwards so that we get the biggest possible aperture.
//
Requirements = ExAllocatePoolWithTag(PagedPool,
sizeof(IO_RESOURCE_LIST) + (AP_SIZE_COUNT-1)*sizeof(IO_RESOURCE_DESCRIPTOR),
'RpgA');
if (Requirements == NULL) {
return(STATUS_INSUFFICIENT_RESOURCES);
}
Requirements->Version = Requirements->Revision = 1;
//
// 815 only supports 64MB and 32MB Aperture sizes
//
Read440Config(&VendorId, 0, sizeof(VendorId));
if (VendorId == AGP_815_IDENTIFIER) {
Requirements->Count = AP_815_SIZE_COUNT;
Length = AP_815_MAX_SIZE;
} else {
Requirements->Count = AP_SIZE_COUNT;
Length = AP_MAX_SIZE;
}
for (i=0; i<Requirements->Count; i++) {
Requirements->Descriptors[i].Option = IO_RESOURCE_ALTERNATIVE;
Requirements->Descriptors[i].Type = CmResourceTypeMemory;
Requirements->Descriptors[i].ShareDisposition = CmResourceShareDeviceExclusive;
Requirements->Descriptors[i].Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_PREFETCHABLE;
Requirements->Descriptors[i].u.Memory.Length = Length;
Requirements->Descriptors[i].u.Memory.Alignment = Length;
Requirements->Descriptors[i].u.Memory.MinimumAddress.QuadPart = 0;
Requirements->Descriptors[i].u.Memory.MaximumAddress.QuadPart = (ULONG)-1;
Length = Length/2;
}
*pApertureRequirements = Requirements;
}
return(STATUS_SUCCESS);
}
NTSTATUS
AgpSetAperture(
IN PAGP440_EXTENSION AgpContext,
IN PHYSICAL_ADDRESS NewBase,
IN ULONG NewSizeInPages
)
/*++
Routine Description:
Sets the GART aperture to the supplied settings
Arguments:
AgpContext - Supplies the AGP context
NewBase - Supplies the new physical memory base for the GART.
NewSizeInPages - Supplies the new size for the GART
Return Value:
NTSTATUS
--*/
{
PACCFG PACConfig;
UCHAR ApSize;
ULONG ApBase;
//
// Figure out the new APSIZE setting, make sure it is valid.
//
switch (NewSizeInPages) {
case 4 * 1024 * 1024 / PAGE_SIZE:
ApSize = AP_SIZE_4MB;
break;
case 8 * 1024 * 1024 / PAGE_SIZE:
ApSize = AP_SIZE_8MB;
break;
case 16 * 1024 * 1024 / PAGE_SIZE:
ApSize = AP_SIZE_16MB;
break;
case 32 * 1024 * 1024 / PAGE_SIZE:
ApSize = AP_SIZE_32MB;
break;
case 64 * 1024 * 1024 / PAGE_SIZE:
ApSize = AP_SIZE_64MB;
break;
case 128 * 1024 * 1024 / PAGE_SIZE:
ApSize = AP_SIZE_128MB;
break;
case 256 * 1024 * 1024 / PAGE_SIZE:
ApSize = AP_SIZE_256MB;
break;
default:
AGPLOG(AGP_CRITICAL,
("AgpSetAperture - invalid GART size of %lx pages specified, aperture at %I64X.\n",
NewSizeInPages,
NewBase.QuadPart));
ASSERT(FALSE);
return(STATUS_INVALID_PARAMETER);
}
//
// Make sure the supplied size is aligned on the appropriate boundary.
//
ASSERT(NewBase.HighPart == 0);
ASSERT((NewBase.QuadPart & ((NewSizeInPages * PAGE_SIZE) - 1)) == 0);
if ((NewBase.QuadPart & ((NewSizeInPages * PAGE_SIZE) - 1)) != 0 ) {
AGPLOG(AGP_CRITICAL,
("AgpSetAperture - invalid base %I64X specified for GART aperture of %lx pages\n",
NewBase.QuadPart,
NewSizeInPages));
return(STATUS_INVALID_PARAMETER);
}
//
// Reprogram Special Target settings when the chip
// is powered off, but ignore rate changes as those were already
// applied during MasterInit
//
if (AgpContext->SpecialTarget & ~AGP_FLAG_SPECIAL_RESERVE) {
AgpSpecialTarget(AgpContext,
AgpContext->SpecialTarget &
~AGP_FLAG_SPECIAL_RESERVE);
}
//
// Need to reset the hardware to match the supplied settings
//
// If the aperture is enabled, disable it, write the new settings, then reenable the aperture
//
Read440Config(&PACConfig, PACCFG_OFFSET, sizeof(PACConfig));
PACConfig.GlobalEnable = 0;
Write440Config(&PACConfig, PACCFG_OFFSET, sizeof(PACConfig));
//
// Write APSIZE first, as this will enable the correct bits in APBASE that need to
// be written next.
//
Write440Config(&ApSize, APSIZE_OFFSET, sizeof(ApSize));
//
// Now we can update APBASE
//
ApBase = NewBase.LowPart & PCI_ADDRESS_MEMORY_ADDRESS_MASK;
Write440Config(&ApBase, APBASE_OFFSET, sizeof(ApBase));
#if DBG
//
// Read back what we wrote, make sure it worked
//
{
ULONG DbgBase;
UCHAR DbgSize;
Read440Config(&DbgSize, APSIZE_OFFSET, sizeof(ApSize));
Read440Config(&DbgBase, APBASE_OFFSET, sizeof(ApBase));
ASSERT(DbgSize == ApSize);
ASSERT((DbgBase & PCI_ADDRESS_MEMORY_ADDRESS_MASK) == ApBase);
}
#endif
//
// Now enable the aperture if it was enabled before
//
if (AgpContext->GlobalEnable) {
Read440Config(&PACConfig, PACCFG_OFFSET, sizeof(PACConfig));
ASSERT(PACConfig.GlobalEnable == 0);
PACConfig.GlobalEnable = 1;
Write440Config(&PACConfig, PACCFG_OFFSET, sizeof(PACConfig));
}
//
// Update our extension to reflect the new GART setting
//
AgpContext->ApertureStart = NewBase;
AgpContext->ApertureLength = NewSizeInPages * PAGE_SIZE;
//
// Enable the TB in case we are resuming from S3 or S4
//
Agp440EnableTB(AgpContext);
//
// If the GART has been allocated, rewrite the ATTBASE
//
if (AgpContext->Gart != NULL) {
Write440Config(&AgpContext->GartPhysical.LowPart,
ATTBASE_OFFSET,
sizeof(AgpContext->GartPhysical.LowPart));
}
return(STATUS_SUCCESS);
}
VOID
AgpDisableAperture(
IN PAGP440_EXTENSION AgpContext
)
/*++
Routine Description:
Disables the GART aperture so that this resource is available
for other devices
Arguments:
AgpContext - Supplies the AGP context
Return Value:
None - this routine must always succeed.
--*/
{
PACCFG PACConfig;
//
// Disable the aperture
//
Read440Config(&PACConfig, PACCFG_OFFSET, sizeof(PACConfig));
if (PACConfig.GlobalEnable == 1) {
PACConfig.GlobalEnable = 0;
Write440Config(&PACConfig, PACCFG_OFFSET, sizeof(PACConfig));
}
AgpContext->GlobalEnable = FALSE;
//
// Nuke the Gart! (It's meaningless now...)
//
if (AgpContext->Gart != NULL) {
MmFreeContiguousMemory(AgpContext->Gart);
AgpContext->Gart = NULL;
AgpContext->GartLength = 0;
}
}
NTSTATUS
AgpReserveMemory(
IN PAGP440_EXTENSION AgpContext,
IN OUT AGP_RANGE *Range
)
/*++
Routine Description:
Reserves a range of memory in the GART.
Arguments:
AgpContext - Supplies the AGP Context
Range - Supplies the AGP_RANGE structure. AGPLIB
will have filled in NumberOfPages and Type. This
routine will fill in MemoryBase and Context.
Return Value:
NTSTATUS
--*/
{
ULONG Index;
ULONG NewState;
NTSTATUS Status;
PGART_PTE FoundRange;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -