windows-nt/Source/XPSP1/NT/base/busdrv/agp/viaagp/init.c

574 lines
16 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1998 VIA Technologies, Inc. and Microsoft Corporation.
Module Name:
init.c
Abstract:
This module contains the initialization code for VIAAGP.SYS.
Revision History:
--*/
#include "viaagp.h"
ULONG AgpExtensionSize = sizeof(AGPVIA_EXTENSION);
PAGP_FLUSH_PAGES AgpFlushPages = NULL; // not implemented
VOID
AgpTweak(
VOID
)
/*++
Routine Description:
Check VIA rev and video device, then tweak config accordingly
Parameters:
None
Return Value:
None
--*/
{
ULONG ulNB_ID, ulVGA_ID, ulNB_Rev=0xFFFFFFFF, ulNB_Version=0xFFFFFFFF;
ULONG ulTmpPhysAddr;
UCHAR bVMask, bVOrg;
UCHAR i, bMaxItem=20;
//----------------------------------------------------------------
//Patch Mapping Table
//----------------------------------------------------------------
ULONG NBtable[11] =
{
//VT3054 VT3055 VT3062 VT3064 VT3056
0x059700FF, 0x0598000F, 0x0598101F, 0x0501000F, 0x0691000F,
//VT3063 VT3073 VT3075 VT3085 VT3067
0x0691202F, 0x0691404F, 0x0691808F, 0x0691C0CF, 0x0601000F, 0xFFFFFFFF
};
ULONG NBVersion[11] =
{
0x3054, 0x3055, 0x3062, 0x3064, 0x3056,
0x3063, 0x3073, 0x3075, 0x3085, 0x3067, 0xFFFFFFFF
};
#ifdef AGP_440
DbgPrint("FineTune\n");
#endif
//----------------------------------------------------------------
//Find the type of North Bridge (device id, revision #)
//----------------------------------------------------------------
//
//Save back door value and close back door
//
ReadVIAConfig(&bVOrg, 0xFC, sizeof(bVOrg));
bVMask=bVOrg & 0xFE;
WriteVIAConfig(&bVMask, 0xFC, sizeof(bVMask));
ReadVIAConfig(&ulNB_ID, 0x00, sizeof(ulNB_ID))
ulNB_ID=ulNB_ID&0xFFFF0000;
ReadVIAConfig(&ulNB_Rev, 0x08, sizeof(ulNB_Rev));
ulNB_Rev=ulNB_Rev&0x000000FF;
ulNB_ID=ulNB_ID | (ulNB_Rev<<8) | ulNB_Rev;
WriteVIAConfig(&bVOrg, 0xFC, sizeof(bVOrg));
//
//Find the type of North Bridge from the predefined NBtable
//
for ( i=0; i<bMaxItem; i++ )
{
if ( (NBtable[i]&0xFFFF0000) == (ulNB_ID&0xFFFF0000) )
{
if ( ((NBtable[i]&0x0000FF00)<=(ulNB_ID&0x0000FF00)) && ((NBtable[i]&0x000000FF)>=(ulNB_ID&0x000000FF)) )
{
ulNB_Version=NBVersion[i];
break;
}
}
if ( NBtable[i]==0xFFFFFFFF )
{
break;
}
}
//----------------------------------------------------------------
// General Case for NB
//----------------------------------------------------------------
//
//Stephen Add Start, If Socket 7's chipset, write 1 to Rx51 bit 6;
//
if ( (ulNB_ID & 0xFF000000) == 0x05000000) {
ReadVIAConfig(&bVMask, 0x51, sizeof(bVMask));
bVMask=bVMask|0x40;
WriteVIAConfig(&bVMask, 0x51, sizeof(bVMask));
}
//
// For the specific NB
//
switch(ulNB_Version)
{
case 0x3054:
break;
case 0x3055:
// 51[7]=1, 51[6]=1, AC[2]=1
if ( ulNB_Rev > 3 )
{
ReadVIAConfig(&bVMask, 0x51, sizeof(bVMask));
bVMask=bVMask|0xC0;
WriteVIAConfig(&bVMask, 0x51, sizeof(bVMask));
ReadVIAConfig(&bVMask, 0xAC, sizeof(bVMask));
bVMask=bVMask|0x04;
WriteVIAConfig(&bVMask, 0xAC, sizeof(bVMask));
}
break;
case 0x3056:
// 69[1]=1, 69[0]=1, AC[2]=1, AC[5]=1
ReadVIAConfig(&bVMask, 0x69, sizeof(bVMask));
bVMask=bVMask|0x03;
WriteVIAConfig(&bVMask, 0x69, sizeof(bVMask));
ReadVIAConfig(&bVMask, 0xAC, sizeof(bVMask));
bVMask=bVMask|0x24;
WriteVIAConfig(&bVMask, 0xAC, sizeof(bVMask));
break;
case 0x3062:
case 0x3063:
case 0x3064:
case 0x3073:
case 0x3075:
case 0x3085:
case 0x3067:
// AC[6]=1, AC[5]=1
ReadVIAConfig(&bVMask, 0xAC, sizeof(bVMask));
bVMask=bVMask|0x60;
WriteVIAConfig(&bVMask, 0xAC, sizeof(bVMask));
break;
default:
break;
}
//----------------------------------------------------------------
//Find the type of AGP VGA Card (vender id, device id, revision #)
//Bus 1, Device 0, Function 0
//----------------------------------------------------------------
ReadVGAConfig(&ulVGA_ID, 0x00, sizeof(ulVGA_ID));
#ifdef AGP_440
DbgPrint("\nPatch for ulNB_Version=%x (ulNB_ID=%x), ulVGA_ID=%x",ulNB_Version,ulNB_ID,ulVGA_ID);
#endif
//----------------------------------------------------------------
//Patch the Compatibility between VGA Card and North Bridge
//----------------------------------------------------------------
//
// Switch 1. For all cards of the same vender
//
switch(ulVGA_ID&0x0000FFFF)
{
//ATI
case 0x00001002:
switch(ulNB_Version)
{
case 0x3055:
case 0x3054:
case 0x3056:
// P2P, 40[7]=0
ReadP2PConfig(&bVMask, 0x40, sizeof(bVMask));
bVMask=bVMask&0x7F;
WriteP2PConfig(&bVMask, 0x40, sizeof(bVMask));
break;
}
break;
//3DLAB
case 0x0000104C:
if (ulNB_Version==0x3063)
{
// AC[1]=0
ReadVIAConfig(&bVMask, 0xAC, sizeof(bVMask));
bVMask=bVMask&0xFD;
WriteVIAConfig(&bVMask, 0xAC, sizeof(bVMask));
}
break;
}
//
// Switch 2. For the specific card
//
switch(ulVGA_ID)
{
//ATIRage128
case 0x52461002:
switch(ulNB_Version)
{
case 0x3056:
// P2P, 40[7]=0
ReadP2PConfig(&bVMask, 0x40, sizeof(bVMask));
bVMask=bVMask&0x7F;
WriteP2PConfig(&bVMask, 0x40, sizeof(bVMask));
break;
case 0x3063:
if (ulNB_Rev == 6)
{
// P2P, 40[7]=1
ReadP2PConfig(&bVMask, 0x40, sizeof(bVMask));
bVMask=bVMask|0x80;
WriteP2PConfig(&bVMask, 0x40, sizeof(bVMask));
}
else
{
// P2P, 40[7]=0
ReadP2PConfig(&bVMask, 0x40, sizeof(bVMask));
bVMask=bVMask&0x7F;
WriteP2PConfig(&bVMask, 0x40, sizeof(bVMask));
}
break;
}
break;
//TNT
case 0x002010DE:
switch(ulNB_Version)
{
case 0x3056:
case 0x3063:
case 0x3073:
// P2P, 40[1]=0
ReadP2PConfig(&bVMask, 0x40, sizeof(bVMask));
bVMask=bVMask&0xFD;
WriteP2PConfig(&bVMask, 0x40, sizeof(bVMask));
// 70[2]=0
ReadVIAConfig(&bVMask, 0x70, sizeof(bVMask));
bVMask=bVMask&0xFB;
WriteVIAConfig(&bVMask, 0x70, sizeof(bVMask));
break;
}
break;
//S33D
case 0x8A225333:
if (ulNB_Version==0x3063)
if (ulNB_Rev==6)
{
// P2P, 40[7]=0
ReadP2PConfig(&bVMask, 0x40, sizeof(bVMask));
bVMask=bVMask&0x7F;
WriteP2PConfig(&bVMask, 0x40, sizeof(bVMask));
}
break;
}
}
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 VendorId = 0;
PAGPVIA_EXTENSION Extension = AgpExtension;
VIA_GATT_BASE GARTBASE_Config;
//
// Make sure we are really loaded only on a VIA chipset
//
ReadVIAConfig(&VendorId,0,sizeof(VendorId));
VendorId &= 0x0000FFFF;
ASSERT(VendorId == AGP_VIA_IDENTIFIER);
if (VendorId != AGP_VIA_IDENTIFIER) {
AGPLOG(AGP_CRITICAL,
("VIAAGP - AgpInitializeTarget called for platform %08lx which is not a VIA chipset!\n",
VendorId));
return(STATUS_UNSUCCESSFUL);
}
//
// Initialize our chipset-specific extension
//
Extension->ApertureStart.QuadPart = 0;
Extension->ApertureLength = 0;
Extension->Gart = NULL;
Extension->GartLength = 0;
Extension->GlobalEnable = FALSE;
Extension->PCIEnable = FALSE;
Extension->GartPhysical.QuadPart = 0;
Extension->SpecialTarget = 0;
//
// Check whether the chipset support Flush TLB or not
// 88[2]=0, support FLUSH TLB
//
ReadVIAConfig(&GARTBASE_Config, GATTBASE_OFFSET, sizeof(GARTBASE_Config));
if ( GARTBASE_Config.TLB_Timing == 0) {
Extension->Cap_FlushTLB = TRUE;
} else {
Extension->Cap_FlushTLB = FALSE;
}
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.
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;
PAGPVIA_EXTENSION Extension = AgpExtension;
ULONG SBAEnable;
ULONG DataRate;
ULONG FastWrite;
ULONG FourGB;
VIA_GART_TLB_CTRL AGPCTRL_Config;
VIA_GATT_BASE GARTBASE_Config;
VREF_REG VREF_Config;
BOOLEAN ReverseInit;
AGPMISC_REG AGPMISC_Config;
#if DBG
PCI_AGP_CAPABILITY CurrentCap;
#endif
//
// Indicate that we can map memory through the GART aperture
//
*AgpCapabilities = AGP_CAPABILITIES_MAP_PHYSICAL;
//
// Get the master and target AGP capabilities
//
Status = AgpLibGetMasterCapability(AgpExtension, &MasterCap);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_CRITICAL,
("AGPVIAInitializeDevice - 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,
("AGP440InitializeDevice - AgpLibGetMasterCapability returned no valid transfer rate\n"));
return(STATUS_INVALID_DEVICE_REQUEST);
}
Status = AgpLibGetPciDeviceCapability(0,0,&TargetCap);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_CRITICAL,
("AGPVIAInitializeDevice - 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;
//
//Disable FW capability
//
TargetCap.AGPStatus.FastWrite = 0;
ReadVIAConfig(&AGPMISC_Config, AGPMISC_OFFSET, sizeof(AGPMISC_Config));
AGPMISC_Config.FW_Support = 0;
WriteVIAConfig(&AGPMISC_Config, AGPMISC_OFFSET, sizeof(AGPMISC_Config));
}
//
// 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);
}
//
// Set the VREF, RxB0[7].
// 4x -> STB#
// 1x, 2x -> AGPREF
//
ReadVIAConfig(&VREF_Config, VREF_OFFSET, sizeof(VREF_Config));
if (DataRate == PCI_AGP_RATE_4X) {
VREF_Config.VREF_Control = 0;
} else {
VREF_Config.VREF_Control = 1;
}
WriteVIAConfig(&VREF_Config, VREF_OFFSET, sizeof(VREF_Config));
//
// 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 FourGB if both master and target support it.
//
FourGB = (TargetCap.AGPStatus.FourGB & MasterCap.AGPStatus.FourGB);
//
// Fine tune the Compatibility between VGA Card and North Bridge
//
AgpTweak();
//
// Enable the Master
//
ReverseInit =
(Extension->SpecialTarget & AGP_FLAG_REVERSE_INITIALIZATION) ==
AGP_FLAG_REVERSE_INITIALIZATION;
if (ReverseInit) {
MasterCap.AGPCommand.Rate = DataRate;
MasterCap.AGPCommand.AGPEnable = 1;
MasterCap.AGPCommand.SBAEnable = SBAEnable;
MasterCap.AGPCommand.RequestQueueDepth = TargetCap.AGPStatus.RequestQueueDepthMaximum;
MasterCap.AGPCommand.FastWriteEnable = FastWrite;
MasterCap.AGPCommand.FourGBEnable = FourGB;
Status = AgpLibSetMasterCapability(AgpExtension, &MasterCap);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_CRITICAL,
("AGPVIAInitializeDevice - AgpLibSetMasterCapability %08lx failed %08lx\n",
&MasterCap,
Status));
}
}
//
// Now enable the Target
//
TargetCap.AGPCommand.Rate = DataRate;
TargetCap.AGPCommand.AGPEnable = 1;
TargetCap.AGPCommand.SBAEnable = SBAEnable;
TargetCap.AGPCommand.FastWriteEnable = FastWrite;
TargetCap.AGPCommand.FourGBEnable = FourGB;
Status = AgpLibSetPciDeviceCapability(0, 0, &TargetCap);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_CRITICAL,
("AGPVIAInitializeDevice - AgpLibSetPciDeviceCapability %08lx for target failed %08lx\n",
&TargetCap,
Status));
return(Status);
}
if (!ReverseInit) {
MasterCap.AGPCommand.Rate = DataRate;
MasterCap.AGPCommand.AGPEnable = 1;
MasterCap.AGPCommand.SBAEnable = SBAEnable;
MasterCap.AGPCommand.RequestQueueDepth = TargetCap.AGPStatus.RequestQueueDepthMaximum;
MasterCap.AGPCommand.FastWriteEnable = FastWrite;
MasterCap.AGPCommand.FourGBEnable = FourGB;
Status = AgpLibSetMasterCapability(AgpExtension, &MasterCap);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_CRITICAL,
("AGPVIAInitializeDevice - 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);
ASSERT(NT_SUCCESS(Status));
ASSERT(RtlEqualMemory(&CurrentCap.AGPCommand, &TargetCap.AGPCommand, sizeof(CurrentCap.AGPCommand)));
#endif
return(Status);
}