Add config interface start (PciReadWriteConfigSpace, PciReadSlotConfig)
[reactos.git] / reactos / drivers / bus / pcix / enum.c
index d67db28..89cb5f8 100644 (file)
 
 /* FUNCTIONS ******************************************************************/
 
+NTSTATUS
+NTAPI
+PciScanBus(IN PPCI_FDO_EXTENSION DeviceExtension)
+{
+    ULONG MaxDevice = PCI_MAX_DEVICES;
+    ULONG i, j, k;
+    UCHAR Buffer[PCI_COMMON_HDR_LENGTH];
+    PPCI_COMMON_HEADER PciData = (PVOID)Buffer;
+    PCI_SLOT_NUMBER PciSlot;
+    PWCHAR DescriptionText;
+    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);
+    }
+
+    /* Loop every device on the bus */
+    PciSlot.u.bits.Reserved = 0;
+    i = DeviceExtension->BaseBus;
+    for (j = 0; j < MaxDevice; j++)
+    {
+        /* Loop every function of each device */
+        PciSlot.u.bits.DeviceNumber = j;
+        for (k = 0; k < PCI_MAX_FUNCTION; k++)
+        {
+            /* Build the final slot structure */
+            PciSlot.u.bits.FunctionNumber = k;
+
+            /* Read the vendor for this slot */
+            PciReadSlotConfig(DeviceExtension,
+                              PciSlot,
+                              PciData,
+                              0,
+                              sizeof(USHORT));
+
+            /* Skip invalid device */
+            if (PciData->VendorID == PCI_INVALID_VENDORID) continue;
+
+            /* Now read the whole header */
+            PciReadSlotConfig(DeviceExtension,
+                              PciSlot,
+                              &PciData->DeviceID,
+                              sizeof(USHORT),
+                              PCI_COMMON_HDR_LENGTH - sizeof(USHORT));
+
+            /* Dump device that was found */
+            DPRINT1("Scan Found Device 0x%x (b=0x%x, d=0x%x, f=0x%x)\n",
+                    PciSlot.u.AsULONG,
+                    i,
+                    j,
+                    k);
+
+            /* Dump the device's header */
+            PciDebugDumpCommonConfig(PciData);
+
+            /* Find description for this device for the debugger's sake */
+            DescriptionText = PciGetDeviceDescriptionMessage(PciData->BaseClass,
+                                                             PciData->SubClass);
+            DPRINT1("Device Description \"%S\".\n", DescriptionText ? DescriptionText : L"(NULL)");
+            if (DescriptionText) ExFreePoolWithTag(DescriptionText, 0);
+
+            /* Check if there is an ACPI Watchdog Table */
+            if (WdTable)
+            {
+                /* Check if this PCI device is the ACPI Watchdog Device... */
+                UNIMPLEMENTED;
+                while (TRUE);
+            }
+        }
+    }
+
+    /* Enumeration is completed */
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+PciQueryDeviceRelations(IN PPCI_FDO_EXTENSION DeviceExtension,
+                        IN OUT PDEVICE_RELATIONS *pDeviceRelations)
+{
+    NTSTATUS Status;
+    PPCI_PDO_EXTENSION PdoExtension;
+    ULONG PdoCount = 0;
+    PDEVICE_RELATIONS DeviceRelations, NewRelations;
+    SIZE_T Size;
+    PDEVICE_OBJECT DeviceObject, *ObjectArray;
+    PAGED_CODE();
+
+    /* Make sure the FDO is started */
+    ASSERT(DeviceExtension->DeviceState == PciStarted);
+
+    /* Synchronize while we enumerate the bus */
+    Status = PciBeginStateTransition(DeviceExtension, PciSynchronizedOperation);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Scan all children PDO */
+    for (PdoExtension = DeviceExtension->ChildPdoList;
+         PdoExtension;
+         PdoExtension = PdoExtension->Next)
+    {
+        /* Invalidate them */
+        PdoExtension->NotPresent = TRUE;
+    }
+
+    /* Scan the PCI Bus */
+    Status = PciScanBus(DeviceExtension);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Enumerate all children PDO again */
+    for (PdoExtension = DeviceExtension->ChildPdoList;
+         PdoExtension;
+         PdoExtension = PdoExtension->Next)
+    {
+        /* Check for PDOs that are still invalidated */
+        if (PdoExtension->NotPresent)
+        {
+            /* This means this PDO existed before, but not anymore */
+            PdoExtension->ReportedMissing = TRUE;
+            DPRINT1("PCI - Old device (pdox) %08x not found on rescan.\n",
+                    PdoExtension);
+        }
+        else
+        {
+            /* Increase count of detected PDOs */
+            PdoCount++;
+        }
+    }
+
+    /* Read the current relations and add the newly discovered relations */
+    DeviceRelations = *pDeviceRelations;
+    Size = FIELD_OFFSET(DEVICE_RELATIONS, Objects) +
+           PdoCount * sizeof(PDEVICE_OBJECT);
+    if (DeviceRelations) Size += sizeof(PDEVICE_OBJECT) * DeviceRelations->Count;
+
+    /* Allocate the device relations */
+    NewRelations = (PDEVICE_RELATIONS)ExAllocatePoolWithTag(0, Size, 'BicP');
+    if (!NewRelations)
+    {
+        /* Out of space, cancel the operation */
+        PciCancelStateTransition(DeviceExtension, PciSynchronizedOperation);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* Check if there were any older relations */
+    NewRelations->Count = 0;
+    if (DeviceRelations)
+    {
+        /* Copy the old relations into the new buffer, then free the old one */
+        RtlCopyMemory(NewRelations,
+                      DeviceRelations,
+                      FIELD_OFFSET(DEVICE_RELATIONS, Objects) +
+                      DeviceRelations->Count * sizeof(PDEVICE_OBJECT));
+        ExFreePoolWithTag(DeviceRelations, 0);
+    }
+
+    /* Print out that we're ready to dump relations */
+    DPRINT1("PCI QueryDeviceRelations/BusRelations FDOx %08x (bus 0x%02x)\n",
+            DeviceExtension,
+            DeviceExtension->BaseBus);
+
+    /* Loop the current PDO children and the device relation object array */
+    PdoExtension = DeviceExtension->ChildPdoList;
+    ObjectArray = &NewRelations->Objects[NewRelations->Count];
+    while (PdoExtension)
+    {
+        /* Dump this relation */
+        DPRINT1("  QDR PDO %08x (x %08x)%s\n",
+                PdoExtension->PhysicalDeviceObject,
+                PdoExtension,
+                PdoExtension->NotPresent ?
+                "<Omitted, device flaged not present>" : "");
+
+        /* Is this PDO present? */
+        if (!PdoExtension->NotPresent)
+        {
+            /* Reference it and add it to the array */
+            DeviceObject = PdoExtension->PhysicalDeviceObject;
+            ObfReferenceObject(DeviceObject);
+            *ObjectArray++ = DeviceObject;
+        }
+
+        /* Go to the next PDO */
+        PdoExtension = PdoExtension->Next;
+    }
+
+    /* Terminate dumping the relations */
+    DPRINT1("  QDR Total PDO count = %d (%d already in list)\n",
+            NewRelations->Count + PdoCount,
+            NewRelations->Count);
+
+    /* Return the final count and the new buffer */
+    NewRelations->Count += PdoCount;
+    *pDeviceRelations = NewRelations;
+    return STATUS_SUCCESS;
+}
+
 /* EOF */