📄 gart.c
字号:
Agp440FindRangeInGart(
IN PGART_PTE StartPte,
IN PGART_PTE EndPte,
IN ULONG Length,
IN BOOLEAN SearchBackward,
IN ULONG SearchState
)
/*++
Routine Description:
Finds a contiguous range in the GART. This routine can
search either from the beginning of the GART forwards or
the end of the GART backwards.
Arguments:
StartIndex - Supplies the first GART pte to search
EndPte - Supplies the last GART to search (inclusive)
Length - Supplies the number of contiguous free entries
to search for.
SearchBackward - TRUE indicates that the search should begin
at EndPte and search backwards. FALSE indicates that the
search should begin at StartPte and search forwards
SearchState - Supplies the PTE state to look for.
Return Value:
Pointer to the first PTE in the GART if a suitable range
is found.
NULL if no suitable range exists.
--*/
{
PGART_PTE Current;
PGART_PTE Last;
LONG Delta;
ULONG Found;
PGART_PTE Candidate;
PAGED_CODE();
ASSERT(EndPte >= StartPte);
ASSERT(Length <= (ULONG)(EndPte - StartPte + 1));
ASSERT(Length != 0);
if (SearchBackward) {
Current = EndPte;
Last = StartPte-1;
Delta = -1;
} else {
Current = StartPte;
Last = EndPte+1;
Delta = 1;
}
Found = 0;
while (Current != Last) {
if (Current->Soft.State == SearchState) {
if (++Found == Length) {
//
// A suitable range was found, return it
//
if (SearchBackward) {
return(Current);
} else {
return(Current - Length + 1);
}
}
} else {
Found = 0;
}
Current += Delta;
}
//
// A suitable range was not found.
//
return(NULL);
}
VOID
Agp440SetGTLB_Enable(
IN PAGP440_EXTENSION AgpContext,
IN BOOLEAN Enable
)
/*++
Routine Description:
Enables or disables the GTLB by setting or clearing the GTLB_Enable bit
in the AGPCTRL register
Arguments:
AgpContext - Supplies the AGP context
Enable - TRUE, GTLB_Enable is set to 1
FALSE, GTLB_Enable is set to 0
Return Value:
None
--*/
{
AGPCTRL AgpCtrl;
Read440Config(&AgpCtrl, AGPCTRL_OFFSET, sizeof(AgpCtrl));
if (Enable) {
AgpCtrl.GTLB_Enable = 1;
} else {
AgpCtrl.GTLB_Enable = 0;
}
Write440Config(&AgpCtrl, AGPCTRL_OFFSET, sizeof(AgpCtrl));
}
VOID
AgpFindFreeRun(
IN PVOID AgpContext,
IN PAGP_RANGE AgpRange,
IN ULONG NumberOfPages,
IN ULONG OffsetInPages,
OUT ULONG *FreePages,
OUT ULONG *FreeOffset
)
/*++
Routine Description:
Finds the first contiguous run of free pages in the specified
part of the reserved range.
Arguments:
AgpContext - Supplies the AGP context
AgpRange - Supplies the AGP range
NumberOfPages - Supplies the size of the region to be searched for free pages
OffsetInPages - Supplies the start of the region to be searched for free pages
FreePages - Returns the length of the first contiguous run of free pages
FreeOffset - Returns the start of the first contiguous run of free pages
Return Value:
None. FreePages == 0 if there are no free pages in the specified range.
--*/
{
PGART_PTE Pte;
ULONG i;
Pte = (PGART_PTE)(AgpRange->Context) + OffsetInPages;
//
// Find the first free PTE
//
for (i=0; i<NumberOfPages; i++) {
if (Pte[i].Hard.Valid == 0) {
//
// Found a free PTE, count the contiguous ones.
//
*FreeOffset = i + OffsetInPages;
*FreePages = 0;
while ((i<NumberOfPages) && (Pte[i].Hard.Valid == 0)) {
*FreePages += 1;
++i;
}
return;
}
}
//
// No free PTEs in the specified range
//
*FreePages = 0;
return;
}
VOID
AgpGetMappedPages(
IN PVOID AgpContext,
IN PAGP_RANGE AgpRange,
IN ULONG NumberOfPages,
IN ULONG OffsetInPages,
OUT PMDL Mdl
)
/*++
Routine Description:
Returns the list of physical pages mapped into the specified
range in the GART.
Arguments:
AgpContext - Supplies the AGP context
AgpRange - Supplies the AGP range
NumberOfPages - Supplies the number of pages to be returned
OffsetInPages - Supplies the start of the region
Mdl - Returns the list of physical pages mapped in the specified range.
Return Value:
None
--*/
{
PGART_PTE Pte;
ULONG i;
PULONG Pages;
ASSERT(NumberOfPages * PAGE_SIZE == Mdl->ByteCount);
Pages = (PULONG)(Mdl + 1);
Pte = (PGART_PTE)(AgpRange->Context) + OffsetInPages;
for (i=0; i<NumberOfPages; i++) {
ASSERT(Pte[i].Hard.Valid == 1);
Pages[i] = Pte[i].Hard.Page;
}
return;
}
NTSTATUS
AgpSpecialTarget(
IN PAGP440_EXTENSION AgpContext,
IN ULONGLONG DeviceFlags
)
/*++
Routine Description:
This routine makes "special" tweaks to the AGP chipset
Arguments:
AgpContext - Supplies the AGP context
DeviceFlags - Flags indicating what tweaks to perform
Return Value:
STATUS_SUCCESS, or error
--*/
{
NTSTATUS Status;
//
// Should we change the AGP rate?
//
if (DeviceFlags & AGP_FLAG_SPECIAL_RESERVE) {
Status = Agp440SetRate(AgpContext,
(ULONG)((DeviceFlags & AGP_FLAG_SPECIAL_RESERVE)
>> AGP_FLAG_SET_RATE_SHIFT));
if (!NT_SUCCESS(Status)) {
return Status;
}
}
//
// Add more tweaks here...
//
AgpContext->SpecialTarget |= DeviceFlags;
return STATUS_SUCCESS;
}
NTSTATUS
Agp440SetRate(
IN PAGP440_EXTENSION AgpContext,
IN ULONG AgpRate
)
/*++
Routine Description:
This routine sets the AGP rate
Arguments:
AgpContext - Supplies the AGP context
AgpRate - Rate to set
Return Value:
STATUS_SUCCESS, or error status
--*/
{
NTSTATUS Status;
ULONG TargetEnable;
ULONG MasterEnable;
PCI_AGP_CAPABILITY TargetCap;
PCI_AGP_CAPABILITY MasterCap;
BOOLEAN ReverseInit;
//
// Read capabilities
//
Status = AgpLibGetPciDeviceCapability(0, 0, &TargetCap);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_WARNING, ("AGP440SetRate: AgpLibGetPciDeviceCapability "
"failed %08lx\n", Status));
return Status;
}
Status = AgpLibGetMasterCapability(AgpContext, &MasterCap);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_WARNING, ("AGP440SetRate: AgpLibGetMasterCapability "
"failed %08lx\n", Status));
return Status;
}
//
// Verify the requested rate is supported by both master and target
//
if (!(AgpRate & TargetCap.AGPStatus.Rate & MasterCap.AGPStatus.Rate)) {
return STATUS_INVALID_PARAMETER;
}
//
// Disable AGP while the pull the rug out from underneath
//
TargetEnable = TargetCap.AGPCommand.AGPEnable;
TargetCap.AGPCommand.AGPEnable = 0;
Status = AgpLibSetPciDeviceCapability(0, 0, &TargetCap);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_WARNING,
("AGP440SetRate: AgpLibSetPciDeviceCapability %08lx for "
"Target failed %08lx\n",
&TargetCap,
Status));
return Status;
}
MasterEnable = MasterCap.AGPCommand.AGPEnable;
MasterCap.AGPCommand.AGPEnable = 0;
Status = AgpLibSetMasterCapability(AgpContext, &MasterCap);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_WARNING,
("AGP440SetRate: AgpLibSetMasterCapability %08lx failed "
"%08lx\n",
&MasterCap,
Status));
return Status;
}
//
// Fire up AGP with new rate
//
ReverseInit =
(AgpContext->SpecialTarget & AGP_FLAG_REVERSE_INITIALIZATION) ==
AGP_FLAG_REVERSE_INITIALIZATION;
if (ReverseInit) {
MasterCap.AGPCommand.Rate = AgpRate;
MasterCap.AGPCommand.AGPEnable = MasterEnable;
Status = AgpLibSetMasterCapability(AgpContext, &MasterCap);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_WARNING,
("AGP440SetRate: AgpLibSetMasterCapability %08lx failed "
"%08lx\n",
&MasterCap,
Status));
}
}
TargetCap.AGPCommand.Rate = AgpRate;
TargetCap.AGPCommand.AGPEnable = TargetEnable;
Status = AgpLibSetPciDeviceCapability(0, 0, &TargetCap);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_WARNING,
("AGP440SetRate: AgpLibSetPciDeviceCapability %08lx for "
"Target failed %08lx\n",
&TargetCap,
Status));
return Status;
}
if (!ReverseInit) {
MasterCap.AGPCommand.Rate = AgpRate;
MasterCap.AGPCommand.AGPEnable = MasterEnable;
Status = AgpLibSetMasterCapability(AgpContext, &MasterCap);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_WARNING,
("AGP440SetRate: AgpLibSetMasterCapability %08lx failed "
"%08lx\n",
&MasterCap,
Status));
}
}
return Status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -