From 29f98a6645751b4cd06e72c450d2c59d68a79ddd Mon Sep 17 00:00:00 2001 From: evb Date: Thu, 23 Sep 2010 13:24:41 +0000 Subject: [PATCH] - Fix PciFindParentPciFdoExtension bug found by sir_richard "Early break would leave the lock held" - Fix PciGetHackFlags for setup found by sir_richard "Setup currently doesn't have a correct registry" - Fix DriverEntry for setup like PciGetHackFlags - Fix DriverEntry PciOpenKey check found by sir_richard "PciOpenKey returns a BOOLEAN, not an NTSTATUS" - Stop call PciGetAcpiTable found by sir_richard "PciGetAcpiTable is really broken, can lead to infinite loops, and also corrupts memory. We need to fix stefan's bugs" - Implement not root FDO code in PciScanBus and support PCI_HACK_ONE_CHILD - Implement multiple FDO exist code in PciAddDevice so PCI Bridge support now - Implement PciAreBusNumbersConfigured for PCI Bridge support - Hack FDO Start Device by sir_richard "The root FDO does send boot resources if PCIX is installed properly, this code will be needed" - Do PCI_BUS_DRIVER_INTERNAL bugcheck by sir_richard "I have hacked KeBugCheckEx to ignore this for now, until PnP is fixed" - Implement not root FDO code in PciInitializeArbiters - Implement PciCacheLegacyDeviceRouting, PciFindPdoByLocation used by PciAssignSlotResources - Make PciTranslateBusAddress do the stub work - PciAssignSlotResources disabled because ReactOS not support IoAssignResources - Implement PPBridge_ChangeResourceSettings PCIX driver nearly working now. svn path=/trunk/; revision=48851 --- reactos/drivers/bus/pcix/arb/arb_comn.c | 19 +- reactos/drivers/bus/pcix/enum.c | 22 +- reactos/drivers/bus/pcix/fdo.c | 71 +++++-- reactos/drivers/bus/pcix/hookhal.c | 204 ++++++++++++++++++- reactos/drivers/bus/pcix/init.c | 18 +- reactos/drivers/bus/pcix/intrface/routintf.c | 90 ++++++++ reactos/drivers/bus/pcix/pci.h | 53 +++++ reactos/drivers/bus/pcix/pci/busno.c | 20 ++ reactos/drivers/bus/pcix/pci/ppbridge.c | 85 +++++++- reactos/drivers/bus/pcix/utils.c | 11 +- 10 files changed, 549 insertions(+), 44 deletions(-) diff --git a/reactos/drivers/bus/pcix/arb/arb_comn.c b/reactos/drivers/bus/pcix/arb/arb_comn.c index 8d955ed4fd2..195eac539f2 100644 --- a/reactos/drivers/bus/pcix/arb/arb_comn.c +++ b/reactos/drivers/bus/pcix/arb/arb_comn.c @@ -138,20 +138,23 @@ PciInitializeArbiterRanges(IN PPCI_FDO_EXTENSION DeviceExtension, DPRINT1("PCI Warning hot start FDOx %08x, resource ranges not checked.\n", DeviceExtension); return STATUS_INVALID_DEVICE_REQUEST; } - + /* Check for non-root FDO */ if (!PCI_IS_ROOT_FDO(DeviceExtension)) { /* Grab the PDO */ PdoExtension = (PPCI_PDO_EXTENSION)DeviceExtension->PhysicalDeviceObject->DeviceExtension; - ASSERT(PdoExtension->ExtensionType == PciPdoExtensionType); + ASSERT_PDO(PdoExtension); - /* Multiple FDOs are not yet supported */ - UNIMPLEMENTED; - while (TRUE); - return STATUS_SUCCESS; + /* Check if this is a subtractive bus */ + if (PdoExtension->Dependent.type1.SubtractiveDecode) + { + /* There is nothing to do regarding arbitration of resources */ + DPRINT1("PCI Skipping arbiter initialization for subtractive bridge FDOX %p\n", DeviceExtension); + return STATUS_SUCCESS; + } } - + /* Loop all arbiters */ for (ArbiterType = PciArb_Io; ArbiterType <= PciArb_Memory; ArbiterType++) { @@ -171,7 +174,7 @@ PciInitializeArbiterRanges(IN PPCI_FDO_EXTENSION DeviceExtension, /* Ignore anything else */ continue; } - + /* Find an arbiter of this type */ Instance = PciFindNextSecondaryExtension(&DeviceExtension->SecondaryExtension, ArbiterType); diff --git a/reactos/drivers/bus/pcix/enum.c b/reactos/drivers/bus/pcix/enum.c index 1aaebb75dcd..5fb207005da 100644 --- a/reactos/drivers/bus/pcix/enum.c +++ b/reactos/drivers/bus/pcix/enum.c @@ -1575,15 +1575,31 @@ PciScanBus(IN PPCI_FDO_EXTENSION DeviceExtension) PWCHAR DescriptionText; USHORT SubVendorId, SubSystemId; PCI_CAPABILITIES_HEADER CapHeader, PcixCapHeader; + UCHAR SecondaryBus; DPRINT1("PCI Scan Bus: FDO Extension @ 0x%x, Base Bus = 0x%x\n", DeviceExtension, DeviceExtension->BaseBus); /* Is this the root FDO? */ if (!PCI_IS_ROOT_FDO(DeviceExtension)) { - /* Other FDOs are not currently supported */ - UNIMPLEMENTED; - while (TRUE); + /* Get the PDO for the child bus */ + PdoExtension = DeviceExtension->PhysicalDeviceObject->DeviceExtension; + ASSERT_PDO(PdoExtension); + + /* Check for hack which only allows bus to have one child device */ + if (PdoExtension->HackFlags & PCI_HACK_ONE_CHILD) MaxDevice = 1; + + /* Check if the secondary bus number has changed */ + PciReadDeviceConfig(PdoExtension, + &SecondaryBus, + FIELD_OFFSET(PCI_COMMON_HEADER, u.type1.SecondaryBus), + sizeof(UCHAR)); + if (SecondaryBus != PdoExtension->Dependent.type1.SecondaryBus) + { + DPRINT1("PCI: Bus numbers have been changed! Restoring originals.\n"); + UNIMPLEMENTED; + while (TRUE); + } } /* Loop every device on the bus */ diff --git a/reactos/drivers/bus/pcix/fdo.c b/reactos/drivers/bus/pcix/fdo.c index 2054f65703d..847585e4483 100644 --- a/reactos/drivers/bus/pcix/fdo.c +++ b/reactos/drivers/bus/pcix/fdo.c @@ -89,7 +89,6 @@ PciFdoIrpStartDevice(IN PIRP Irp, /* Check for any boot-provided resources */ Resources = IoStackLocation->Parameters.StartDevice.AllocatedResources; - DPRINT1("Resources: %p\n", Resources); if ((Resources) && !(PCI_IS_ROOT_FDO(DeviceExtension))) { /* These resources would only be for non-root FDOs, unhandled for now */ @@ -227,7 +226,7 @@ PciFdoIrpQueryInterface(IN PIRP Irp, /* Deleted extensions don't respond to IRPs */ if (DeviceExtension->DeviceState == PciDeleted) { - /* Hand it bacO try to deal with it */ + /* Hand it back to try to deal with it */ return PciPassIrpFromFdoToPdo(DeviceExtension, Irp); } @@ -436,6 +435,7 @@ PciAddDevice(IN PDRIVER_OBJECT DriverObject, 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; @@ -449,6 +449,8 @@ PciAddDevice(IN PDRIVER_OBJECT DriverObject, /* Zero out variables so failure path knows what to do */ AttachedTo = NULL; + FdoExtension = NULL; + PdoExtension = NULL; do { /* Check if there's already a device extension for this bus */ @@ -456,9 +458,44 @@ PciAddDevice(IN PDRIVER_OBJECT DriverObject, &PciGlobalLock); if (ParentExtension) { - /* More than one PCI bus, this is not expected yet */ - UNIMPLEMENTED; - while (TRUE); + /* 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 */ @@ -484,11 +521,15 @@ PciAddDevice(IN PDRIVER_OBJECT DriverObject, ASSERT(AttachedTo != NULL); if (!AttachedTo) break; FdoExtension->AttachedDeviceObject = AttachedTo; + + /* Check if this is a child bus, or the root */ if (ParentExtension) { - /* More than one PCI bus, this is not expected yet */ - UNIMPLEMENTED; - while (TRUE); + /* The child inherits root data */ + FdoExtension->BaseBus = PdoExtension->Dependent.type1.SecondaryBus; + FdoExtension->BusRootFdoExtension = ParentExtension->BusRootFdoExtension; + PdoExtension->BridgeFdoExtension = FdoExtension; + FdoExtension->ParentFdoExtension = ParentExtension; } else { @@ -505,7 +546,9 @@ PciAddDevice(IN PDRIVER_OBJECT DriverObject, { /* Root PDO in ReactOS does not assign boot resources */ UNIMPLEMENTED; - while (TRUE); +// while (TRUE); + DPRINT1("Encountered during setup\n"); + Descriptor = NULL; } if (Descriptor) @@ -520,15 +563,11 @@ PciAddDevice(IN PDRIVER_OBJECT DriverObject, if (PciBreakOnDefault) { /* If a second bus is found and there's still no data, crash */ - #if 0 // ros bug? KeBugCheckEx(PCI_BUS_DRIVER_INTERNAL, 0xDEAD0010u, (ULONG_PTR)DeviceObject, 0, 0); - #else - DPRINT1("Windows would crash!\n"); - #endif } /* Warn that a default configuration will be used, and set bus 0 */ @@ -586,12 +625,16 @@ PciAddDevice(IN PDRIVER_OBJECT DriverObject, /* The Bus FDO is now initialized */ DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; - DPRINT1("PCI Root FDO Added: %p %p\n", DeviceObject, FdoExtension); 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; diff --git a/reactos/drivers/bus/pcix/hookhal.c b/reactos/drivers/bus/pcix/hookhal.c index 7a36024d11e..902b287fb89 100644 --- a/reactos/drivers/bus/pcix/hookhal.c +++ b/reactos/drivers/bus/pcix/hookhal.c @@ -27,10 +27,88 @@ PciTranslateBusAddress(IN INTERFACE_TYPE InterfaceType, OUT PULONG AddressSpace, OUT PPHYSICAL_ADDRESS TranslatedAddress) { - /* This function is not yet implemented */ + /* FIXME: Broken translation */ UNIMPLEMENTED; - while (TRUE); - return FALSE; + TranslatedAddress->QuadPart = BusAddress.QuadPart; + return TRUE; +} + +PPCI_PDO_EXTENSION +NTAPI +PciFindPdoByLocation(IN ULONG BusNumber, + IN ULONG SlotNumber) +{ + PPCI_FDO_EXTENSION DeviceExtension; + PPCI_PDO_EXTENSION PdoExtension; + PCI_SLOT_NUMBER PciSlot; + PciSlot.u.AsULONG = SlotNumber; + + /* Acquire the global lock */ + KeEnterCriticalRegion(); + KeWaitForSingleObject(&PciGlobalLock, Executive, KernelMode, FALSE, NULL); + + /* Now search for the extension */ + DeviceExtension = (PPCI_FDO_EXTENSION)PciFdoExtensionListHead.Next; + while (DeviceExtension) + { + /* If we found it, break out */ + if (DeviceExtension->BaseBus == BusNumber) break; + + /* Move to the next device */ + DeviceExtension = (PPCI_FDO_EXTENSION)DeviceExtension->List.Next; + } + + /* Release the global lock */ + KeSetEvent(&PciGlobalLock, IO_NO_INCREMENT, FALSE); + KeLeaveCriticalRegion(); + + /* Check if the device extension for the bus was found */ + if (!DeviceExtension) + { + /* It wasn't, bail out */ + DPRINT1("Pci: Could not find PCI bus FDO. Bus Number = 0x%x\n", BusNumber); + return NULL; + } + + /* Acquire this device's lock */ + KeEnterCriticalRegion(); + KeWaitForSingleObject(&DeviceExtension->ChildListLock, + Executive, + KernelMode, + FALSE, + NULL); + + /* Loop every child PDO */ + for (PdoExtension = DeviceExtension->ChildPdoList; + PdoExtension; + PdoExtension = PdoExtension->Next) + { + /* Check if the function number and header data matches */ + if ((PdoExtension->Slot.u.bits.FunctionNumber == PciSlot.u.bits.FunctionNumber) && + (PdoExtension->Slot.u.bits.DeviceNumber == PciSlot.u.bits.DeviceNumber)) + { + /* This is considered to be the same PDO */ + ASSERT(PdoExtension->Slot.u.AsULONG == PciSlot.u.AsULONG); + break; + } + } + + /* Release this device's lock */ + KeSetEvent(&DeviceExtension->ChildListLock, IO_NO_INCREMENT, FALSE); + KeLeaveCriticalRegion(); + + /* Check if we found something */ + if (!PdoExtension) + { + /* Let the debugger know */ + DPRINT1("Pci: Could not find PDO for device @ %x.%x.%x\n", + BusNumber, + PciSlot.u.bits.DeviceNumber, + PciSlot.u.bits.FunctionNumber); + } + + /* If the search found something, this is non-NULL, otherwise it's NULL */ + return PdoExtension; } NTSTATUS @@ -44,10 +122,120 @@ PciAssignSlotResources(IN PUNICODE_STRING RegistryPath, IN ULONG SlotNumber, IN OUT PCM_RESOURCE_LIST *AllocatedResources) { - /* This function is not yet implemented */ - UNIMPLEMENTED; - while (TRUE); - return STATUS_NOT_SUPPORTED; + PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList = NULL; + PCM_RESOURCE_LIST Resources = NULL; + PCI_COMMON_HEADER PciData; + PPCI_PDO_EXTENSION PdoExtension; + NTSTATUS Status; + PDEVICE_OBJECT ExistingDeviceObject; + PAGED_CODE(); + ASSERT(PcipSavedAssignSlotResources); + ASSERT(BusType == PCIBus); + + /* Assume no resources */ + *AllocatedResources = NULL; + + /* Find the PDO for this slot and make sure it exists and is started */ + PdoExtension = PciFindPdoByLocation(BusNumber, SlotNumber); + if (!PdoExtension) return STATUS_DEVICE_DOES_NOT_EXIST; + if (PdoExtension->DeviceState == PciNotStarted) return STATUS_INVALID_OWNER; + + /* Acquire the global lock while we attempt to assign resources */ + KeEnterCriticalRegion(); + KeWaitForSingleObject(&PciGlobalLock, Executive, KernelMode, FALSE, NULL); + do + { + /* Make sure we're not on the PDO for some reason */ + ASSERT(DeviceObject != PdoExtension->PhysicalDeviceObject); + + /* Read the PCI header and cache the routing information */ + PciReadDeviceConfig(PdoExtension, &PciData, 0, PCI_COMMON_HDR_LENGTH); + Status = PciCacheLegacyDeviceRouting(DeviceObject, + BusNumber, + SlotNumber, + PciData.u.type0.InterruptLine, + PciData.u.type0.InterruptPin, + PciData.BaseClass, + PciData.SubClass, + PdoExtension->ParentFdoExtension-> + PhysicalDeviceObject, + PdoExtension, + &ExistingDeviceObject); + if (NT_SUCCESS(Status)) + { + /* Manually build the requirements for this device, and mark it legacy */ + Status = PciBuildRequirementsList(PdoExtension, + &PciData, + &RequirementsList); + PdoExtension->LegacyDriver = TRUE; + if (NT_SUCCESS(Status)) + { + /* Now call the legacy Pnp function to actually assign resources */ + Status = IoAssignResources(RegistryPath, + DriverClassName, + DriverObject, + DeviceObject, + RequirementsList, + &Resources); + if (NT_SUCCESS(Status)) + { + /* Resources are ready, so enable all decodes */ + PdoExtension->CommandEnables |= (PCI_ENABLE_IO_SPACE | + PCI_ENABLE_MEMORY_SPACE | + PCI_ENABLE_BUS_MASTER); + + /* Compute new resource settings based on what PnP assigned */ + PciComputeNewCurrentSettings(PdoExtension, Resources); + + /* Set these new resources on the device */ + Status = PciSetResources(PdoExtension, TRUE, TRUE); + if (NT_SUCCESS(Status)) + { + /* Some work needs to happen here to handle this */ + ASSERT(Resources->Count == 1); + //ASSERT(PartialList->Count > 0); + + UNIMPLEMENTED; + + /* Return the allocated resources, and success */ + *AllocatedResources = Resources; + Resources = NULL; + Status = STATUS_SUCCESS; + } + } + else + { + /* If assignment failed, no resources should exist */ + ASSERT(Resources == NULL); + } + + /* If assignment succeeed, then we are done */ + if (NT_SUCCESS(Status)) break; + } + + /* Otherwise, cache the new routing */ + PciCacheLegacyDeviceRouting(ExistingDeviceObject, + BusNumber, + SlotNumber, + PciData.u.type0.InterruptLine, + PciData.u.type0.InterruptPin, + PciData.BaseClass, + PciData.SubClass, + PdoExtension->ParentFdoExtension-> + PhysicalDeviceObject, + PdoExtension, + NULL); + } + } while (0); + + /* Release the lock */ + KeSetEvent(&PciGlobalLock, 0, 0); + KeLeaveCriticalRegion(); + + /* Free any temporary resource data and return the status */ + if (RequirementsList) ExFreePoolWithTag(RequirementsList, 0); + if (Resources) ExFreePoolWithTag(Resources, 0); + return Status; } VOID @@ -61,7 +249,7 @@ PciHookHal(VOID) PcipSavedTranslateBusAddress = HalPciTranslateBusAddress; /* Take over the HAL's Bus Handler functions */ - HalPciAssignSlotResources = PciAssignSlotResources; +// HalPciAssignSlotResources = PciAssignSlotResources; HalPciTranslateBusAddress = PciTranslateBusAddress; } diff --git a/reactos/drivers/bus/pcix/init.c b/reactos/drivers/bus/pcix/init.c index 07f226a279b..45e02ae011f 100644 --- a/reactos/drivers/bus/pcix/init.c +++ b/reactos/drivers/bus/pcix/init.c @@ -641,6 +641,7 @@ PciBuildHackTable(IN HANDLE KeyHandle) Entry->HackFlags = HackFlags; /* Print out for the debugger's sake */ +#ifdef HACK_DEBUG DPRINT1("Adding Hack entry for Vendor:0x%04x Device:0x%04x ", Entry->VendorID, Entry->DeviceID); if (Entry->Flags & PCI_HACK_HAS_SUBSYSTEM_INFO) @@ -649,6 +650,7 @@ PciBuildHackTable(IN HANDLE KeyHandle) if (Entry->Flags & PCI_HACK_HAS_REVISION_INFO) DbgPrint("Revision:0x%02x", Entry->RevisionID); DbgPrint(" = 0x%I64x\n", Entry->HackFlags); +#endif } /* Bail out in case of failure */ @@ -705,6 +707,12 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject, UNICODE_STRING OptionString, PciLockString; NTSTATUS Status; DPRINT1("PCI: DriverEntry!\n"); + + /* Setup initial loop variables */ + KeyHandle = NULL; + ParametersKey = NULL; + DebugKey = NULL; + ControlSetKey = NULL; do { /* Remember our object so we can get it to it later */ @@ -735,11 +743,11 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject, KEY_QUERY_VALUE, &ParametersKey, &Status); - if (!Result) break; + //if (!Result) break; /* Build the list of all known PCI erratas */ Status = PciBuildHackTable(ParametersKey); - if (!NT_SUCCESS(Status)) break; + //if (!NT_SUCCESS(Status)) break; /* Open the debug key, if it exists */ Result = PciOpenKey(L"Debug", @@ -760,12 +768,12 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject, KeInitializeEvent(&PciLegacyDescriptionLock, SynchronizationEvent, TRUE); /* Open the control set key */ - Status = PciOpenKey(L"\\Registry\\Machine\\System\\CurrentControlSet", + Result = PciOpenKey(L"\\Registry\\Machine\\System\\CurrentControlSet", NULL, KEY_QUERY_VALUE, &ControlSetKey, &Status); - if (!NT_SUCCESS(Status)) break; + if (!Result) break; /* Read the command line */ Status = PciGetRegistryValue(L"SystemStartOptions", @@ -852,7 +860,7 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject, if (PciRunningDatacenter) DPRINT1("PCI running on datacenter build\n"); /* Check if the system has an ACPI Hardware Watchdog Timer */ - WdTable = PciGetAcpiTable(WDRT_SIGNATURE); + //WdTable = PciGetAcpiTable(WDRT_SIGNATURE); Status = STATUS_SUCCESS; } while (FALSE); diff --git a/reactos/drivers/bus/pcix/intrface/routintf.c b/reactos/drivers/bus/pcix/intrface/routintf.c index e910b7c47f6..d7b7b458b4d 100644 --- a/reactos/drivers/bus/pcix/intrface/routintf.c +++ b/reactos/drivers/bus/pcix/intrface/routintf.c @@ -14,6 +14,8 @@ /* GLOBALS ********************************************************************/ +PPCI_LEGACY_DEVICE PciLegacyDeviceHead; + PCI_INTERFACE PciRoutingInterface = { &GUID_INT_ROUTE_INTERFACE_STANDARD, @@ -55,4 +57,92 @@ routeintrf_Constructor(IN PVOID DeviceExtension, while (TRUE); } +NTSTATUS +NTAPI +PciCacheLegacyDeviceRouting(IN PDEVICE_OBJECT DeviceObject, + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN UCHAR InterruptLine, + IN UCHAR InterruptPin, + IN UCHAR BaseClass, + IN UCHAR SubClass, + IN PDEVICE_OBJECT PhysicalDeviceObject, + IN PPCI_PDO_EXTENSION PdoExtension, + OUT PDEVICE_OBJECT *pFoundDeviceObject) +{ + PPCI_LEGACY_DEVICE *Link; + PPCI_LEGACY_DEVICE LegacyDevice; + PDEVICE_OBJECT FoundDeviceObject; + PAGED_CODE(); + + /* Scan current registered devices */ + LegacyDevice = PciLegacyDeviceHead; + Link = &PciLegacyDeviceHead; + while (LegacyDevice) + { + /* Find a match */ + if ((BusNumber == LegacyDevice->BusNumber) && + (SlotNumber == LegacyDevice->SlotNumber)) + { + /* We already know about this routing */ + break; + } + + /* We know about device already, but for a different location */ + if (LegacyDevice->DeviceObject == DeviceObject) + { + /* Free the existing structure, move to the next one */ + *Link = LegacyDevice->Next; + ExFreePoolWithTag(LegacyDevice, 0); + LegacyDevice = *Link; + } + else + { + /* Keep going */ + Link = &LegacyDevice->Next; + LegacyDevice = LegacyDevice->Next; + } + } + + /* Did we find a match? */ + if (!LegacyDevice) + { + /* Allocate a new cache structure */ + LegacyDevice = ExAllocatePoolWithTag(PagedPool, + sizeof(PCI_LEGACY_DEVICE), + 'PciR'); + if (!LegacyDevice) return STATUS_INSUFFICIENT_RESOURCES; + + /* Save all the data in it */ + RtlZeroMemory(LegacyDevice, sizeof(PCI_LEGACY_DEVICE)); + LegacyDevice->BusNumber = BusNumber; + LegacyDevice->SlotNumber = SlotNumber; + LegacyDevice->InterruptLine = InterruptLine; + LegacyDevice->InterruptPin = InterruptPin; + LegacyDevice->BaseClass = BaseClass; + LegacyDevice->SubClass = SubClass; + LegacyDevice->PhysicalDeviceObject = PhysicalDeviceObject; + LegacyDevice->DeviceObject = DeviceObject; + LegacyDevice->PdoExtension = PdoExtension; + + /* Link it in the list */ + LegacyDevice->Next = PciLegacyDeviceHead; + PciLegacyDeviceHead = LegacyDevice; + } + + /* Check if we found, or created, a matching caching structure */ + FoundDeviceObject = LegacyDevice->DeviceObject; + if (FoundDeviceObject == DeviceObject) + { + /* Return the device object and success */ + if (pFoundDeviceObject) *pFoundDeviceObject = DeviceObject; + return STATUS_SUCCESS; + } + + /* Otherwise, this is a new device object for this location */ + LegacyDevice->DeviceObject = DeviceObject; + if (pFoundDeviceObject) *pFoundDeviceObject = FoundDeviceObject; + return STATUS_SUCCESS; +} + /* EOF */ diff --git a/reactos/drivers/bus/pcix/pci.h b/reactos/drivers/bus/pcix/pci.h index d1b8f9faec7..c1984da84d6 100644 --- a/reactos/drivers/bus/pcix/pci.h +++ b/reactos/drivers/bus/pcix/pci.h @@ -514,6 +514,24 @@ typedef struct _PCI_IPI_CONTEXT PVOID Context; } PCI_IPI_CONTEXT, *PPCI_IPI_CONTEXT; +// +// PCI Legacy Device Location Cache +// +typedef struct _PCI_LEGACY_DEVICE +{ + struct _PCI_LEGACY_DEVICE *Next; + PDEVICE_OBJECT DeviceObject; + ULONG BusNumber; + ULONG SlotNumber; + UCHAR InterruptLine; + UCHAR InterruptPin; + UCHAR BaseClass; + UCHAR SubClass; + PDEVICE_OBJECT PhysicalDeviceObject; + ROUTING_TOKEN RoutingToken; + PPCI_PDO_EXTENSION PdoExtension; +} PCI_LEGACY_DEVICE, *PPCI_LEGACY_DEVICE; + // // IRP Dispatch Routines // @@ -1560,6 +1578,14 @@ PciSetResources( IN BOOLEAN SomethingSomethingDarkSide ); +NTSTATUS +NTAPI +PciBuildRequirementsList( + IN PPCI_PDO_EXTENSION PdoExtension, + IN PPCI_COMMON_HEADER PciData, + OUT PIO_RESOURCE_REQUIREMENTS_LIST* Buffer +); + // // Identification Functions // @@ -1734,6 +1760,33 @@ PPBridge_ChangeResourceSettings( IN PPCI_COMMON_HEADER PciData ); +// +// Bus Number Routines +// +BOOLEAN +NTAPI +PciAreBusNumbersConfigured( + IN PPCI_PDO_EXTENSION PdoExtension +); + +// +// Routine Interface +// +NTSTATUS +NTAPI +PciCacheLegacyDeviceRouting( + IN PDEVICE_OBJECT DeviceObject, + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN UCHAR InterruptLine, + IN UCHAR InterruptPin, + IN UCHAR BaseClass, + IN UCHAR SubClass, + IN PDEVICE_OBJECT PhysicalDeviceObject, + IN PPCI_PDO_EXTENSION PdoExtension, + OUT PDEVICE_OBJECT *pFoundDeviceObject +); + // // External Resources // diff --git a/reactos/drivers/bus/pcix/pci/busno.c b/reactos/drivers/bus/pcix/pci/busno.c index e5a981631c4..6b6316493f3 100644 --- a/reactos/drivers/bus/pcix/pci/busno.c +++ b/reactos/drivers/bus/pcix/pci/busno.c @@ -16,4 +16,24 @@ /* FUNCTIONS ******************************************************************/ +BOOLEAN +NTAPI +PciAreBusNumbersConfigured(IN PPCI_PDO_EXTENSION PdoExtension) +{ + PAGED_CODE(); + UCHAR PrimaryBus, BaseBus, SecondaryBus, SubordinateBus; + + /* Get all relevant bus number details */ + PrimaryBus = PdoExtension->Dependent.type1.PrimaryBus; + BaseBus = PdoExtension->ParentFdoExtension->BaseBus; + SecondaryBus = PdoExtension->Dependent.type1.SecondaryBus; + SubordinateBus = PdoExtension->Dependent.type1.SubordinateBus; + + /* The primary bus should be the base bus of the parent */ + if ((PrimaryBus != BaseBus) || (SecondaryBus <= PrimaryBus)) return FALSE; + + /* The subordinate should be a higher bus number than the secondary */ + return SubordinateBus >= SecondaryBus; +} + /* EOF */ diff --git a/reactos/drivers/bus/pcix/pci/ppbridge.c b/reactos/drivers/bus/pcix/pci/ppbridge.c index a6d942a7e61..b7a9356bf25 100644 --- a/reactos/drivers/bus/pcix/pci/ppbridge.c +++ b/reactos/drivers/bus/pcix/pci/ppbridge.c @@ -680,8 +680,89 @@ NTAPI PPBridge_ChangeResourceSettings(IN PPCI_PDO_EXTENSION PdoExtension, IN PPCI_COMMON_HEADER PciData) { - UNIMPLEMENTED; - while (TRUE); + BOOLEAN IoActive; + PPCI_FDO_EXTENSION FdoExtension; + PPCI_FUNCTION_RESOURCES PciResources; + ULONG i; + + /* Check if I/O Decodes are enabled */ + IoActive = (PciData->u.type1.IOBase & 0xF) == 1; + + /* + * Check for Intel ICH PCI-to-PCI (i82801) bridges (used on the i810, + * i820, i840, i845 Chipsets) that don't have subtractive decode broken. + * If they do have broken subtractive support, or if they are not ICH bridges, + * then check if the bridge supports substractive decode at all. + */ + if ((((PdoExtension->VendorId == 0x8086) && + ((PdoExtension->DeviceId == 0x2418) || + (PdoExtension->DeviceId == 0x2428) || + (PdoExtension->DeviceId == 0x244E) || + (PdoExtension->DeviceId == 0x2448))) && + (!(PdoExtension->HackFlags & PCI_HACK_BROKEN_SUBTRACTIVE_DECODE) || + (PdoExtension->Dependent.type1.SubtractiveDecode == FALSE))) || + (PdoExtension->Dependent.type1.SubtractiveDecode == FALSE)) + { + /* No resources are needed on a subtractive decode bridge */ + PciData->u.type1.MemoryBase = 0xFFFF; + PciData->u.type1.PrefetchBase = 0xFFFF; + PciData->u.type1.IOBase = 0xFF; + PciData->u.type1.IOLimit = 0; + PciData->u.type1.MemoryLimit = 0; + PciData->u.type1.PrefetchLimit = 0; + PciData->u.type1.PrefetchBaseUpper32 = 0; + PciData->u.type1.PrefetchLimitUpper32 = 0; + PciData->u.type1.IOBaseUpper16 = 0; + PciData->u.type1.IOLimitUpper16 = 0; + } + else + { + /* + * Otherwise, get the FDO to read the old PCI configuration header that + * had been saved by the hack in PPBridge_SaveCurrentSettings. + */ + FdoExtension = PdoExtension->ParentFdoExtension; + ASSERT(PdoExtension->Resources == NULL); + + /* Read the PCI header data and use that here */ + PciData->u.type1.IOBase = FdoExtension->PreservedConfig->u.type1.IOBase; + PciData->u.type1.IOLimit = FdoExtension->PreservedConfig->u.type1.IOLimit; + PciData->u.type1.MemoryBase = FdoExtension->PreservedConfig->u.type1.MemoryBase; + PciData->u.type1.MemoryLimit = FdoExtension->PreservedConfig->u.type1.MemoryLimit; + PciData->u.type1.PrefetchBase = FdoExtension->PreservedConfig->u.type1.PrefetchBase; + PciData->u.type1.PrefetchLimit = FdoExtension->PreservedConfig->u.type1.PrefetchLimit; + PciData->u.type1.PrefetchBaseUpper32 = FdoExtension->PreservedConfig->u.type1.PrefetchBaseUpper32; + PciData->u.type1.PrefetchLimitUpper32 = FdoExtension->PreservedConfig->u.type1.PrefetchLimitUpper32; + PciData->u.type1.IOBaseUpper16 = FdoExtension->PreservedConfig->u.type1.IOBaseUpper16; + PciData->u.type1.IOLimitUpper16 = FdoExtension->PreservedConfig->u.type1.IOLimitUpper16; + } + + /* Loop bus resources */ + PciResources = PdoExtension->Resources; + if (PciResources) + { + /* Loop each resource type (the BARs, ROM BAR and Prefetch) */ + for (i = 0; i < 6; i++) + { + UNIMPLEMENTED; + } + } + + /* Copy the bus number data */ + PciData->u.type1.PrimaryBus = PdoExtension->Dependent.type1.PrimaryBus; + PciData->u.type1.SecondaryBus = PdoExtension->Dependent.type1.SecondaryBus; + PciData->u.type1.SubordinateBus = PdoExtension->Dependent.type1.SubordinateBus; + + /* Copy the decode flags */ + if (PdoExtension->Dependent.type1.IsaBitSet) + { + PciData->u.type1.BridgeControl |= PCI_ENABLE_BRIDGE_ISA; + } + + if (PdoExtension->Dependent.type1.VgaBitSet) + { + PciData->u.type1.BridgeControl |= PCI_ENABLE_BRIDGE_VGA; + } } /* EOF */ diff --git a/reactos/drivers/bus/pcix/utils.c b/reactos/drivers/bus/pcix/utils.c index 24f442ae16d..5948e8a5168 100644 --- a/reactos/drivers/bus/pcix/utils.c +++ b/reactos/drivers/bus/pcix/utils.c @@ -369,16 +369,16 @@ PciFindParentPciFdoExtension(IN PDEVICE_OBJECT DeviceObject, /* Scan all children PDO, stop when no more PDOs, or found it */ for (FoundExtension = DeviceExtension->ChildPdoList; - FoundExtension && (FoundExtension != SearchExtension); + ((FoundExtension) && (FoundExtension != SearchExtension)); FoundExtension = FoundExtension->Next); - /* If we found it, break out */ - if (FoundExtension) break; - /* Release this device's lock */ KeSetEvent(&DeviceExtension->ChildListLock, IO_NO_INCREMENT, FALSE); KeLeaveCriticalRegion(); + /* If we found it, break out */ + if (FoundExtension) break; + /* Move to the next device */ DeviceExtension = (PPCI_FDO_EXTENSION)DeviceExtension->List.Next; } @@ -611,6 +611,9 @@ PciGetHackFlags(IN USHORT VendorId, ULONGLONG HackFlags; ULONG LastWeight, MatchWeight; ULONG EntryFlags; + + /* ReactOS SetupLDR Hack */ + if (!PciHackTable) return 0; /* Initialize the variables before looping */ LastWeight = 0;