예제 #1
0
//
// fit bridge [checked]
//
VOID PciFitBridge(__in PPCI_FDO_EXTENSION ParentFdoExt,__in PPCI_PDO_EXTENSION BridgePdoExt)
{
	PAGED_CODE();

	UCHAR Lowest										= 0xff;
	UCHAR MaxGaps										= 0;
	UCHAR SecondaryBusForMaxGaps						= 0;

	PPCI_PDO_EXTENSION BridgeExt						= ParentFdoExt->ChildBridgePdoList;
	while(BridgeExt)
	{
		if(BridgeExt->NotPresent)
		{
			PciDebugPrintf(0x100000,"Skipping not present bridge PDOX @ %p\n",BridgeExt);
		}
		else if(PciAreBusNumbersConfigured(BridgeExt))
		{
			UCHAR BaseBus								= BridgeExt->Dependent.type1.SubordinateBus;
			UCHAR Limit									= PciFindBridgeNumberLimit(ParentFdoExt,BaseBus);

			ASSERT(Limit >= BaseBus);

			if(Limit - BaseBus > MaxGaps)
			{
				ASSERT(Limit > BaseBus);
				MaxGaps									= Limit - BaseBus;
				SecondaryBusForMaxGaps					= BaseBus + 1;
			}

			if(BridgeExt->Dependent.type1.SecondaryBus < Lowest)
				Lowest									= BridgeExt->Dependent.type1.SecondaryBus;
		}

		BridgeExt										= BridgeExt->NextBridge;
	}

	ASSERT(Lowest > ParentFdoExt->BaseBus);

	UCHAR Gaps											= 0;
	UCHAR SecondaryBus									= 0;

	if(Lowest - ParentFdoExt->BaseBus - 1 <= MaxGaps)
	{
		Gaps											= MaxGaps;
		SecondaryBus									= SecondaryBusForMaxGaps;
	}
	else
	{
		SecondaryBus									= ParentFdoExt->BaseBus + 1;
		Gaps											= Lowest - ParentFdoExt->BaseBus - 1;
	}

	if(Gaps >= 1)
	{
		SecondaryBus									= static_cast<UCHAR>(SecondaryBus + Gaps / 2);
		PciSetBusNumbers(BridgePdoExt,ParentFdoExt->BaseBus,SecondaryBus,SecondaryBus);

		PciUpdateAncestorSubordinateBuses(ParentFdoExt,BridgePdoExt->Dependent.type1.SecondaryBus);
	}
}
예제 #2
0
//
// find bridge limit worker [checked]
//
UCHAR PciFindBridgeNumberLimitWorker(__in PPCI_FDO_EXTENSION StartFdoExt,__in PPCI_FDO_EXTENSION CurFdoExt,__in UCHAR BaseBus,__out PBOOLEAN Include)
{
	PAGED_CODE();

	if(CurFdoExt != StartFdoExt)
	{
		KeEnterCriticalRegion();
		KeWaitForSingleObject(&CurFdoExt->ChildListLock,Executive,KernelMode,FALSE,0);
	}

	PPCI_PDO_EXTENSION ChildBridgeExt					= CurFdoExt->ChildBridgePdoList;
	UCHAR Limit											= 0;
	if(ChildBridgeExt)
	{
		while(ChildBridgeExt)
		{
			if(ChildBridgeExt->NotPresent)
			{
				PciDebugPrintf(0x100000,"Skipping not present bridge PDOX @ %p\n",ChildBridgeExt);
			}
			else if(PciAreBusNumbersConfigured(ChildBridgeExt))
			{
				if(ChildBridgeExt->Dependent.type1.SecondaryBus > BaseBus && (ChildBridgeExt->Dependent.type1.SecondaryBus < Limit || !Limit))
					Limit								= ChildBridgeExt->Dependent.type1.SecondaryBus;
			}

			ChildBridgeExt								= ChildBridgeExt->NextBridge;
		}
	}

	if(Limit)
	{
		*Include										= FALSE;
	}
	else
	{
		if(CurFdoExt->ParentFdoExtension)
		{
			Limit										= PciFindBridgeNumberLimitWorker(StartFdoExt,CurFdoExt->ParentFdoExtension,BaseBus,Include);
		}
		else
		{
			Limit										= CurFdoExt->MaxSubordinateBus;
			*Include									= TRUE;
		}
	}

	if(CurFdoExt != StartFdoExt)
	{
		KeSetEvent(&CurFdoExt->ChildListLock,IO_NO_INCREMENT,FALSE);
		KeLeaveCriticalRegion();
	}

	return Limit;
}
예제 #3
0
//
// spread bridges [checked]
//
VOID PciSpreadBridges(__in PPCI_FDO_EXTENSION ParentFdoExt,__in ULONG BridgeCount)
{
	PAGED_CODE();

	ASSERT(ParentFdoExt->BaseBus < PCI_MAX_BRIDGE_NUMBER);

	UCHAR BaseBus										= ParentFdoExt->BaseBus;
	UCHAR Limit											= PciFindBridgeNumberLimit(ParentFdoExt,BaseBus);

	ASSERT(Limit >= BaseBus);

	UCHAR Gaps											= Limit - BaseBus;
	if(!Gaps)
		return;

	UCHAR Step											= static_cast<UCHAR>(BridgeCount < Gaps ? Gaps / (BridgeCount + 1) : 1);
	UCHAR SecondaryBus									= BaseBus + 1;
	UCHAR MaxAssigned									= 0;

	PPCI_PDO_EXTENSION BridgeExt						= ParentFdoExt->ChildBridgePdoList;
	while(BridgeExt)
	{
		if(BridgeExt->NotPresent)
		{
			PciDebugPrintf(0x100000,"Skipping not present bridge PDOX @ %p\n",BridgeExt);
		}
		else
		{
			ASSERT(!PciAreBusNumbersConfigured(BridgeExt));

			PciSetBusNumbers(BridgeExt,BaseBus,SecondaryBus,SecondaryBus);

			MaxAssigned									= SecondaryBus;

			if(static_cast<ULONG>(SecondaryBus) + static_cast<ULONG>(Step) < static_cast<ULONG>(SecondaryBus))
				break;

			if(static_cast<ULONG>(SecondaryBus) + static_cast<ULONG>(Step) > static_cast<ULONG>(Limit))
				break;

			SecondaryBus								= SecondaryBus + Step;
		}

		BridgeExt										= BridgeExt->NextBridge;
	}

	ASSERT(MaxAssigned);

	PciUpdateAncestorSubordinateBuses(ParentFdoExt,MaxAssigned);
}
예제 #4
0
파일: fdo.c 프로젝트: hoangduit/reactos
NTSTATUS
NTAPI
PciAddDevice(IN PDRIVER_OBJECT DriverObject,
             IN PDEVICE_OBJECT PhysicalDeviceObject)
{
    PCM_RESOURCE_LIST Descriptor;
    PDEVICE_OBJECT AttachedTo;
    PPCI_FDO_EXTENSION FdoExtension;
    PPCI_FDO_EXTENSION ParentExtension;
    PPCI_PDO_EXTENSION PdoExtension;
    PDEVICE_OBJECT DeviceObject;
    UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
    PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)Buffer;
    NTSTATUS Status;
    HANDLE KeyHandle;
    UNICODE_STRING ValueName;
    ULONG ResultLength;
    PAGED_CODE();
    DPRINT1("PCI - AddDevice (a new bus). PDO: %p (Driver: %wZ)\n",
            PhysicalDeviceObject, &PhysicalDeviceObject->DriverObject->DriverName);

    /* Zero out variables so failure path knows what to do */
    AttachedTo = NULL;
    FdoExtension = NULL;
    PdoExtension = NULL;
    DeviceObject = NULL;

    do
    {
        /* Check if there's already a device extension for this bus */
        ParentExtension = PciFindParentPciFdoExtension(PhysicalDeviceObject,
                                                       &PciGlobalLock);
        if (ParentExtension)
        {
            /* Make sure we find a real PDO */
            PdoExtension = PhysicalDeviceObject->DeviceExtension;
            ASSERT_PDO(PdoExtension);

            /* Make sure it's a PCI-to-PCI bridge */
            if ((PdoExtension->BaseClass != PCI_CLASS_BRIDGE_DEV) ||
                (PdoExtension->SubClass != PCI_SUBCLASS_BR_PCI_TO_PCI))
            {
                /* This should never happen */
                DPRINT1("PCI - PciAddDevice for Non-Root/Non-PCI-PCI bridge,\n"
                        "      Class %02x, SubClass %02x, will not add.\n",
                        PdoExtension->BaseClass,
                        PdoExtension->SubClass);
                ASSERT((PdoExtension->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
                       (PdoExtension->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI));

                /* Enter the failure path */
                Status = STATUS_INVALID_DEVICE_REQUEST;
                break;
            }

            /* Subordinate bus on the bridge */
            DPRINT1("PCI - AddDevice (new bus is child of bus 0x%x).\n",
                    ParentExtension->BaseBus);

            /* Make sure PCI bus numbers are configured */
            if (!PciAreBusNumbersConfigured(PdoExtension))
            {
                /* This is a critical failure */
                DPRINT1("PCI - Bus numbers not configured for bridge (0x%x.0x%x.0x%x)\n",
                        ParentExtension->BaseBus,
                        PdoExtension->Slot.u.bits.DeviceNumber,
                        PdoExtension->Slot.u.bits.FunctionNumber);

                /* Enter the failure path */
                Status = STATUS_INVALID_DEVICE_REQUEST;
                break;
            }
        }

        /* Create the FDO for the bus */
        Status = IoCreateDevice(DriverObject,
                                sizeof(PCI_FDO_EXTENSION),
                                NULL,
                                FILE_DEVICE_BUS_EXTENDER,
                                0,
                                0,
                                &DeviceObject);
        if (!NT_SUCCESS(Status)) break;

        /* Initialize the extension for the FDO */
        FdoExtension = DeviceObject->DeviceExtension;
        PciInitializeFdoExtensionCommonFields(DeviceObject->DeviceExtension,
                                              DeviceObject,
                                              PhysicalDeviceObject);

        /* Attach to the root PDO */
        Status = STATUS_NO_SUCH_DEVICE;
        AttachedTo = IoAttachDeviceToDeviceStack(DeviceObject,
                                                 PhysicalDeviceObject);
        ASSERT(AttachedTo != NULL);
        if (!AttachedTo) break;
        FdoExtension->AttachedDeviceObject = AttachedTo;

        /* Check if this is a child bus, or the root */
        if (ParentExtension)
        {
            /* The child inherits root data */
            FdoExtension->BaseBus = PdoExtension->Dependent.type1.SecondaryBus;
            FdoExtension->BusRootFdoExtension = ParentExtension->BusRootFdoExtension;
            PdoExtension->BridgeFdoExtension = FdoExtension;
            FdoExtension->ParentFdoExtension = ParentExtension;
        }
        else
        {
            /* Query the boot configuration */
            Status = PciGetDeviceProperty(PhysicalDeviceObject,
                                          DevicePropertyBootConfiguration,
                                          (PVOID*)&Descriptor);
            if (!NT_SUCCESS(Status))
            {
                /* No configuration has been set */
                Descriptor = NULL;
            }
            else
            {
                /* Root PDO in ReactOS does not assign boot resources */
                UNIMPLEMENTED_DBGBREAK("Encountered during setup\n");
                Descriptor = NULL;
            }

            if (Descriptor)
            {
                /* Root PDO in ReactOS does not assign boot resources */
                UNIMPLEMENTED_DBGBREAK();
            }
            else
            {
                /* Default configuration isn't the normal path on Windows */
                if (PciBreakOnDefault)
                {
                    /* If a second bus is found and there's still no data, crash */
                    KeBugCheckEx(PCI_BUS_DRIVER_INTERNAL,
                                 0xDEAD0010u,
                                 (ULONG_PTR)DeviceObject,
                                 0,
                                 0);
                }

                /* Warn that a default configuration will be used, and set bus 0 */
                DPRINT1("PCI   Will use default configuration.\n");
                PciBreakOnDefault = TRUE;
                FdoExtension->BaseBus = 0;
            }

            /* This is the root bus */
            FdoExtension->BusRootFdoExtension = FdoExtension;
        }

        /* Get the HAL or ACPI Bus Handler Callbacks for Configuration Access */
        Status = PciGetConfigHandlers(FdoExtension);
        if (!NT_SUCCESS(Status)) break;

        /* Initialize all the supported PCI arbiters */
        Status = PciInitializeArbiters(FdoExtension);
        if (!NT_SUCCESS(Status)) break;

        /* This is a real FDO, insert it into the list */
        FdoExtension->Fake = FALSE;
        PciInsertEntryAtTail(&PciFdoExtensionListHead,
                             FdoExtension,
                             &PciGlobalLock);

        /* Open the device registry key so that we can query the errata flags */
        IoOpenDeviceRegistryKey(DeviceObject,
                                PLUGPLAY_REGKEY_DEVICE,
                                KEY_ALL_ACCESS,
                                &KeyHandle),

        /* Open the value that contains errata flags for this bus instance */
        RtlInitUnicodeString(&ValueName, L"HackFlags");
        Status = ZwQueryValueKey(KeyHandle,
                                 &ValueName,
                                 KeyValuePartialInformation,
                                 ValueInfo,
                                 sizeof(Buffer),
                                 &ResultLength);
        ZwClose(KeyHandle);
        if (NT_SUCCESS(Status))
        {
            /* Make sure the data is of expected type and size */
            if ((ValueInfo->Type == REG_DWORD) &&
                (ValueInfo->DataLength == sizeof(ULONG)))
            {
                /* Read the flags for this bus */
                FdoExtension->BusHackFlags = *(PULONG)&ValueInfo->Data;
            }
        }

        /* Query ACPI for PCI HotPlug Support */
        PciGetHotPlugParameters(FdoExtension);

        /* The Bus FDO is now initialized */
        DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
        return STATUS_SUCCESS;
    } while (FALSE);

    /* This is the failure path */
    ASSERT(!NT_SUCCESS(Status));

    /* Check if the FDO extension exists */
    if (FdoExtension) DPRINT1("Should destroy secondaries\n");

    /* Delete device objects */
    if (AttachedTo) IoDetachDevice(AttachedTo);
    if (DeviceObject) IoDeleteDevice(DeviceObject);
    return Status;
}
예제 #5
0
//
// configure bus numbers [checked]
//
VOID PciConfigureBusNumbers(__in PPCI_FDO_EXTENSION FdoExt)
{
	PAGED_CODE();

	PPCI_PDO_EXTENSION PdoExt							= 0;
	if(FdoExt != FdoExt->BusRootFdoExtension)
		PdoExt											= static_cast<PPCI_PDO_EXTENSION>(FdoExt->PhysicalDeviceObject->DeviceExtension);

	KeEnterCriticalRegion();
	KeWaitForSingleObject(&FdoExt->ChildListLock,Executive,KernelMode,FALSE,0);

	PPCI_PDO_EXTENSION BridgeExt						= FdoExt->ChildBridgePdoList;
	ULONG BridgeCount									= 0;
	ULONG ConfiguredBridgeCount							= 0;
	while(BridgeExt)
	{
		if(BridgeExt->NotPresent)
		{
			PciDebugPrintf(0x100000,"Skipping not present bridge PDOX @ %p\n",BridgeExt);
		}
		else
		{
			BridgeCount									+= 1;

			if((!PdoExt || !PdoExt->Dependent.type1.WeChangedBusNumbers || BridgeExt->Common.DeviceState != PciNotStarted) && PciAreBusNumbersConfigured(BridgeExt))
				ConfiguredBridgeCount					+= 1;
			else
				PciDisableBridge(BridgeExt);

		}

		BridgeExt										= BridgeExt->NextBridge;
	}

	KeSetEvent(&FdoExt->ChildListLock,IO_NO_INCREMENT,FALSE);
	KeLeaveCriticalRegion();

	if(!BridgeCount)
	{
		PciDebugPrintf(0x100000,"PCI - No bridges found on bus 0x%x\n",FdoExt->BaseBus);
		return;
	}

	if(BridgeCount == ConfiguredBridgeCount)
	{
		PciDebugPrintf(0x100000,"PCI - 0x%x bridges found on bus 0x%x - all already configured\n",BridgeCount,FdoExt->BaseBus);
		return;
	}

	if(!ConfiguredBridgeCount)
	{
		PciDebugPrintf(0x100000,"PCI - 0x%x bridges found on bus 0x%x - all need configuration\n",BridgeCount,FdoExt->BaseBus);

		return PciSpreadBridges(FdoExt,BridgeCount);
	}

	ASSERT(ConfiguredBridgeCount < BridgeCount);

	PciDebugPrintf(0x100000,"PCI - 0x%x bridges found on bus 0x%x - 0x%x need configuration\n",BridgeCount,FdoExt->BaseBus,BridgeCount - ConfiguredBridgeCount);

	BridgeExt											= FdoExt->ChildBridgePdoList;
	while(BridgeExt)
	{
		if(BridgeExt->NotPresent)
		{
			PciDebugPrintf(0x100000,"Skipping not present bridge PDOX @ %p\n",BridgeExt);
		}
		else
		{
			if((PdoExt && PdoExt->Dependent.type1.WeChangedBusNumbers && BridgeExt->Common.DeviceState == PciNotStarted) || !PciAreBusNumbersConfigured(BridgeExt))
			{
				ASSERT(!BridgeExt->Dependent.type1.PrimaryBus && !BridgeExt->Dependent.type1.SecondaryBus && !BridgeExt->Dependent.type1.SubordinateBus);

				PciFitBridge(FdoExt,PdoExt);
			}
		}

		BridgeExt										= BridgeExt->NextBridge;
	}
}