📄 config.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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -