|
|
/*++
Copyright (c) 1997-2000 Microsoft Corporation
Module Name:
arb_comn.c
Abstract:
This module contains arbitration generic "utility" routines for the PCI driver.
Author:
Peter Johnston (peterj) 1-Apr-1997 Andrew Thornton (andrewth) 15-May-1997
Revision History:
--*/
#include "pcip.h"
#define PCI_CONTEXT_TO_INSTANCE(context) \
CONTAINING_RECORD(context, PCI_ARBITER_INSTANCE, CommonInstance)
//
// Plain text (short) description of each arbiter type.
// (For debug).
//
// N.B. Order corresponds to PCI Signature enumeration.
//
PUCHAR PciArbiterNames[] = { "I/O Port", "Memory", "Interrupt", "Bus Number" }; VOID PciArbiterDestructor( IN PVOID Extension )
/*++
Routine Description:
This routine is called when a PCI Secondary Extension that contains an arbiter instance is being torn down. Its function is to do any arbiter specific teardown.
Arguments:
Extension Address of PCI secondary extension containing the arbiter.
Return Value:
None.
--*/
{ PPCI_ARBITER_INSTANCE instance; PARBITER_INSTANCE arbiter; PARBITER_MEMORY_EXTENSION extension;
instance = (PPCI_ARBITER_INSTANCE)Extension; arbiter = &instance->CommonInstance;
PCI_ASSERT(!arbiter->ReferenceCount); PCI_ASSERT(!arbiter->TransactionInProgress);
//
// NTRAID #54671 - 04/03/2000 - andrewth
// This is rather gross but it fixes the leak from the memory
// arbiter.
//
if (arbiter->ResourceType == CmResourceTypeMemory) {
extension = arbiter->Extension;
PCI_ASSERT(extension);
ArbFreeOrderingList(&extension->PrefetchableOrdering); ArbFreeOrderingList(&extension->NonprefetchableOrdering); ArbFreeOrderingList(&extension->OriginalOrdering);
//
// Arbiter->OrderingList is one of the above three lists we just freed -
// don't free it again
//
RtlZeroMemory(&arbiter->OrderingList, sizeof(ARBITER_ORDERING_LIST)); }
ArbDeleteArbiterInstance(arbiter); }
NTSTATUS PciArbiterInitializeInterface( IN PVOID DeviceExtension, IN PCI_SIGNATURE DesiredInterface, IN OUT PARBITER_INTERFACE ArbiterInterface ) { PPCI_ARBITER_INSTANCE instance; PPCI_FDO_EXTENSION fdoExtension = (PPCI_FDO_EXTENSION)DeviceExtension;
//
// Find the arbiter instance (context) for this resource type
// on this FDO.
//
instance = PciFindSecondaryExtension(fdoExtension, DesiredInterface); if (instance == NULL) {
#if DBG
//
// Check if this bridge is doing subtractive decoding in
// which case there will be no arbiter for IO or Memory.
//
// N.B. Only relevant to debug, either way the call will
// fail but we don't want to actually assert if this is
// the case.
//
if (!PCI_IS_ROOT_FDO(fdoExtension)) {
PPCI_PDO_EXTENSION pdoExtension = (PPCI_PDO_EXTENSION) fdoExtension->PhysicalDeviceObject->DeviceExtension;
ASSERT_PCI_PDO_EXTENSION(pdoExtension);
if (pdoExtension->Dependent.type1.SubtractiveDecode) {
//
// Subtractive, no arbiters.
//
return STATUS_INVALID_PARAMETER_2; }
}
PCI_ASSERTMSG("couldn't locate arbiter for resource.", instance);
#endif
return STATUS_INVALID_PARAMETER_5; }
//
// Fill in the rest of the caller's arbiter interface structure.
//
ArbiterInterface->Context = &instance->CommonInstance;
PciDebugPrint( PciDbgObnoxious, "PCI - %S Arbiter Interface Initialized.\n", instance->CommonInstance.Name );
return STATUS_SUCCESS; }
NTSTATUS PciInitializeArbiters( IN PVOID DeviceExtension ) { NTSTATUS status; PPCI_INTERFACE *interfaceEntry; PCI_SIGNATURE arbiterType; PPCI_ARBITER_INSTANCE instance; PPCI_FDO_EXTENSION fdoExtension = (PPCI_FDO_EXTENSION)DeviceExtension; BOOLEAN ok;
ASSERT_PCI_FDO_EXTENSION(fdoExtension);
//
// For each resource type for which we do arbitration, initialize
// a context.
//
for (arbiterType = PciArb_Io; arbiterType <= PciArb_BusNumber; arbiterType++) {
//
// If this bridge provides this resource via subtractive
// decode, get the system to fall thru to the parent
// arbiter by not creating an arbiter at this level.
//
if (!PCI_IS_ROOT_FDO(fdoExtension)) {
PPCI_PDO_EXTENSION pdoExtension = (PPCI_PDO_EXTENSION) fdoExtension->PhysicalDeviceObject->DeviceExtension;
ASSERT_PCI_PDO_EXTENSION(pdoExtension);
if (pdoExtension->Dependent.type1.SubtractiveDecode) {
//
// Skip creation of this arbiter.
//
PciDebugPrint( PciDbgVerbose, "PCI Not creating arbiters for subtractive bus %d\n", pdoExtension->Dependent.type1.SecondaryBus );
continue; } }
//
// Find this entry in the interface table (if not found, skip
// it).
//
for (interfaceEntry = PciInterfaces; *interfaceEntry; interfaceEntry++) {
if ((*interfaceEntry)->Signature == arbiterType) { break; } }
if (*interfaceEntry == NULL) {
//
// Did not find an interface entry. This means we don't
// actually implement this arbiter type.
//
PciDebugPrint( PciDbgObnoxious, "PCI - FDO ext 0x%08x no %s arbiter.\n", DeviceExtension, PciArbiterNames[arbiterType - PciArb_Io] );
continue; }
instance = ExAllocatePool( PagedPool | POOL_COLD_ALLOCATION, sizeof(PCI_ARBITER_INSTANCE) );
if (instance == NULL) { return STATUS_INSUFFICIENT_RESOURCES; }
//
// Initialize PCI specific fields
//
instance->BusFdoExtension = fdoExtension; instance->Interface = *interfaceEntry;
ok = SUCCEEDED(StringCbPrintfW(instance->InstanceName, sizeof(instance->InstanceName), L"PCI %S (b=%02x)", PciArbiterNames[arbiterType - PciArb_Io], fdoExtension->BaseBus ));
ASSERT(ok);
//
// Allow this arbiter to do any of it's own first time
// initialization.
//
status = (*interfaceEntry)->Initializer(instance); if (!NT_SUCCESS(status)) { return status; }
//
// Push this arbiter onto the FDO's list of extensions.
//
PciLinkSecondaryExtension(fdoExtension, instance, arbiterType, PciArbiterDestructor);
PciDebugPrint( PciDbgObnoxious, "PCI - FDO ext 0x%08x %S arbiter initialized (context 0x%08x).\n", DeviceExtension, instance->CommonInstance.Name, instance ); } return STATUS_SUCCESS; }
NTSTATUS PciInitializeArbiterRanges( IN PPCI_FDO_EXTENSION FdoExtension, IN PCM_RESOURCE_LIST ResourceList ) { NTSTATUS status; PCI_SIGNATURE arbiterType; CM_RESOURCE_TYPE resourceType; PPCI_ARBITER_INSTANCE instance;
//
// NTRAID #95564 - 04/03/2000 - andrewth
// This routine needs to be reworked, in the case where
// this FDO is processing a second or subsequent START_DEVICE
// IRP, the arbiter's ranges may need to be adjusted according
// to the incoming resource list. Until this is done, avoid
// causing problems by processing it again.
//
if (FdoExtension->ArbitersInitialized) { PciDebugPrint( PciDbgInformative, "PCI Warning hot start FDOx %08x, resource ranges not checked.\n", FdoExtension ); return STATUS_INVALID_DEVICE_REQUEST; }
//
// Check if this bridge is doing subtractive decoding in
// which case there will be no arbiters
//
if (!PCI_IS_ROOT_FDO(FdoExtension)) { PPCI_PDO_EXTENSION pdoExtension;
pdoExtension = (PPCI_PDO_EXTENSION) FdoExtension->PhysicalDeviceObject->DeviceExtension;
ASSERT_PCI_PDO_EXTENSION(pdoExtension);
if (pdoExtension->Dependent.type1.SubtractiveDecode) {
//
// Subtractive decode no arbiters.
//
PciDebugPrint( PciDbgInformative, "PCI Skipping arbiter initialization for subtractive bridge FDOX %p\n", FdoExtension );
return STATUS_SUCCESS; } }
//
// For each resource type for which we do arbitration, initialize
// a context.
//
for (arbiterType = PciArb_Io; arbiterType <= PciArb_Memory; arbiterType++) {
//
// Currently this is only supported for Memory and IO.
//
switch (arbiterType) {
//
// Go ahead and process these ones.
//
case PciArb_Io: resourceType = CmResourceTypePort; break;
case PciArb_Memory: resourceType = CmResourceTypeMemory; break;
default:
//
// Skip anything else.
//
continue; }
//
// Find this arbiter instance.
//
instance = PciFindSecondaryExtension(FdoExtension, arbiterType); if (instance == NULL) {
//
// Did not find an interface entry. This means we don't
// actually implement this arbiter type.
//
PciDebugPrint( PciDbgAlways, "PCI - FDO ext 0x%08x %s arbiter (REQUIRED) is missing.\n", FdoExtension, PciArbiterNames[arbiterType - PciArb_Io] );
continue; }
//
// The incoming ResourceList gives the ranges this bus supports.
// Convert this to an inverted range so we can exclude everything
// we don't cover.
//
status = PciRangeListFromResourceList( FdoExtension, ResourceList, resourceType, TRUE, instance->CommonInstance.Allocation ); if (!NT_SUCCESS(status)) {
//
// Nothing we can do here. Additional debug stuff was
// in the lower level. Skip this puppy.
//
continue; }
//
// NTRAID #95564 - 04/03/2000 - andrewth
//
// When ArbStartArbiter is complete it will replace
// the call to PciRangeListFromResourceList.
//
PCI_ASSERT(instance->CommonInstance.StartArbiter);
status = instance->CommonInstance.StartArbiter(&instance->CommonInstance, ResourceList );
if (!NT_SUCCESS(status)) {
//
// Bail initializing this arbiter and fail the start. The arbiters
// will be cleaned up when we get the REMOVE_DEVICE
//
return status; } }
FdoExtension->ArbitersInitialized = TRUE; return STATUS_SUCCESS; }
VOID PciReferenceArbiter( IN PVOID Context ) { PPCI_ARBITER_INSTANCE instance = PCI_CONTEXT_TO_INSTANCE(Context); InterlockedIncrement(&instance->CommonInstance.ReferenceCount); }
VOID PciDereferenceArbiter( IN PVOID Context ) { PPCI_ARBITER_INSTANCE instance = PCI_CONTEXT_TO_INSTANCE(Context); InterlockedDecrement(&instance->CommonInstance.ReferenceCount); }
|