2 * PROJECT: ReactOS PCI Bus Driver
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/bus/pci/enum.c
5 * PURPOSE: PCI Bus/Device Enumeration
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
15 /* GLOBALS ********************************************************************/
17 /* FUNCTIONS ******************************************************************/
21 PciScanBus(IN PPCI_FDO_EXTENSION DeviceExtension
)
23 ULONG MaxDevice
= PCI_MAX_DEVICES
;
25 UCHAR Buffer
[PCI_COMMON_HDR_LENGTH
];
26 PPCI_COMMON_HEADER PciData
= (PVOID
)Buffer
;
27 PCI_SLOT_NUMBER PciSlot
;
28 PWCHAR DescriptionText
;
29 DPRINT1("PCI Scan Bus: FDO Extension @ 0x%x, Base Bus = 0x%x\n",
30 DeviceExtension
, DeviceExtension
->BaseBus
);
32 /* Is this the root FDO? */
33 if (!PCI_IS_ROOT_FDO(DeviceExtension
))
35 /* Other FDOs are not currently supported */
40 /* Loop every device on the bus */
41 PciSlot
.u
.bits
.Reserved
= 0;
42 i
= DeviceExtension
->BaseBus
;
43 for (j
= 0; j
< MaxDevice
; j
++)
45 /* Loop every function of each device */
46 PciSlot
.u
.bits
.DeviceNumber
= j
;
47 for (k
= 0; k
< PCI_MAX_FUNCTION
; k
++)
49 /* Build the final slot structure */
50 PciSlot
.u
.bits
.FunctionNumber
= k
;
52 /* Read the vendor for this slot */
53 PciReadSlotConfig(DeviceExtension
,
59 /* Skip invalid device */
60 if (PciData
->VendorID
== PCI_INVALID_VENDORID
) continue;
62 /* Now read the whole header */
63 PciReadSlotConfig(DeviceExtension
,
67 PCI_COMMON_HDR_LENGTH
- sizeof(USHORT
));
69 /* Dump device that was found */
70 DPRINT1("Scan Found Device 0x%x (b=0x%x, d=0x%x, f=0x%x)\n",
76 /* Dump the device's header */
77 PciDebugDumpCommonConfig(PciData
);
79 /* Find description for this device for the debugger's sake */
80 DescriptionText
= PciGetDeviceDescriptionMessage(PciData
->BaseClass
,
82 DPRINT1("Device Description \"%S\".\n", DescriptionText
? DescriptionText
: L
"(NULL)");
83 if (DescriptionText
) ExFreePoolWithTag(DescriptionText
, 0);
85 /* Check if there is an ACPI Watchdog Table */
88 /* Check if this PCI device is the ACPI Watchdog Device... */
95 /* Enumeration is completed */
96 return STATUS_SUCCESS
;
101 PciQueryDeviceRelations(IN PPCI_FDO_EXTENSION DeviceExtension
,
102 IN OUT PDEVICE_RELATIONS
*pDeviceRelations
)
105 PPCI_PDO_EXTENSION PdoExtension
;
107 PDEVICE_RELATIONS DeviceRelations
, NewRelations
;
109 PDEVICE_OBJECT DeviceObject
, *ObjectArray
;
112 /* Make sure the FDO is started */
113 ASSERT(DeviceExtension
->DeviceState
== PciStarted
);
115 /* Synchronize while we enumerate the bus */
116 Status
= PciBeginStateTransition(DeviceExtension
, PciSynchronizedOperation
);
117 if (!NT_SUCCESS(Status
)) return Status
;
119 /* Scan all children PDO */
120 for (PdoExtension
= DeviceExtension
->ChildPdoList
;
122 PdoExtension
= PdoExtension
->Next
)
124 /* Invalidate them */
125 PdoExtension
->NotPresent
= TRUE
;
128 /* Scan the PCI Bus */
129 Status
= PciScanBus(DeviceExtension
);
130 ASSERT(NT_SUCCESS(Status
));
132 /* Enumerate all children PDO again */
133 for (PdoExtension
= DeviceExtension
->ChildPdoList
;
135 PdoExtension
= PdoExtension
->Next
)
137 /* Check for PDOs that are still invalidated */
138 if (PdoExtension
->NotPresent
)
140 /* This means this PDO existed before, but not anymore */
141 PdoExtension
->ReportedMissing
= TRUE
;
142 DPRINT1("PCI - Old device (pdox) %08x not found on rescan.\n",
147 /* Increase count of detected PDOs */
152 /* Read the current relations and add the newly discovered relations */
153 DeviceRelations
= *pDeviceRelations
;
154 Size
= FIELD_OFFSET(DEVICE_RELATIONS
, Objects
) +
155 PdoCount
* sizeof(PDEVICE_OBJECT
);
156 if (DeviceRelations
) Size
+= sizeof(PDEVICE_OBJECT
) * DeviceRelations
->Count
;
158 /* Allocate the device relations */
159 NewRelations
= (PDEVICE_RELATIONS
)ExAllocatePoolWithTag(0, Size
, 'BicP');
162 /* Out of space, cancel the operation */
163 PciCancelStateTransition(DeviceExtension
, PciSynchronizedOperation
);
164 return STATUS_INSUFFICIENT_RESOURCES
;
167 /* Check if there were any older relations */
168 NewRelations
->Count
= 0;
171 /* Copy the old relations into the new buffer, then free the old one */
172 RtlCopyMemory(NewRelations
,
174 FIELD_OFFSET(DEVICE_RELATIONS
, Objects
) +
175 DeviceRelations
->Count
* sizeof(PDEVICE_OBJECT
));
176 ExFreePoolWithTag(DeviceRelations
, 0);
179 /* Print out that we're ready to dump relations */
180 DPRINT1("PCI QueryDeviceRelations/BusRelations FDOx %08x (bus 0x%02x)\n",
182 DeviceExtension
->BaseBus
);
184 /* Loop the current PDO children and the device relation object array */
185 PdoExtension
= DeviceExtension
->ChildPdoList
;
186 ObjectArray
= &NewRelations
->Objects
[NewRelations
->Count
];
189 /* Dump this relation */
190 DPRINT1(" QDR PDO %08x (x %08x)%s\n",
191 PdoExtension
->PhysicalDeviceObject
,
193 PdoExtension
->NotPresent
?
194 "<Omitted, device flaged not present>" : "");
196 /* Is this PDO present? */
197 if (!PdoExtension
->NotPresent
)
199 /* Reference it and add it to the array */
200 DeviceObject
= PdoExtension
->PhysicalDeviceObject
;
201 ObfReferenceObject(DeviceObject
);
202 *ObjectArray
++ = DeviceObject
;
205 /* Go to the next PDO */
206 PdoExtension
= PdoExtension
->Next
;
209 /* Terminate dumping the relations */
210 DPRINT1(" QDR Total PDO count = %d (%d already in list)\n",
211 NewRelations
->Count
+ PdoCount
,
212 NewRelations
->Count
);
214 /* Return the final count and the new buffer */
215 NewRelations
->Count
+= PdoCount
;
216 *pDeviceRelations
= NewRelations
;
217 return STATUS_SUCCESS
;