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

328 lines
9.6 KiB
C

/*++
Copyright (c) 1996, 1997 Microsoft Corporation
Module Name:
init.c
Abstract:
This module contains the initialization code for AGPALi.SYS.
Author:
John Vert (jvert) 10/21/1997
Modified by:
Chi-Ming Cheng 06/24/1998 Acer Labs, Inc.
Wang-Kai Tsai 08/29/2000 Acer Labs, Inc.
Revision History:
--*/
#include "ALiM1541.h"
ULONG AgpExtensionSize = sizeof(AGPALi_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 VendorId = 0;
PAGPALi_EXTENSION Extension = AgpExtension;
UCHAR HidId;
//
// Make sure we are really loaded only on a ALi chipset
//
ReadConfigUlong(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &VendorId, 0);
ASSERT((VendorId == AGP_ALi_1541_IDENTIFIER) ||
(VendorId == AGP_ALi_1621_IDENTIFIER) ||
(VendorId == AGP_ALi_1631_IDENTIFIER) ||
(VendorId == AGP_ALi_1632_IDENTIFIER) ||
(VendorId == AGP_ALi_1641_IDENTIFIER) ||
(VendorId == AGP_ALi_1644_IDENTIFIER) ||
(VendorId == AGP_ALi_1646_IDENTIFIER) ||
(VendorId == AGP_ALi_1647_IDENTIFIER) ||
(VendorId == AGP_ALi_1651_IDENTIFIER) ||
(VendorId == AGP_ALi_1661_IDENTIFIER) ||
(VendorId == AGP_ALi_1667_IDENTIFIER));
//
// Determine which particular chipset we are running on.
//
if (VendorId == AGP_ALi_1541_IDENTIFIER) {
Extension->ChipsetType = ALi1541;
AgpFlushPages = Agp1541FlushPages;
} else if (VendorId == AGP_ALi_1621_IDENTIFIER) {
Extension->ChipsetType = ALi1621;
ReadConfigUchar(AGP_ALi_GART_BUS_ID, AGP_ALi_GART_SLOT_ID, &HidId, M1621_HIDDEN_REV_ID);
switch (HidId)
{
case 0x31:
Extension->ChipsetType = ALi1631;
break;
case 0x32:
Extension->ChipsetType = ALi1632;
break;
case 0x41:
Extension->ChipsetType = ALi1641;
break;
case 0x43:
Extension->ChipsetType = ALi1621;
break;
default:
Extension->ChipsetType = ALi1621;
break;
}
AgpFlushPages = NULL;
} else if (VendorId == AGP_ALi_1631_IDENTIFIER) {
Extension->ChipsetType = ALi1631;
AgpFlushPages = NULL;
} else if (VendorId == AGP_ALi_1632_IDENTIFIER) {
Extension->ChipsetType = ALi1632;
AgpFlushPages = NULL;
} else if (VendorId == AGP_ALi_1641_IDENTIFIER) {
Extension->ChipsetType = ALi1641;
AgpFlushPages = NULL;
} else if (VendorId == AGP_ALi_1644_IDENTIFIER) {
Extension->ChipsetType = ALi1644;
AgpFlushPages = NULL;
} else if (VendorId == AGP_ALi_1646_IDENTIFIER) {
Extension->ChipsetType = ALi1646;
AgpFlushPages = NULL;
} else if (VendorId == AGP_ALi_1647_IDENTIFIER) {
Extension->ChipsetType = ALi1647;
AgpFlushPages = NULL;
} else if (VendorId == AGP_ALi_1651_IDENTIFIER) {
Extension->ChipsetType = ALi1651;
AgpFlushPages = NULL;
} else if (VendorId == AGP_ALi_1661_IDENTIFIER) {
Extension->ChipsetType = ALi1661;
AgpFlushPages = NULL;
} else if (VendorId == AGP_ALi_1667_IDENTIFIER) {
Extension->ChipsetType = ALi1667;
AgpFlushPages = NULL;
} else {
AGPLOG(AGP_CRITICAL,
("AGPALi - AgpInitializeTarget called for platform %08lx which is not a ALi 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->GartPhysical.QuadPart = 0;
Extension->SpecialTarget = 0;
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;
PAGPALi_EXTENSION Extension = AgpExtension;
ULONG SBAEnable;
ULONG DataRate;
BOOLEAN ReverseInit;
#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,
("AGPALiInitializeDevice - 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,
("AGPALiInitializeDevice - 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);
//
// Before we enable AGP, apply any workarounds
//
AgpWorkaround(Extension);
//
// 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.RequestQueueDepth = TargetCap.AGPStatus.RequestQueueDepthMaximum;
Status = AgpLibSetMasterCapability(AgpExtension, &MasterCap);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_CRITICAL,
("AGPALiInitializeDevice - AgpLibSetMasterCapability %08lx failed %08lx\n",
&MasterCap,
Status));
}
}
//
// Now enable the Target.
//
TargetCap.AGPCommand.Rate = DataRate;
TargetCap.AGPCommand.AGPEnable = 1;
TargetCap.AGPCommand.SBAEnable = SBAEnable;
Status = AgpLibSetPciDeviceCapability(0, 0, &TargetCap);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_CRITICAL,
("AGPALiInitializeDevice - 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;
Status = AgpLibSetMasterCapability(AgpExtension, &MasterCap);
if (!NT_SUCCESS(Status)) {
AGPLOG(AGP_CRITICAL,
("AGPALiInitializeDevice - 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);
}