916 lines
23 KiB
C
916 lines
23 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1997 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
config.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Routines for accessing config space in the PCI-PCI bridge
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
John Vert (jvert) 10/27/1997
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
#include "agplib.h"
|
|||
|
|
|||
|
typedef struct _BUS_SLOT_ID {
|
|||
|
ULONG BusId;
|
|||
|
ULONG SlotId;
|
|||
|
} BUS_SLOT_ID, *PBUS_SLOT_ID;
|
|||
|
|
|||
|
//
|
|||
|
// Local function prototypes
|
|||
|
//
|
|||
|
NTSTATUS
|
|||
|
ApGetSetDeviceBusData(
|
|||
|
IN PCOMMON_EXTENSION Extension,
|
|||
|
IN BOOLEAN Read,
|
|||
|
IN PVOID Buffer,
|
|||
|
IN ULONG Offset,
|
|||
|
IN ULONG Length
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
ApGetSetBusData(
|
|||
|
IN PBUS_SLOT_ID BusSlotId,
|
|||
|
IN BOOLEAN Read,
|
|||
|
IN PVOID Buffer,
|
|||
|
IN ULONG Offset,
|
|||
|
IN ULONG Length
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
ApFindAgpCapability(
|
|||
|
IN PAGP_GETSET_CONFIG_SPACE pConfigFn,
|
|||
|
IN PVOID Context,
|
|||
|
OUT PPCI_AGP_CAPABILITY Capability,
|
|||
|
OUT UCHAR *pOffset,
|
|||
|
OUT PPCI_COMMON_CONFIG PciCommonConfig OPTIONAL
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
ApQueryBusInterface(
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
OUT PBUS_INTERFACE_STANDARD BusInterface
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Sends a query-interface IRP to the specified device object
|
|||
|
to obtain the BUS_INTERFACE_STANDARD interface.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DeviceObject - Supplies the device object to send the BUS_INTERFACE_STANDARD to
|
|||
|
|
|||
|
BusInterface - Returns the bus interface
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS if successful
|
|||
|
NTSTATUS if unsuccessful
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PIRP Irp;
|
|||
|
KEVENT Event;
|
|||
|
PIO_STACK_LOCATION IrpSp;
|
|||
|
IO_STATUS_BLOCK IoStatusBlock;
|
|||
|
NTSTATUS Status;
|
|||
|
ULONG ReturnLength;
|
|||
|
|
|||
|
KeInitializeEvent( &Event, NotificationEvent, FALSE );
|
|||
|
Irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP,
|
|||
|
DeviceObject,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
&Event,
|
|||
|
&IoStatusBlock );
|
|||
|
if (Irp == NULL) {
|
|||
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|||
|
}
|
|||
|
|
|||
|
IrpSp = IoGetNextIrpStackLocation( Irp );
|
|||
|
ASSERT(IrpSp != NULL);
|
|||
|
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED ;
|
|||
|
IrpSp->MajorFunction = IRP_MJ_PNP;
|
|||
|
IrpSp->MinorFunction = IRP_MN_QUERY_INTERFACE;
|
|||
|
IrpSp->Parameters.QueryInterface.InterfaceType = (LPGUID)&GUID_BUS_INTERFACE_STANDARD;
|
|||
|
IrpSp->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
|
|||
|
IrpSp->Parameters.QueryInterface.Version = 1;
|
|||
|
IrpSp->Parameters.QueryInterface.Interface = (PINTERFACE) BusInterface;
|
|||
|
IrpSp->Parameters.QueryInterface.InterfaceSpecificData = NULL;
|
|||
|
|
|||
|
Status = IoCallDriver(DeviceObject, Irp);
|
|||
|
if (Status == STATUS_PENDING) {
|
|||
|
KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL );
|
|||
|
Status = Irp->IoStatus.Status;
|
|||
|
}
|
|||
|
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
ApGetSetDeviceBusData(
|
|||
|
IN PCOMMON_EXTENSION Extension,
|
|||
|
IN BOOLEAN Read,
|
|||
|
IN PVOID Buffer,
|
|||
|
IN ULONG Offset,
|
|||
|
IN ULONG Length
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Reads or writes PCI config space for the specified device.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Extension - Supplies the common AGP extension
|
|||
|
|
|||
|
Read - if TRUE, this is a READ IRP
|
|||
|
if FALSE, this is a WRITE IRP
|
|||
|
|
|||
|
Buffer - Returns the PCI config data
|
|||
|
|
|||
|
Offset - Supplies the offset into the PCI config data where the read should begin
|
|||
|
|
|||
|
Length - Supplies the number of bytes to be read
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
ULONG ReturnLength;
|
|||
|
ULONG Transferred;
|
|||
|
|
|||
|
//
|
|||
|
// First check our device extension. This must be either a master
|
|||
|
// or target extension, we don't care too much which.
|
|||
|
//
|
|||
|
ASSERT((Extension->Signature == TARGET_SIG) ||
|
|||
|
(Extension->Signature == MASTER_SIG));
|
|||
|
|
|||
|
//
|
|||
|
// Now we simply use our bus interface to call directly to PCI.
|
|||
|
//
|
|||
|
|
|||
|
if (Read) {
|
|||
|
Transferred = Extension->BusInterface.GetBusData(Extension->BusInterface.Context,
|
|||
|
PCI_WHICHSPACE_CONFIG,
|
|||
|
Buffer,
|
|||
|
Offset,
|
|||
|
Length);
|
|||
|
} else {
|
|||
|
Transferred = Extension->BusInterface.SetBusData(Extension->BusInterface.Context,
|
|||
|
PCI_WHICHSPACE_CONFIG,
|
|||
|
Buffer,
|
|||
|
Offset,
|
|||
|
Length);
|
|||
|
}
|
|||
|
if (Transferred == Length) {
|
|||
|
return(STATUS_SUCCESS);
|
|||
|
} else {
|
|||
|
return(STATUS_UNSUCCESSFUL);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
ApGetSetBusData(
|
|||
|
IN PBUS_SLOT_ID BusSlotId,
|
|||
|
IN BOOLEAN Read,
|
|||
|
IN PVOID Buffer,
|
|||
|
IN ULONG Offset,
|
|||
|
IN ULONG Length
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Calls HalGet/SetBusData for the specified PCI bus/slot ID.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BusSlotId - Supplies the bus and slot ID.
|
|||
|
|
|||
|
Read - if TRUE, this is a GetBusData
|
|||
|
if FALSE, this is a SetBusData
|
|||
|
|
|||
|
Buffer - Returns the PCI config data
|
|||
|
|
|||
|
Offset - Supplies the offset into the PCI config data where the read should begin
|
|||
|
|
|||
|
Length - Supplies the number of bytes to be read
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ULONG Transferred;
|
|||
|
|
|||
|
if (Read) {
|
|||
|
Transferred = HalGetBusDataByOffset(PCIConfiguration,
|
|||
|
BusSlotId->BusId,
|
|||
|
BusSlotId->SlotId,
|
|||
|
Buffer,
|
|||
|
Offset,
|
|||
|
Length);
|
|||
|
} else {
|
|||
|
Transferred = HalSetBusDataByOffset(PCIConfiguration,
|
|||
|
BusSlotId->BusId,
|
|||
|
BusSlotId->SlotId,
|
|||
|
Buffer,
|
|||
|
Offset,
|
|||
|
Length);
|
|||
|
|
|||
|
}
|
|||
|
if (Transferred == Length) {
|
|||
|
return(STATUS_SUCCESS);
|
|||
|
} else {
|
|||
|
return(STATUS_UNSUCCESSFUL);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
ApFindAgpCapability(
|
|||
|
IN PAGP_GETSET_CONFIG_SPACE pConfigFn,
|
|||
|
IN PVOID Context,
|
|||
|
OUT PPCI_AGP_CAPABILITY Capability,
|
|||
|
OUT UCHAR *pOffset,
|
|||
|
OUT PPCI_COMMON_CONFIG PciCommonConfig OPTIONAL
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Finds the capability offset for the specified device and
|
|||
|
reads in the header.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pConfigFn - Supplies the function to call for accessing config space
|
|||
|
on the appropriate device.
|
|||
|
|
|||
|
Context - Supplies the context to pass to pConfigFn
|
|||
|
|
|||
|
Capabilities - Returns the AGP Capabilities common header
|
|||
|
|
|||
|
pOffset - Returns the offset into config space.
|
|||
|
|
|||
|
PciCommonConfig - NULL, or points to the PCI common configuration header
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PCI_COMMON_HEADER Header;
|
|||
|
PPCI_COMMON_CONFIG PciConfig = (PPCI_COMMON_CONFIG)&Header;
|
|||
|
NTSTATUS Status;
|
|||
|
UCHAR CapabilityOffset;
|
|||
|
|
|||
|
//
|
|||
|
// Read the PCI common header to get the capabilities pointer
|
|||
|
//
|
|||
|
Status = (pConfigFn)(Context,
|
|||
|
TRUE,
|
|||
|
PciConfig,
|
|||
|
0,
|
|||
|
sizeof(PCI_COMMON_HEADER));
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
AGPLOG(AGP_CRITICAL,
|
|||
|
("AgpLibGetAgpCapability - read PCI Config space for Context %08lx failed %08lx\n",
|
|||
|
Context,
|
|||
|
Status));
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Check the Status register to see if this device supports capability lists.
|
|||
|
// If not, it is not an AGP-compliant device.
|
|||
|
//
|
|||
|
if ((PciConfig->Status & PCI_STATUS_CAPABILITIES_LIST) == 0) {
|
|||
|
AGPLOG(AGP_CRITICAL,
|
|||
|
("AgpLibGetAgpCapability - Context %08lx does not support Capabilities list, not an AGP device\n",
|
|||
|
Context));
|
|||
|
return(STATUS_NOT_IMPLEMENTED);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// The device supports capability lists, find the AGP capabilities
|
|||
|
//
|
|||
|
if ((PciConfig->HeaderType & (~PCI_MULTIFUNCTION)) == PCI_BRIDGE_TYPE) {
|
|||
|
CapabilityOffset = PciConfig->u.type1.CapabilitiesPtr;
|
|||
|
} else {
|
|||
|
ASSERT((PciConfig->HeaderType & (~PCI_MULTIFUNCTION)) == PCI_DEVICE_TYPE);
|
|||
|
CapabilityOffset = PciConfig->u.type0.CapabilitiesPtr;
|
|||
|
}
|
|||
|
while (CapabilityOffset != 0) {
|
|||
|
|
|||
|
//
|
|||
|
// Read the Capability at this offset
|
|||
|
//
|
|||
|
Status = (pConfigFn)(Context,
|
|||
|
TRUE,
|
|||
|
Capability,
|
|||
|
CapabilityOffset,
|
|||
|
sizeof(PCI_CAPABILITIES_HEADER));
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
AGPLOG(AGP_CRITICAL,
|
|||
|
("AgpLibGetAgpCapability - read PCI Capability at offset %x for Context %08lx failed %08lx\n",
|
|||
|
CapabilityOffset,
|
|||
|
Context,
|
|||
|
Status));
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
if (Capability->Header.CapabilityID == PCI_CAPABILITY_ID_AGP) {
|
|||
|
//
|
|||
|
// Found the AGP Capability
|
|||
|
//
|
|||
|
break;
|
|||
|
} else {
|
|||
|
//
|
|||
|
// This is some other Capability, keep looking for the AGP Capability
|
|||
|
//
|
|||
|
CapabilityOffset = Capability->Header.Next;
|
|||
|
}
|
|||
|
}
|
|||
|
if (CapabilityOffset == 0) {
|
|||
|
//
|
|||
|
// No AGP capability was found
|
|||
|
//
|
|||
|
AGPLOG(AGP_CRITICAL,
|
|||
|
("AgpLibGetAgpCapability - Context %08lx does have an AGP Capability entry, not an AGP device\n",
|
|||
|
Context));
|
|||
|
return(STATUS_NOT_IMPLEMENTED);
|
|||
|
}
|
|||
|
|
|||
|
AGPLOG(AGP_NOISE,
|
|||
|
("AgpLibGetAgpCapability - Context %08lx has AGP Capability at offset %x\n",
|
|||
|
Context,
|
|||
|
CapabilityOffset));
|
|||
|
|
|||
|
*pOffset = CapabilityOffset;
|
|||
|
|
|||
|
if (PciCommonConfig) {
|
|||
|
RtlCopyMemory(PciCommonConfig, PciConfig, sizeof(PCI_COMMON_HEADER));
|
|||
|
}
|
|||
|
|
|||
|
return(STATUS_SUCCESS);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
AgpLibGetAgpCapability(
|
|||
|
IN PAGP_GETSET_CONFIG_SPACE pConfigFn,
|
|||
|
IN PVOID Context,
|
|||
|
IN BOOLEAN DoSpecial,
|
|||
|
OUT PPCI_AGP_CAPABILITY Capability
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine finds and retrieves the AGP capabilities in the
|
|||
|
PCI config space of the AGP master (graphics card).
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pConfigFn - Supplies the function to call for accessing config space
|
|||
|
on the appropriate device.
|
|||
|
|
|||
|
Context - Supplies the context to pass to pConfigFn
|
|||
|
|
|||
|
DoSpecial - Indicates whether we should apply any "pecial" tweaks
|
|||
|
|
|||
|
Capabilities - Returns the current AGP Capabilities
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
ULONGLONG DeviceFlags;
|
|||
|
UCHAR CapabilityOffset;
|
|||
|
PCI_COMMON_HEADER Header;
|
|||
|
USHORT SubVendorID, SubSystemID;
|
|||
|
PPCI_COMMON_CONFIG PciConfig = (PPCI_COMMON_CONFIG)&Header;
|
|||
|
|
|||
|
Status = ApFindAgpCapability(pConfigFn,
|
|||
|
Context,
|
|||
|
Capability,
|
|||
|
&CapabilityOffset,
|
|||
|
PciConfig);
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Read the rest of the AGP capability
|
|||
|
//
|
|||
|
Status = (pConfigFn)(Context,
|
|||
|
TRUE,
|
|||
|
&Capability->Header + 1,
|
|||
|
CapabilityOffset + sizeof(PCI_CAPABILITIES_HEADER),
|
|||
|
sizeof(PCI_AGP_CAPABILITY) - sizeof(PCI_CAPABILITIES_HEADER));
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
AGPLOG(AGP_CRITICAL,
|
|||
|
("AgpLibGetAgpCapability - read AGP Capability at offset %x for Context %08lx failed %08lx\n",
|
|||
|
CapabilityOffset,
|
|||
|
Context,
|
|||
|
Status));
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Check device flags for broken HW, we may need to tweak caps
|
|||
|
//
|
|||
|
if ((PCI_CONFIGURATION_TYPE(PciConfig) == PCI_DEVICE_TYPE) &&
|
|||
|
(PciConfig->BaseClass != PCI_CLASS_BRIDGE_DEV)) {
|
|||
|
SubVendorID = PciConfig->u.type0.SubVendorID;
|
|||
|
SubSystemID = PciConfig->u.type0.SubSystemID;
|
|||
|
} else {
|
|||
|
SubVendorID = 0;
|
|||
|
SubSystemID = 0;
|
|||
|
}
|
|||
|
|
|||
|
DeviceFlags = AgpGetDeviceFlags(AgpGlobalHackTable,
|
|||
|
PciConfig->VendorID,
|
|||
|
PciConfig->DeviceID,
|
|||
|
SubVendorID,
|
|||
|
SubSystemID,
|
|||
|
PciConfig->RevisionID);
|
|||
|
|
|||
|
DeviceFlags |= AgpGetDeviceFlags(AgpDeviceHackTable,
|
|||
|
PciConfig->VendorID,
|
|||
|
PciConfig->DeviceID,
|
|||
|
SubVendorID,
|
|||
|
SubSystemID,
|
|||
|
PciConfig->RevisionID);
|
|||
|
|
|||
|
if (DeviceFlags & AGP_FLAG_NO_1X_RATE) {
|
|||
|
Capability->AGPStatus.Rate &= ~PCI_AGP_RATE_1X;
|
|||
|
|
|||
|
AGPLOG(AGP_WARNING,
|
|||
|
("AGP HAMMER CAPS: NO_1X_RATE Vendor %x, Device %x.\n",
|
|||
|
PciConfig->VendorID,
|
|||
|
PciConfig->DeviceID));
|
|||
|
}
|
|||
|
|
|||
|
if (DeviceFlags & AGP_FLAG_NO_2X_RATE) {
|
|||
|
Capability->AGPStatus.Rate &= ~PCI_AGP_RATE_2X;
|
|||
|
|
|||
|
AGPLOG(AGP_WARNING,
|
|||
|
("AGP HAMMER CAPS: NO_2X_RATE Vendor %x, Device %x.\n",
|
|||
|
PciConfig->VendorID,
|
|||
|
PciConfig->DeviceID));
|
|||
|
}
|
|||
|
|
|||
|
if (DeviceFlags & AGP_FLAG_NO_4X_RATE) {
|
|||
|
Capability->AGPStatus.Rate &= ~PCI_AGP_RATE_4X;
|
|||
|
|
|||
|
AGPLOG(AGP_WARNING,
|
|||
|
("AGP HAMMER CAPS: NO_4X_RATE Vendor %x, Device %x.\n",
|
|||
|
PciConfig->VendorID,
|
|||
|
PciConfig->DeviceID));
|
|||
|
}
|
|||
|
|
|||
|
if (DeviceFlags & AGP_FLAG_NO_8X_RATE) {
|
|||
|
Capability->AGPStatus.Rate &= ~8;
|
|||
|
|
|||
|
AGPLOG(AGP_WARNING,
|
|||
|
("AGP HAMMER CAPS: NO_8X_RATE Vendor %x, Device %x.\n",
|
|||
|
PciConfig->VendorID,
|
|||
|
PciConfig->DeviceID));
|
|||
|
}
|
|||
|
|
|||
|
if (DeviceFlags & AGP_FLAG_NO_SBA_ENABLE) {
|
|||
|
Capability->AGPStatus.SideBandAddressing = 0;
|
|||
|
|
|||
|
AGPLOG(AGP_WARNING,
|
|||
|
("AGP HAMMER CAPS: NO_SBA_ENABLE Vendor %x, Device %x.\n",
|
|||
|
PciConfig->VendorID,
|
|||
|
PciConfig->DeviceID));
|
|||
|
}
|
|||
|
|
|||
|
if (DeviceFlags & AGP_FLAG_REVERSE_INITIALIZATION) {
|
|||
|
|
|||
|
AGPLOG(AGP_WARNING,
|
|||
|
("AGP GLOBAL HACK: REVERSE_INITIALIZATION Vendor %x, "
|
|||
|
"Device %x.\n",
|
|||
|
PciConfig->VendorID,
|
|||
|
PciConfig->DeviceID));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Test if this device requires any platform specific AGP tweaks
|
|||
|
//
|
|||
|
if (DoSpecial && (DeviceFlags > AGP_FLAG_SPECIAL_TARGET) ||
|
|||
|
(DeviceFlags & AGP_FLAG_REVERSE_INITIALIZATION)) {
|
|||
|
AgpSpecialTarget(GET_AGP_CONTEXT_FROM_MASTER((PMASTER_EXTENSION)Context), ((DeviceFlags & ~AGP_FLAG_SPECIAL_TARGET) | (DeviceFlags & AGP_FLAG_REVERSE_INITIALIZATION)));
|
|||
|
}
|
|||
|
|
|||
|
AGPLOG(AGP_NOISE,
|
|||
|
("AGP CAPABILITY: version %d.%d\n",Capability->Major, Capability->Minor));
|
|||
|
AGPLOG(AGP_NOISE,
|
|||
|
("\tSTATUS - Rate: %x SBA: %x RQ: %02x\n",
|
|||
|
Capability->AGPStatus.Rate,
|
|||
|
Capability->AGPStatus.SideBandAddressing,
|
|||
|
Capability->AGPStatus.RequestQueueDepthMaximum));
|
|||
|
AGPLOG(AGP_NOISE,
|
|||
|
("\tCOMMAND - Rate: %x SBA: %x RQ: %02x AGPEnable: %x\n",
|
|||
|
Capability->AGPCommand.Rate,
|
|||
|
Capability->AGPCommand.SBAEnable,
|
|||
|
Capability->AGPCommand.RequestQueueDepth,
|
|||
|
Capability->AGPCommand.AGPEnable));
|
|||
|
|
|||
|
return(STATUS_SUCCESS);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
AgpLibGetTargetCapability(
|
|||
|
IN PVOID AgpExtension,
|
|||
|
OUT PPCI_AGP_CAPABILITY Capability
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Retrieves the AGP capability for the AGP target (AGP bridge)
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
AgpExtension - Supplies the AGP extension
|
|||
|
|
|||
|
Capability - Returns the AGP capability
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PTARGET_EXTENSION Extension;
|
|||
|
|
|||
|
GET_TARGET_EXTENSION(Extension, AgpExtension);
|
|||
|
|
|||
|
return(AgpLibGetAgpCapability(ApGetSetDeviceBusData,
|
|||
|
Extension,
|
|||
|
FALSE,
|
|||
|
Capability));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
AgpLibGetMasterCapability(
|
|||
|
IN PVOID AgpExtension,
|
|||
|
OUT PPCI_AGP_CAPABILITY Capability
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Retrieves the AGP capability for the AGP master (graphics card)
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
AgpExtension - Supplies the AGP extension
|
|||
|
|
|||
|
Capability - Returns the AGP capability
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PMASTER_EXTENSION Extension;
|
|||
|
|
|||
|
GET_MASTER_EXTENSION(Extension, AgpExtension);
|
|||
|
|
|||
|
return(AgpLibGetAgpCapability(ApGetSetDeviceBusData,
|
|||
|
Extension,
|
|||
|
TRUE,
|
|||
|
Capability));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
AgpLibGetPciDeviceCapability(
|
|||
|
IN ULONG BusId,
|
|||
|
IN ULONG SlotId,
|
|||
|
OUT PPCI_AGP_CAPABILITY Capability
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Retrieves the AGP capability for the specified PCI slot.
|
|||
|
|
|||
|
Caller is responsible for figuring out what the correct
|
|||
|
Bus/Slot ID is. These are just passed right to HalGetBusData.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BusId - supplies the bus id
|
|||
|
|
|||
|
SlotId - Supplies the slot id
|
|||
|
|
|||
|
Capability - Returns the AGP capability
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
BUS_SLOT_ID BusSlotId;
|
|||
|
|
|||
|
BusSlotId.BusId = BusId;
|
|||
|
BusSlotId.SlotId = SlotId;
|
|||
|
|
|||
|
return(AgpLibGetAgpCapability(ApGetSetBusData,
|
|||
|
&BusSlotId,
|
|||
|
FALSE,
|
|||
|
Capability));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
AgpLibSetAgpCapability(
|
|||
|
IN PAGP_GETSET_CONFIG_SPACE pConfigFn,
|
|||
|
IN PVOID Context,
|
|||
|
OUT PPCI_AGP_CAPABILITY Capability
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine finds and retrieves the AGP capabilities in the
|
|||
|
PCI config space of the AGP master (graphics card).
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pConfigFn - Supplies the function to call for accessing config space
|
|||
|
on the appropriate device.
|
|||
|
|
|||
|
Context - Supplies the context to pass to pConfigFn
|
|||
|
|
|||
|
Capabilities - Returns the current AGP Capabilities
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
UCHAR CapabilityOffset;
|
|||
|
|
|||
|
Status = ApFindAgpCapability(pConfigFn,
|
|||
|
Context,
|
|||
|
Capability,
|
|||
|
&CapabilityOffset,
|
|||
|
NULL);
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now that we know the offset, write the supplied command register
|
|||
|
//
|
|||
|
Status = (pConfigFn)(Context,
|
|||
|
FALSE,
|
|||
|
&Capability->AGPCommand,
|
|||
|
CapabilityOffset + FIELD_OFFSET(PCI_AGP_CAPABILITY, AGPCommand),
|
|||
|
sizeof(Capability->AGPCommand));
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
AGPLOG(AGP_CRITICAL,
|
|||
|
("AgpLibSetAgpCapability - Set AGP command at offset %x for Context %08lx failed %08lx\n",
|
|||
|
CapabilityOffset,
|
|||
|
Context,
|
|||
|
Status));
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
return(STATUS_SUCCESS);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
AgpLibSetTargetCapability(
|
|||
|
IN PVOID AgpExtension,
|
|||
|
OUT PPCI_AGP_CAPABILITY Capability
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Sets the AGP capability for the AGP target (AGP bridge)
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
AgpExtension - Supplies the AGP extension
|
|||
|
|
|||
|
Capability - Returns the AGP capability
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PTARGET_EXTENSION Extension;
|
|||
|
|
|||
|
GET_TARGET_EXTENSION(Extension, AgpExtension);
|
|||
|
|
|||
|
return(AgpLibSetAgpCapability(ApGetSetDeviceBusData,
|
|||
|
Extension,
|
|||
|
Capability));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
AgpLibSetMasterCapability(
|
|||
|
IN PVOID AgpExtension,
|
|||
|
OUT PPCI_AGP_CAPABILITY Capability
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Sets the AGP capability for the AGP master (graphics card)
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
AgpExtension - Supplies the AGP extension
|
|||
|
|
|||
|
Capability - Returns the AGP capability
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PMASTER_EXTENSION Extension;
|
|||
|
|
|||
|
GET_MASTER_EXTENSION(Extension, AgpExtension);
|
|||
|
|
|||
|
return(AgpLibSetAgpCapability(ApGetSetDeviceBusData,
|
|||
|
Extension,
|
|||
|
Capability));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
AgpLibSetPciDeviceCapability(
|
|||
|
IN ULONG BusId,
|
|||
|
IN ULONG SlotId,
|
|||
|
OUT PPCI_AGP_CAPABILITY Capability
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Sets the AGP capability for the specified PCI slot.
|
|||
|
|
|||
|
Caller is responsible for figuring out what the correct
|
|||
|
Bus/Slot ID is. These are just passed right to HalSetBusData.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BusId - supplies the bus id
|
|||
|
|
|||
|
SlotId - Supplies the slot id
|
|||
|
|
|||
|
Capability - Returns the AGP capability
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
BUS_SLOT_ID BusSlotId;
|
|||
|
|
|||
|
BusSlotId.BusId = BusId;
|
|||
|
BusSlotId.SlotId = SlotId;
|
|||
|
|
|||
|
return(AgpLibSetAgpCapability(ApGetSetBusData,
|
|||
|
&BusSlotId,
|
|||
|
Capability));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
AgpLibGetMasterDeviceId(
|
|||
|
IN PVOID AgpExtension,
|
|||
|
OUT PULONG DeviceId
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function returns the PCI DeviceId/Vendo58rId of the master AGP
|
|||
|
device
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DeviceId - Identifies PCI manufaturer and device of master
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS or an appropriate error status
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PCI_COMMON_HEADER Header;
|
|||
|
PPCI_COMMON_CONFIG PciConfig = (PPCI_COMMON_CONFIG)&Header;
|
|||
|
NTSTATUS Status;
|
|||
|
PMASTER_EXTENSION Master = NULL;
|
|||
|
PTARGET_EXTENSION Target = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Try to make this as idiot proof as possible for the case
|
|||
|
// where this is called from SetAperture on a system without
|
|||
|
// an AGP adapter, so we don't AV if some context hasn't been
|
|||
|
// initialized, or is missing...
|
|||
|
//
|
|||
|
|
|||
|
Target = CONTAINING_RECORD(AgpExtension,
|
|||
|
TARGET_EXTENSION,
|
|||
|
AgpContext);
|
|||
|
|
|||
|
if (Target) {
|
|||
|
if (Target->CommonExtension.Signature == TARGET_SIG) {
|
|||
|
if (Target->ChildDevice) {
|
|||
|
if (Target->ChildDevice->CommonExtension.Signature ==
|
|||
|
MASTER_SIG) {
|
|||
|
Master = Target->ChildDevice;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (Master) {
|
|||
|
|
|||
|
//
|
|||
|
// Read the PCI common header to get the capabilities pointer
|
|||
|
//
|
|||
|
Status = (ApGetSetDeviceBusData)((PCOMMON_EXTENSION)Master,
|
|||
|
TRUE,
|
|||
|
PciConfig,
|
|||
|
0,
|
|||
|
sizeof(PCI_COMMON_HEADER));
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
AGPLOG(AGP_CRITICAL,
|
|||
|
("AgpLibGetMasterDeviceId - read PCI Config space for Context %08lx failed %08lx\n",
|
|||
|
Master,
|
|||
|
Status));
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
*DeviceId = *(PULONG)PciConfig;
|
|||
|
|
|||
|
} else {
|
|||
|
*DeviceId = (ULONG)-1;
|
|||
|
}
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|