|
|
/*++
Copyright (c) 1996, 1997 Microsoft Corporation
Module Name:
init.c
Abstract:
This module contains the initialization code for the Compaq driver.
Author:
John Vert (jvert) 10/21/1997
Revision History:
12/15/97 John Theisen Modified to support Compaq Chipsets 10/09/98 John Theisen Modified to workaround an RCC silicon bug. If RCC Silicon Rev <= 4, then limit DATA_RATE to 1X. 10/09/98 John Theisen Modified to enable Shadowing in the SP700 prior to MMIO writes. 01/15/98 John Theisen Modified to set RQ depth to be 0x0F for all REV_IDs 03/14/00 Peter Johnston Add support for HE chipset.
--*/
#include "AGPCPQ.H"
ULONG AgpExtensionSize = sizeof(AGPCPQ_EXTENSION); PAGP_FLUSH_PAGES AgpFlushPages = NULL; // not implemented
NTSTATUS AgpInitializeTarget( IN PVOID AgpExtension ) /*******************************************************************************
* * Routine Functional Description: * * This function is the entrypoint for initialization of the AGP Target. It * is called first, and performs initialization of the chipset and extension. * * Assumptions: Regardless of whether we are running on a dual north bridge platform, * this driver will only be installed and invoked once (for the AGP bridge at B0D0F1). * * Arguments: * * AgpExtension -- Supplies the AGP Extension * * Return Value: * * STATUS_SUCCESS if successfull * *******************************************************************************/
{ ULONG DeviceVendorID = 0; ULONG BAR1 = 0; PAGPCPQ_EXTENSION Extension = AgpExtension; PHYSICAL_ADDRESS pa; ULONG BytesReturned = 0;
AGPLOG(AGP_NOISE, ("AgpCpq: AgpInitializeTarget entered.\n")); //
// Initialize our Extension
//
RtlZeroMemory(Extension, sizeof(AGPCPQ_EXTENSION));
//
// Verify that the chipset is a supported RCC Chipset.
//
ReadCPQConfig(&DeviceVendorID,OFFSET_DEVICE_VENDOR_ID,sizeof(DeviceVendorID));
if ((DeviceVendorID != AGP_CNB20_LE_IDENTIFIER) && (DeviceVendorID != AGP_CNB20_HE_IDENTIFIER) && (DeviceVendorID != AGP_CNB20_HE4X_IDENTIFIER) && (DeviceVendorID != AGP_CMIC_GC_IDENTIFIER)) { AGPLOG(AGP_CRITICAL, ("AGPCPQ - AgpInitializeTarget was called for platform %08x, which is not a known RCC AGP chipset!\n", DeviceVendorID)); return(STATUS_UNSUCCESSFUL); }
Extension->DeviceVendorID = DeviceVendorID;
//
// Read the chipset's BAR1 Register, and then map the chipset's
// Memory Mapped Control Registers into kernel mode address space.
//
ReadCPQConfig(&BAR1,OFFSET_BAR1,sizeof(BAR1)); pa.HighPart = 0; pa.LowPart = BAR1; Extension->MMIO = (PMM_CONTROL_REGS)MmMapIoSpace(pa, sizeof(MM_CONTROL_REGS), FALSE);
if (Extension->MMIO == NULL) { AGPLOG(AGP_CRITICAL, ("AgpInitializeTarget - Couldn't allocate %08x bytes for MMIO\n", sizeof(MM_CONTROL_REGS))); return(STATUS_UNSUCCESSFUL); }
//
// Verify that the chipset's Revision ID is correct, but only complain, if it isn't.
//
if (Extension->MMIO->RevisionID < LOWEST_REVISION_ID_SUPPORTED) { AGPLOG(AGP_CRITICAL, ("AgpInitializeTarget - Revision ID = %08x, it should = 1.\n", Extension->MMIO->RevisionID)); }
//
// Determine if there are two RCC North Bridges in this system.
//
DeviceVendorID = 0; BytesReturned = HalGetBusDataByOffset(PCIConfiguration, SECONDARY_LE_BUS_ID, SECONDARY_LE_HOSTPCI_SLOT_ID, &DeviceVendorID, OFFSET_DEVICE_VENDOR_ID, sizeof(DeviceVendorID));
if((DeviceVendorID != Extension->DeviceVendorID) || (BytesReturned != sizeof(DeviceVendorID)) ) { Extension->IsHPSA = FALSE; } else { Extension->IsHPSA = TRUE; }
//
// Enable the GART cache
//
if (Extension->IsHPSA) DnbSetShadowBit(0);
Extension->MMIO->FeatureControl.GARTCacheEnable = 1;
Extension->GartPointer = 0; Extension->SpecialTarget = 0; //
// If the chipset supports linking then enable linking.
//
if (Extension->MMIO->Capabilities.LinkingSupported==1) { Extension->MMIO->FeatureControl.LinkingEnable=1; }
if (Extension->IsHPSA) DnbSetShadowBit(1); return(STATUS_SUCCESS); }
NTSTATUS AgpInitializeMaster( IN PVOID AgpExtension, OUT ULONG *AgpCapabilities ) /*******************************************************************************
* * Routine Functional Description: * * This function is the entrypoint for initialization of the AGP Master. It * is called after Target initialization, and is intended to be used to * initialize the AGP capabilities of both master and target. * * Arguments: * * AgpExtension -- Supplies the AGP Extension * * AgpCapabilities -- Returns the "software-visible" capabilities of the device * * Return Value: * * NTSTATUS * *******************************************************************************/
{ NTSTATUS Status; PCI_AGP_CAPABILITY MasterCap; PCI_AGP_CAPABILITY TargetCap; PAGPCPQ_EXTENSION Extension = AgpExtension; ULONG SBAEnable; ULONG FastWrite; ULONG DataRate; UCHAR RevID = 0; BOOLEAN ReverseInit;
AGPLOG(AGP_NOISE, ("AgpCpq: AgpInitializeMaster entered.\n"));
//
// Get the master and target AGP capabilities
//
Status = AgpLibGetMasterCapability(AgpExtension, &MasterCap); if (!NT_SUCCESS(Status)) { AGPLOG(AGP_CRITICAL, ("AGPCPQInitializeDevice - AgpLibGetMasterCapability failed %08lx\n", Status)); return(Status); }
Status = AgpLibGetPciDeviceCapability(AGP_CPQ_BUS_ID, AGP_CPQ_PCIPCI_SLOT_ID, &TargetCap); if (!NT_SUCCESS(Status)) { AGPLOG(AGP_CRITICAL, ("AGPCPQInitializeDevice - AgpLibGetPciDeviceCapability failed %08lx\n", Status)); 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); }
//
// FIX RCC silicon bugs:
// If RevID <= 4, then the reported Data Rate is 2X but the chip only supports 1X.
// Regardless of RevID the reported RQDepth should be 0x0F.
//
if (Extension->DeviceVendorID == AGP_CNB20_LE_IDENTIFIER) { ReadCPQConfig(&RevID, OFFSET_REV_ID, sizeof(RevID));
ASSERT(TargetCap.AGPStatus.RequestQueueDepthMaximum == 0x10); TargetCap.AGPStatus.RequestQueueDepthMaximum = 0x0F;
if (RevID <= MAX_REV_ID_TO_LIMIT_1X) { DataRate = PCI_AGP_RATE_1X; } }
//
// 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 = 1; MasterCap.AGPCommand.SBAEnable = SBAEnable; MasterCap.AGPCommand.FastWriteEnable = FastWrite; MasterCap.AGPCommand.RequestQueueDepth = TargetCap.AGPStatus.RequestQueueDepthMaximum; Status = AgpLibSetMasterCapability(AgpExtension, &MasterCap); if (!NT_SUCCESS(Status)) { AGPLOG(AGP_CRITICAL, ("AGPCPQInitializeDevice - 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; Status = AgpLibSetPciDeviceCapability(AGP_CPQ_BUS_ID, AGP_CPQ_PCIPCI_SLOT_ID, &TargetCap); if (!NT_SUCCESS(Status)) { AGPLOG(AGP_CRITICAL, ("AGPCPQInitializeDevice - 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.FastWriteEnable = FastWrite; MasterCap.AGPCommand.RequestQueueDepth = TargetCap.AGPStatus.RequestQueueDepthMaximum; Status = AgpLibSetMasterCapability(AgpExtension, &MasterCap); if (!NT_SUCCESS(Status)) { AGPLOG(AGP_CRITICAL, ("AGPCPQInitializeDevice - AgpLibSetMasterCapability %08lx failed %08lx\n", &MasterCap, Status)); } }
#if DBG
{ PCI_AGP_CAPABILITY CurrentCap;
//
// 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(AGP_CPQ_BUS_ID, AGP_CPQ_PCIPCI_SLOT_ID, &CurrentCap); ASSERT(NT_SUCCESS(Status)); ASSERT(RtlEqualMemory(&CurrentCap.AGPCommand, &TargetCap.AGPCommand, sizeof(CurrentCap.AGPCommand))); } #endif
//
// Indicate that we can map memory through the GART aperture
//
*AgpCapabilities = AGP_CAPABILITIES_MAP_PHYSICAL;
return(Status); }
NTSTATUS DnbSetShadowBit( ULONG SetToOne ) //
// This routine is required, (because of a new requirement in the RCC chipset.).
// When there are two NorthBridge's, the shadow bit must be set to 0 prior
// to any MMIO writes, and then set back to 1 when done.
//
{ NTSTATUS Status = STATUS_SUCCESS; // Assume Success
UCHAR ShadowByte = 0; ULONG BytesReturned = 0; ULONG length = 1;
if (SetToOne == 1) {
//
// Set the shadow bit to a one. (This disables shadowing.)
//
BytesReturned = HalGetBusDataByOffset(PCIConfiguration, SECONDARY_LE_BUS_ID, SECONDARY_LE_HOSTPCI_SLOT_ID, &ShadowByte, OFFSET_SHADOW_BYTE, length);
if(BytesReturned != length) { AGPLOG(AGP_CRITICAL,("ERROR: Failed to read shadow register!\n")); Status = STATUS_UNSUCCESSFUL; goto exit_routine; }
ShadowByte |= FLAG_DISABLE_SHADOW;
HalSetBusDataByOffset(PCIConfiguration, SECONDARY_LE_BUS_ID, SECONDARY_LE_HOSTPCI_SLOT_ID, &ShadowByte, OFFSET_SHADOW_BYTE, length);
if(BytesReturned != length) { AGPLOG(AGP_CRITICAL,("ERROR: Failed to write shadow register!\n")); Status = STATUS_UNSUCCESSFUL; goto exit_routine; }
} else {
//
// Set the shadow bit to a zero. (This enables shadowing.)
//
BytesReturned = HalGetBusDataByOffset(PCIConfiguration, SECONDARY_LE_BUS_ID, SECONDARY_LE_HOSTPCI_SLOT_ID, &ShadowByte, OFFSET_SHADOW_BYTE, length);
if(BytesReturned != length) { AGPLOG(AGP_CRITICAL,("ERROR: Failed to read shadow register!")); Status = STATUS_UNSUCCESSFUL; goto exit_routine; }
ShadowByte &= MASK_ENABLE_SHADOW;
HalSetBusDataByOffset(PCIConfiguration, SECONDARY_LE_BUS_ID, SECONDARY_LE_HOSTPCI_SLOT_ID, &ShadowByte, OFFSET_SHADOW_BYTE, length);
if(BytesReturned != length) { AGPLOG(AGP_CRITICAL,("ERROR: Failed to write shadow register!")); Status = STATUS_UNSUCCESSFUL; goto exit_routine; } }
exit_routine:
return(Status); }
|