You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
357 lines
10 KiB
357 lines
10 KiB
/*++
|
|
|
|
Copyright (2) 2002 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
init.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the initialization support routines for the
|
|
MS AGP v3 Filter Driver
|
|
|
|
Author:
|
|
|
|
Eric F. Nelson (enelson) June 6, 2002
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "agp.h"
|
|
#include "uagp35.h"
|
|
|
|
ULONG AgpExtensionSize = sizeof(UAGP35_EXTENSION);
|
|
PAGP_FLUSH_PAGES AgpFlushPages = NULL; // Not implemented (yet)
|
|
|
|
|
|
NTSTATUS
|
|
AgpInitializeTarget(
|
|
IN PVOID AgpExtension
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Entrypoint for target initialization, this is called first
|
|
|
|
Arguments:
|
|
|
|
AgpExtension - Supplies our AGP3 extension
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS
|
|
|
|
--*/
|
|
{
|
|
ULONG DeviceId;
|
|
NTSTATUS Status;
|
|
PCI_AGP_CAPABILITY TargetCap;
|
|
PUAGP35_EXTENSION Extension = AgpExtension;
|
|
|
|
//
|
|
// Zero/init our AGP3 extension
|
|
//
|
|
RtlZeroMemory(AgpExtension, sizeof(UAGP35_EXTENSION));
|
|
|
|
//
|
|
// Figure out what type of AGP3 capability our target is
|
|
//
|
|
Status = AgpLibGetTargetCapability(AgpExtension, &TargetCap);
|
|
if (!NT_SUCCESS(Status)) {
|
|
AGPLOG(AGP_CRITICAL,
|
|
("UAGP35TargetInit: AgpLibGetTargetCapability "
|
|
"failed %08lx\n"));
|
|
return Status;
|
|
}
|
|
Extension->CapabilityId = TargetCap.Header.CapabilityID;
|
|
|
|
//
|
|
// Make sure the capability is v3!!!
|
|
//
|
|
if ((TargetCap.Major < 3) ||
|
|
((TargetCap.Major == 3) && (TargetCap.Minor < 5))) {
|
|
AGPLOG(AGP_CRITICAL,
|
|
("UAGP35TargetInit: Capability version (%d) != 3\n",
|
|
TargetCap.Major));
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
//
|
|
// Save the vendor and device IDs in case we need to "tweak"
|
|
// something for a particular platform
|
|
//
|
|
AgpLibReadAgpTargetConfig(AgpExtension, &DeviceId, 0, sizeof(DeviceId));
|
|
Extension->DeviceId = DeviceId;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
AgpInitializeMaster(
|
|
IN PVOID AgpExtension,
|
|
OUT ULONG *AgpCapabilities
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Entrypoint for master initialization, this is called after target
|
|
initialization and should be used to initialize the AGP capabilities
|
|
of both master and target
|
|
|
|
This is also called when the master transitions into the D0 state
|
|
|
|
Arguments:
|
|
|
|
AgpExtension - Supplies our AGP3 extension
|
|
|
|
AgpCapabilities - Returns the capabilities of this AGP device
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS, or an appropriate error status
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status;
|
|
PCI_AGP_CAPABILITY MasterCap;
|
|
PCI_AGP_CAPABILITY TargetCap;
|
|
ULONG ApertureBase;
|
|
PUAGP35_EXTENSION Extension = AgpExtension;
|
|
ULONG SBAEnable;
|
|
ULONG DataRate;
|
|
ULONG FourGBEnable = OFF;
|
|
ULONG FastWrite;
|
|
BOOLEAN ReverseInit;
|
|
|
|
#if DBG
|
|
PCI_AGP_CAPABILITY CurrentCap;
|
|
#endif
|
|
|
|
//
|
|
// Get the master and target AGP capabilities
|
|
//
|
|
Status = AgpLibGetMasterCapability(AgpExtension, &MasterCap);
|
|
if (!NT_SUCCESS(Status)) {
|
|
AGPLOG(AGP_CRITICAL,
|
|
("UAGP35MasterInit: AgpLibGetMasterCapability failed %08lx\n"));
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Some broken cards (Matrox Millenium II "AGP") report no valid
|
|
// supported transfer rates. These are not really AGP cards. They
|
|
// have an AGP Capabilities structure that reports no capabilities.
|
|
//
|
|
if (MasterCap.AGPStatus.Rate == 0) {
|
|
AGPLOG(AGP_CRITICAL,
|
|
("UAGP35MasterInit: AgpLibGetMasterCapability returned "
|
|
"no valid transfer rate\n"));
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
|
|
Status = AgpLibGetTargetCapability(AgpExtension, &TargetCap);
|
|
if (!NT_SUCCESS(Status)) {
|
|
AGPLOG(AGP_CRITICAL,
|
|
("UAGP35MasterInit: AgpLibGetTargetCapability "
|
|
"failed %08lx\n"));
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Determine the greatest common denominator for data rate.
|
|
//
|
|
DataRate = TargetCap.AGPStatus.Rate & MasterCap.AGPStatus.Rate;
|
|
|
|
AGP_ASSERT(DataRate != 0);
|
|
|
|
//
|
|
// Select the highest common rate
|
|
//
|
|
if (DataRate & PCI_AGP_RATE_4X) {
|
|
DataRate = PCI_AGP_RATE_4X;
|
|
} else if (DataRate & PCI_AGP_RATE_2X) {
|
|
DataRate = PCI_AGP_RATE_2X;
|
|
} else if (DataRate & PCI_AGP_RATE_1X) {
|
|
DataRate = PCI_AGP_RATE_1X;
|
|
}
|
|
|
|
//
|
|
// Previously a call was made to change the rate (successfully),
|
|
// use this rate again now
|
|
//
|
|
if (Extension->SpecialTarget & AGP_FLAG_SPECIAL_RESERVE) {
|
|
DataRate = (ULONG)((Extension->SpecialTarget &
|
|
AGP_FLAG_SPECIAL_RESERVE) >>
|
|
AGP_FLAG_SET_RATE_SHIFT);
|
|
|
|
//
|
|
// If we're in AGP3 mode, and our rate was successfully
|
|
// programmed, then we must convert into AGP2 rate bits
|
|
//
|
|
if (TargetCap.AGPStatus.Agp3Mode == ON) {
|
|
ASSERT(MasterCap.AGPStatus.Agp3Mode == ON);
|
|
ASSERT((DataRate == 8) || (DataRate == PCI_AGP_RATE_4X));
|
|
DataRate >>= 2;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Enable SBA if both master and target support it
|
|
//
|
|
SBAEnable = TargetCap.AGPStatus.SideBandAddressing &
|
|
MasterCap.AGPStatus.SideBandAddressing;
|
|
|
|
//
|
|
// Enable FastWrite if both master and target support it
|
|
//
|
|
FastWrite = TargetCap.AGPStatus.FastWrite &
|
|
MasterCap.AGPStatus.FastWrite;
|
|
|
|
//
|
|
// Enable 4GB addressing if aperture is 64-bit
|
|
//
|
|
AgpLibReadAgpTargetConfig(AgpExtension,
|
|
&ApertureBase,
|
|
APERTURE_BASE,
|
|
sizeof(ApertureBase));
|
|
|
|
if (ApertureBase & APERTURE_BASE64_MASK) {
|
|
FourGBEnable = ON;
|
|
Extension->FourGBEnable = TRUE;
|
|
}
|
|
|
|
//
|
|
// Indicate whether we can map memory through the GART aperture
|
|
//
|
|
*AgpCapabilities = (TargetCap.AGPStatus.HostTransDisable) ? 0:
|
|
AGP_CAPABILITIES_MAP_PHYSICAL;
|
|
|
|
MasterCap.AGPCommand.Rate = DataRate;
|
|
TargetCap.AGPCommand.Rate = DataRate;
|
|
MasterCap.AGPCommand.AGPEnable = ON;
|
|
TargetCap.AGPCommand.AGPEnable = ON;
|
|
MasterCap.AGPCommand.SBAEnable = SBAEnable;
|
|
TargetCap.AGPCommand.SBAEnable = SBAEnable;
|
|
MasterCap.AGPCommand.FastWriteEnable = FastWrite;
|
|
TargetCap.AGPCommand.FastWriteEnable = FastWrite;
|
|
MasterCap.AGPCommand.FourGBEnable = FourGBEnable;
|
|
TargetCap.AGPCommand.FourGBEnable = FourGBEnable;
|
|
MasterCap.AGPCommand.RequestQueueDepth =
|
|
TargetCap.AGPStatus.RequestQueueDepthMaximum;
|
|
MasterCap.AGPCommand.AsyncReqSize =
|
|
TargetCap.AGPStatus.AsyncRequestSize;
|
|
|
|
//
|
|
// Patch rate for early rev VIA 8X silicon errata
|
|
//
|
|
if ((Extension->SpecialTarget & AGP_FLAG_SPECIAL_VIA_AGP2_RATE_PATCH) &&
|
|
(TargetCap.AGPStatus.Agp3Mode == OFF)) {
|
|
switch (DataRate) {
|
|
case PCI_AGP_RATE_1X:
|
|
case PCI_AGP_RATE_2X:
|
|
MasterCap.AGPCommand.Rate = PCI_AGP_RATE_1X;
|
|
TargetCap.AGPCommand.Rate = PCI_AGP_RATE_4X;
|
|
break;
|
|
case PCI_AGP_RATE_4X:
|
|
MasterCap.AGPCommand.Rate = PCI_AGP_RATE_4X;
|
|
TargetCap.AGPCommand.Rate = PCI_AGP_RATE_1X;
|
|
}
|
|
AGPLOG(AGP_WARNING,
|
|
("UAGP35MasterInit: AGP_FLAG_SPECIAL_VIA_AGP2_RATE_PATCH\n"));
|
|
}
|
|
|
|
//
|
|
// Enable the Master first if the reverse init bit is set
|
|
//
|
|
ReverseInit =
|
|
(Extension->SpecialTarget & AGP_FLAG_REVERSE_INITIALIZATION) ==
|
|
AGP_FLAG_REVERSE_INITIALIZATION;
|
|
if (ReverseInit) {
|
|
Status = AgpLibSetMasterCapability(AgpExtension, &MasterCap);
|
|
if (!NT_SUCCESS(Status)) {
|
|
AGPLOG(AGP_CRITICAL,
|
|
("UAGP35MasterInit: AgpLibSetMasterCapability %08lx "
|
|
"failed %08lx\n",
|
|
&MasterCap,
|
|
Status));
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Otherwise enable the Target first
|
|
//
|
|
Status = AgpLibSetTargetCapability(AgpExtension, &TargetCap);
|
|
if (!NT_SUCCESS(Status)) {
|
|
AGPLOG(AGP_CRITICAL,
|
|
("UAGP35MasterInit: AgpLibSetTargetCapability %08lx "
|
|
"for target failed %08lx\n",
|
|
&TargetCap,
|
|
Status));
|
|
return Status;
|
|
}
|
|
|
|
if (!ReverseInit) {
|
|
Status = AgpLibSetMasterCapability(AgpExtension, &MasterCap);
|
|
if (!NT_SUCCESS(Status)) {
|
|
AGPLOG(AGP_CRITICAL,
|
|
("UAGP35MasterInit: AgpLibSetMasterCapability %08lx "
|
|
"failed %08lx\n",
|
|
&MasterCap,
|
|
Status));
|
|
}
|
|
}
|
|
|
|
#if DBG
|
|
//
|
|
// Read them back, see if it worked
|
|
//
|
|
Status = AgpLibGetMasterCapability(AgpExtension, &CurrentCap);
|
|
AGP_ASSERT(NT_SUCCESS(Status));
|
|
|
|
//
|
|
// If the target request queue depth is greater than the master will
|
|
// allow, it will be trimmed, so loosen the assert to not require an
|
|
// exact match
|
|
//
|
|
// We'll do the same for asynchronous request queue depth too
|
|
//
|
|
AGP_ASSERT(CurrentCap.AGPCommand.RequestQueueDepth <=
|
|
MasterCap.AGPCommand.RequestQueueDepth);
|
|
AGP_ASSERT(CurrentCap.AGPCommand.AsyncReqSize <=
|
|
MasterCap.AGPCommand.AsyncReqSize);
|
|
|
|
CurrentCap.AGPCommand.RequestQueueDepth =
|
|
MasterCap.AGPCommand.RequestQueueDepth;
|
|
CurrentCap.AGPCommand.AsyncReqSize = MasterCap.AGPCommand.AsyncReqSize;
|
|
|
|
AGP_ASSERT(RtlEqualMemory(&CurrentCap.AGPCommand,
|
|
&MasterCap.AGPCommand,
|
|
sizeof(CurrentCap.AGPCommand)));
|
|
|
|
AGPLOG(AGP_NOISE,
|
|
("UAGP35MasterInit: WroteMasterCmd=%08x, ReadMasterCmd=%08lx\n",
|
|
MasterCap.AGPCommand,
|
|
CurrentCap.AGPCommand));
|
|
|
|
Status = AgpLibGetTargetCapability(AgpExtension, &CurrentCap);
|
|
|
|
AGP_ASSERT(NT_SUCCESS(Status));
|
|
AGP_ASSERT(RtlEqualMemory(&CurrentCap.AGPCommand,
|
|
&TargetCap.AGPCommand,
|
|
sizeof(CurrentCap.AGPCommand)));
|
|
|
|
AGPLOG(AGP_NOISE,
|
|
("UAGP35MasterInit: WroteTargetCmd=%08x, ReadTargetCmd=%08lx\n",
|
|
TargetCap.AGPCommand,
|
|
CurrentCap.AGPCommand));
|
|
#endif
|
|
|
|
return Status;
|
|
}
|