Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

369 lines
9.2 KiB

/*++
Copyright (c) 1997-2000 Microsoft Corporation
Module Name:
agpintrf.c
Abstract:
This module implements the "bus handler" interfaces supported
by the PCI driver.
Author:
Peter Johnston (peterj) 6-Jun-1997
Revision History:
--*/
#include "pcip.h"
#define AGPINTRF_VERSION 1
//
// Prototypes for routines exposed only thru the "interface"
// mechanism.
//
NTSTATUS
agpintrf_Constructor(
PVOID DeviceExtension,
PVOID PciInterface,
PVOID InterfaceSpecificData,
USHORT Version,
USHORT Size,
PINTERFACE InterfaceReturn
);
VOID
agpintrf_Reference(
IN PVOID Context
);
VOID
agpintrf_Dereference(
IN PVOID Context
);
NTSTATUS
agpintrf_Initializer(
IN PPCI_ARBITER_INSTANCE Instance
);
ULONG
PciReadAgpConfig(
IN PVOID Context,
IN ULONG WhichSpace,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
);
ULONG
PciWriteAgpConfig(
IN PVOID Context,
IN ULONG WhichSpace,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
);
//
// Define the Bus Interface "Interface" structure.
//
PCI_INTERFACE AgpTargetInterface = {
&GUID_AGP_TARGET_BUS_INTERFACE_STANDARD, // InterfaceType
sizeof(AGP_TARGET_BUS_INTERFACE_STANDARD), // MinSize
AGPINTRF_VERSION, // MinVersion
AGPINTRF_VERSION, // MaxVersion
PCIIF_PDO, // Flags
0, // ReferenceCount
PciInterface_AgpTarget, // Signature
agpintrf_Constructor, // Constructor
agpintrf_Initializer // Instance Initializer
};
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, agpintrf_Constructor)
#pragma alloc_text(PAGE, agpintrf_Dereference)
#pragma alloc_text(PAGE, agpintrf_Initializer)
#pragma alloc_text(PAGE, agpintrf_Reference)
#endif
VOID
agpintrf_Reference(
IN PVOID Context
)
{
PPCI_PDO_EXTENSION targetExtension = (PPCI_PDO_EXTENSION)Context;
ASSERT_PCI_PDO_EXTENSION(targetExtension);
if (InterlockedIncrement(&targetExtension->AgpInterfaceReferenceCount) == 1) {
ObReferenceObject(targetExtension->PhysicalDeviceObject);
}
}
VOID
agpintrf_Dereference(
IN PVOID Context
)
{
PPCI_PDO_EXTENSION targetExtension = (PPCI_PDO_EXTENSION)Context;
ASSERT_PCI_PDO_EXTENSION(targetExtension);
if (InterlockedDecrement(&targetExtension->AgpInterfaceReferenceCount) == 0) {
ObDereferenceObject(targetExtension->PhysicalDeviceObject);
}
}
NTSTATUS
agpintrf_Constructor(
PVOID DeviceExtension,
PVOID PciInterface,
PVOID InterfaceSpecificData,
USHORT Version,
USHORT Size,
PINTERFACE InterfaceReturn
)
/*++
Routine Description:
Initialize the AGP_TARGET_BUS_INTERFACE fields.
This interface can only be requested from the device stack of an AGP
bridge. This routine looks for an AGP capability in the requester
bridge and any peer host bridges. If one is found, config access
to the device with the capability is granted.
Arguments:
PciInterface Pointer to the PciInterface record for this
interface type.
InterfaceSpecificData
A ULONG containing the resource type for which
arbitration is required.
InterfaceReturn
Return Value:
TRUE is this device is not known to cause problems, FALSE
if the device should be skipped altogether.
--*/
{
PAGP_TARGET_BUS_INTERFACE_STANDARD targetInterface = (PAGP_TARGET_BUS_INTERFACE_STANDARD)InterfaceReturn;
PPCI_PDO_EXTENSION extension = (PPCI_PDO_EXTENSION)DeviceExtension;
PPCI_PDO_EXTENSION current;
PPCI_PDO_EXTENSION targetExtension = NULL;
PPCI_FDO_EXTENSION parentExtension;
if ((extension->BaseClass != PCI_CLASS_BRIDGE_DEV) ||
(extension->SubClass != PCI_SUBCLASS_BR_PCI_TO_PCI)) {
//
// This interface is only supported on AGP bridges,
// which are PCI-PCI bridges.
//
return STATUS_NOT_SUPPORTED;
}
if (extension->TargetAgpCapabilityId == PCI_CAPABILITY_ID_AGP_TARGET) {
//
// The bridge has a target AGP capability itself. Give the
// caller access to its config space.
//
targetExtension = extension;
} else {
//
// No target AGP capability on the bridge itself. Look on the same
// bus as the bridge for host bridges with the AGP capability.
//
parentExtension = extension->ParentFdoExtension;
if (!PCI_IS_ROOT_FDO(parentExtension)) {
//
// Not likely to find host bridges on non-root busses.
// Even if we could, constrain this interface to only support
// root busses.
//
return STATUS_NOT_SUPPORTED;
}
ExAcquireFastMutex(&parentExtension->ChildListMutex);
for (current = parentExtension->ChildPdoList; current != NULL; current = current->Next) {
if ((current->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
(current->SubClass == PCI_SUBCLASS_BR_HOST) &&
(current->TargetAgpCapabilityId != 0)) {
//
// We have a host bridge with a target AGP capability. Check to make
// sure that there's only one such host bridge. If there are multiple,
// we don't know which to grant access to, so fail the call.
//
if (targetExtension != NULL) {
ExReleaseFastMutex(&parentExtension->ChildListMutex);
return STATUS_NOT_SUPPORTED;
}
targetExtension = current;
}
}
ExReleaseFastMutex(&parentExtension->ChildListMutex);
if (targetExtension == NULL) {
return STATUS_NO_SUCH_DEVICE;
}
}
PCI_ASSERT(targetExtension != NULL);
targetInterface->Size = sizeof( AGP_TARGET_BUS_INTERFACE_STANDARD );
targetInterface->Version = AGPINTRF_VERSION;
targetInterface->Context = targetExtension;
targetInterface->InterfaceReference = agpintrf_Reference;
targetInterface->InterfaceDereference = agpintrf_Dereference;
targetInterface->CapabilityID = targetExtension->TargetAgpCapabilityId;
targetInterface->SetBusData = PciWriteAgpConfig;
targetInterface->GetBusData = PciReadAgpConfig;
return STATUS_SUCCESS;
}
NTSTATUS
agpintrf_Initializer(
IN PPCI_ARBITER_INSTANCE Instance
)
/*++
Routine Description:
For bus interface, does nothing, shouldn't actually be called.
Arguments:
Instance Pointer to the PDO extension.
Return Value:
Returns the status of this operation.
--*/
{
PCI_ASSERTMSG("PCI agpintrf_Initializer, unexpected call.", 0);
return STATUS_UNSUCCESSFUL;
}
ULONG
PciReadAgpConfig(
IN PVOID Context,
IN ULONG WhichSpace,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
)
/*++
Routine Description:
This function reads the PCI configuration space.
Arguments:
Context - Supplies a pointer to the interface context. This is actually
the PDO for the root bus.
Buffer - Supplies a pointer to where the data should be placed.
Offset - Indicates the offset into the data where the reading should begin.
Length - Indicates the count of bytes which should be read.
Return Value:
Returns the number of bytes read.
--*/
{
PPCI_PDO_EXTENSION pdoExtension = (PPCI_PDO_EXTENSION)Context;
ULONG lengthRead;
ASSERT_PCI_PDO_EXTENSION(pdoExtension);
PciReadDeviceSpace(pdoExtension,
WhichSpace,
Buffer,
Offset,
Length,
&lengthRead
);
return lengthRead;
}
ULONG
PciWriteAgpConfig(
IN PVOID Context,
IN ULONG WhichSpace,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
)
/*++
Routine Description:
This function writes the PCI configuration space.
Arguments:
Context - Supplies a pointer to the interface context. This is actually
the PDO for the root bus.
Buffer - Supplies a pointer to where the data to be written is.
Offset - Indicates the offset into the data where the writing should begin.
Length - Indicates the count of bytes which should be written.
Return Value:
Returns the number of bytes read.
--*/
{
PPCI_PDO_EXTENSION pdoExtension = (PPCI_PDO_EXTENSION)Context;
ULONG lengthWritten;
ASSERT_PCI_PDO_EXTENSION(pdoExtension);
PciWriteDeviceSpace(pdoExtension,
WhichSpace,
Buffer,
Offset,
Length,
&lengthWritten
);
return lengthWritten;
}