328 lines
9.6 KiB
C
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);
|
|
}
|