windows-nt/Source/XPSP1/NT/base/busdrv/agp/agp460/init.c
2020-09-26 16:20:57 +08:00

380 lines
11 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
init.c
Abstract:
This module contains the initialization code for AGP460.SYS.
Author:
Naga Gurumoorthy 6/11/1999
Revision History:
--*/
#include "agp460.h"
ULONG AgpExtensionSize = sizeof(AGP460_EXTENSION);
PAGP_FLUSH_PAGES AgpFlushPages;
NTSTATUS
AgpInitializeTarget(
IN PVOID AgpExtension
)
/*++
Routine Description:
Entrypoint for target initialization. This is called first.
Arguments:
AgpExtension - Supplies the AGP extension
Return Value:
NTSTATUS
--*/
{
ULONG DeviceVendorID = 0;
PAGP460_EXTENSION Extension = AgpExtension;
AGPLOG(AGP_NOISE, ("AGP460: AgpInitializeTarget entered.\n"));
//
// Initialize our Extension
//
RtlZeroMemory(Extension, sizeof(AGP460_EXTENSION));
//
// TO DO: Check the Device & Vendor ID for 82460GX. - Naga G
//
//
// Initialize our chipset-specific extension
//
Extension->ApertureStart.QuadPart = 0;
Extension->ApertureLength = 0;
Extension->Gart = NULL;
Extension->GartLength = 0;
Extension->GlobalEnable = FALSE;
Extension->ChipsetPageSize = PAGESIZE_460GX_CHIPSET;
Extension->GartPhysical.QuadPart = 0;
Extension->bSupportMultipleAGPDevices = FALSE;
Extension->bSupportsCacheCoherency = TRUE;
Extension->SpecialTarget = 0;
AgpFlushPages = Agp460FlushPages;
AGPLOG(AGP_NOISE, ("AGP460: Leaving AgpInitializeTarget.\n"));
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 the AGP extension
AgpCapabilities - Returns the capabilities of this AGP device.
Return Value:
STATUS_SUCCESS
--*/
{
NTSTATUS Status;
PCI_AGP_CAPABILITY MasterCap;
PCI_AGP_CAPABILITY TargetCap;
PAGP460_EXTENSION Extension = AgpExtension;
ULONG SBAEnable;
ULONG DataRate;
ULONG FastWrite;
ULONG CBN;
BOOLEAN ReverseInit;
#if DBG
PCI_AGP_CAPABILITY CurrentCap;
#endif
AGPLOG(AGP_NOISE, ("AGP460: AgpInitializeMaster entered.\n"));
//
// VERY IMPORTANT: In 82460GX, the GART is not part of the main memory (though it
// occupies a range in the address space) and is instead hanging off the GXB. This
// will make accesses from the Graphics Card to the GART pretty fast. But, the price
// we pay - processor can't access the GART. Therefore, we tell the rest of the
// world that is NOT OK to map the physical addresses given by GART. Instead processor
// accesses should use the MDL. This is done by setting the capabilities to 0.
// - Naga G
//
*AgpCapabilities = 0;
//
// Get the master and target AGP capabilities
//
Status = AgpLibGetMasterCapability(AgpExtension, &MasterCap);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_CRITICAL,
("AGP460InitializeDevice - 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,
("AGP460InitializeDevice - AgpLibGetMasterCapability returned no valid transfer rate\n"));
return(STATUS_INVALID_DEVICE_REQUEST);
}
// We can't get the capability for bus 0, dev 0 in 460GX. it is the SAC & we want the
// GXB (Target).
//Status = AgpLibGetPciDeviceCapability(0,0,&TargetCap);
Read460CBN((PVOID)&CBN);
// CBN is of one byte width, so zero out the other bits from 32-bits - Sunil
EXTRACT_LSBYTE(CBN);
Status = AgpLibGetPciDeviceCapability(CBN,AGP460_GXB_SLOT_ID,&TargetCap);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_CRITICAL,
("AGP460InitializeDevice - AgpLibGetPciDeviceCapability failed %08lx\n"));
return(Status);
}
//
// Determine the greatest common denominator for data rate.
//
DataRate = TargetCap.AGPStatus.Rate & MasterCap.AGPStatus.Rate;
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);
}
//
// 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 the Master first.
//
ReverseInit =
(Extension->SpecialTarget & AGP_FLAG_REVERSE_INITIALIZATION) ==
AGP_FLAG_REVERSE_INITIALIZATION;
if (ReverseInit) {
MasterCap.AGPCommand.Rate = DataRate;
MasterCap.AGPCommand.AGPEnable = TRUE;
MasterCap.AGPCommand.SBAEnable = SBAEnable;
MasterCap.AGPCommand.FastWriteEnable = FastWrite;
MasterCap.AGPCommand.FourGBEnable = FALSE;
MasterCap.AGPCommand.RequestQueueDepth = TargetCap.AGPStatus.RequestQueueDepthMaximum;
Status = AgpLibSetMasterCapability(AgpExtension, &MasterCap);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_CRITICAL,
("AGP460InitializeDevice - AgpLibSetMasterCapability %08lx failed %08lx\n",
&MasterCap,
Status));
}
}
//
// Now enable the Target.
//
TargetCap.AGPCommand.Rate = DataRate;
TargetCap.AGPCommand.AGPEnable = TRUE;
TargetCap.AGPCommand.SBAEnable = SBAEnable;
TargetCap.AGPCommand.FastWriteEnable = FastWrite;
TargetCap.AGPCommand.FourGBEnable = FALSE;
Status = AgpLibSetPciDeviceCapability(CBN, AGP460_GXB_SLOT_ID, &TargetCap);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_CRITICAL,
("AGP460InitializeDevice - AgpLibSetPciDeviceCapability %08lx for target failed %08lx\n",
&TargetCap,
Status));
return(Status);
}
if (!ReverseInit) {
MasterCap.AGPCommand.Rate = DataRate;
MasterCap.AGPCommand.AGPEnable = TRUE;
MasterCap.AGPCommand.SBAEnable = SBAEnable;
MasterCap.AGPCommand.FastWriteEnable = FastWrite;
MasterCap.AGPCommand.FourGBEnable = FALSE;
MasterCap.AGPCommand.RequestQueueDepth = TargetCap.AGPStatus.RequestQueueDepthMaximum;
Status = AgpLibSetMasterCapability(AgpExtension, &MasterCap);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_CRITICAL,
("AGP460InitializeDevice - AgpLibSetMasterCapability %08lx failed %08lx\n",
&MasterCap,
Status));
}
}
#if DBG
//
// Read them back, see if it worked
//
Status = AgpLibGetMasterCapability(AgpExtension, &CurrentCap);
ASSERT(NT_SUCCESS(Status));
//
// If the target request queue depth is greater than the master will
// allow, it will be trimmed. Loosen the assert to not require an
// exact match.
//
ASSERT(CurrentCap.AGPCommand.RequestQueueDepth <= MasterCap.AGPCommand.RequestQueueDepth);
CurrentCap.AGPCommand.RequestQueueDepth = MasterCap.AGPCommand.RequestQueueDepth;
ASSERT(RtlEqualMemory(&CurrentCap.AGPCommand, &MasterCap.AGPCommand, sizeof(CurrentCap.AGPCommand)));
// Status = AgpLibGetPciDeviceCapability(0,0,&CurrentCap);
Status = AgpLibGetPciDeviceCapability(CBN,AGP460_GXB_SLOT_ID,&CurrentCap);
ASSERT(NT_SUCCESS(Status));
ASSERT(RtlEqualMemory(&CurrentCap.AGPCommand, &TargetCap.AGPCommand, sizeof(CurrentCap.AGPCommand)));
#endif
AGPLOG(AGP_NOISE, ("AGP460: Leaving AgpInitializeMaster.\n"));
return(Status);
}
NTSTATUS
Agp460FlushPages(
IN PAGP460_EXTENSION AgpContext,
IN PMDL Mdl
)
/*++
Routine Description:
Flush entries in the GART. Currently a stub for
Win64 version of 460GX filter driver. This flushing is done previously to
avoid any caching issues due to the same memory aliased with different caching
attributes. Now that is taken care by the memory manager calls themselves (Win64 only).
Therefore we just have a stub so that nothing gets executed in the AGPLIB code. (see
AGPLIB code for details)
Arguments:
AgpContext - Supplies the AGP context
Mdl - Supplies the MDL describing the physical pages to be flushed
Return Value:
STATUS_SUCCESS
--*/
{
AGPLOG(AGP_NOISE, ("AGP460: Entering AGPFlushPages.\n"));
AGPLOG(AGP_NOISE, ("AGP460: Leaving AGPFlushPages.\n"));
return STATUS_SUCCESS;
}
void Read460CBN(PVOID _CBN_)
{
ULONG _len_;
_len_ = HalGetBusDataByOffset(PCIConfiguration,
AGP460_SAC_BUS_ID,
AGP460_SAC_CBN_SLOT_ID,
_CBN_,
0x40,
1);
ASSERT(_len_ == 1);
return;
}
void Read460Config(ULONG _CBN_,PVOID _buf_,ULONG _offset_,ULONG _size_)
{
ULONG _len_;
_len_ = HalGetBusDataByOffset(PCIConfiguration,
_CBN_,
AGP460_GXB_SLOT_ID,
_buf_,
_offset_,
_size_);
ASSERT(_len_ == (_size_));
return;
}
void Write460Config(ULONG _CBN_,PVOID _buf_,ULONG _offset_,ULONG _size_)
{
ULONG _len_;
_len_ = HalSetBusDataByOffset(PCIConfiguration,
(_CBN_),
AGP460_GXB_SLOT_ID,
(_buf_),
(_offset_),
(_size_));
ASSERT(_len_ == (_size_));
return;
}