Sync with trunk r58740.
[reactos.git] / drivers / bus / pcix / hookhal.c
index 7a36024..902b287 100644 (file)
@@ -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;
 }