89cb5f8bfd25a54e74b542123e584db05354d05d
[reactos.git] / reactos / drivers / bus / pcix / enum.c
1 /*
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
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <pci.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* GLOBALS ********************************************************************/
16
17 /* FUNCTIONS ******************************************************************/
18
19 NTSTATUS
20 NTAPI
21 PciScanBus(IN PPCI_FDO_EXTENSION DeviceExtension)
22 {
23 ULONG MaxDevice = PCI_MAX_DEVICES;
24 ULONG i, j, k;
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);
31
32 /* Is this the root FDO? */
33 if (!PCI_IS_ROOT_FDO(DeviceExtension))
34 {
35 /* Other FDOs are not currently supported */
36 UNIMPLEMENTED;
37 while (TRUE);
38 }
39
40 /* Loop every device on the bus */
41 PciSlot.u.bits.Reserved = 0;
42 i = DeviceExtension->BaseBus;
43 for (j = 0; j < MaxDevice; j++)
44 {
45 /* Loop every function of each device */
46 PciSlot.u.bits.DeviceNumber = j;
47 for (k = 0; k < PCI_MAX_FUNCTION; k++)
48 {
49 /* Build the final slot structure */
50 PciSlot.u.bits.FunctionNumber = k;
51
52 /* Read the vendor for this slot */
53 PciReadSlotConfig(DeviceExtension,
54 PciSlot,
55 PciData,
56 0,
57 sizeof(USHORT));
58
59 /* Skip invalid device */
60 if (PciData->VendorID == PCI_INVALID_VENDORID) continue;
61
62 /* Now read the whole header */
63 PciReadSlotConfig(DeviceExtension,
64 PciSlot,
65 &PciData->DeviceID,
66 sizeof(USHORT),
67 PCI_COMMON_HDR_LENGTH - sizeof(USHORT));
68
69 /* Dump device that was found */
70 DPRINT1("Scan Found Device 0x%x (b=0x%x, d=0x%x, f=0x%x)\n",
71 PciSlot.u.AsULONG,
72 i,
73 j,
74 k);
75
76 /* Dump the device's header */
77 PciDebugDumpCommonConfig(PciData);
78
79 /* Find description for this device for the debugger's sake */
80 DescriptionText = PciGetDeviceDescriptionMessage(PciData->BaseClass,
81 PciData->SubClass);
82 DPRINT1("Device Description \"%S\".\n", DescriptionText ? DescriptionText : L"(NULL)");
83 if (DescriptionText) ExFreePoolWithTag(DescriptionText, 0);
84
85 /* Check if there is an ACPI Watchdog Table */
86 if (WdTable)
87 {
88 /* Check if this PCI device is the ACPI Watchdog Device... */
89 UNIMPLEMENTED;
90 while (TRUE);
91 }
92 }
93 }
94
95 /* Enumeration is completed */
96 return STATUS_SUCCESS;
97 }
98
99 NTSTATUS
100 NTAPI
101 PciQueryDeviceRelations(IN PPCI_FDO_EXTENSION DeviceExtension,
102 IN OUT PDEVICE_RELATIONS *pDeviceRelations)
103 {
104 NTSTATUS Status;
105 PPCI_PDO_EXTENSION PdoExtension;
106 ULONG PdoCount = 0;
107 PDEVICE_RELATIONS DeviceRelations, NewRelations;
108 SIZE_T Size;
109 PDEVICE_OBJECT DeviceObject, *ObjectArray;
110 PAGED_CODE();
111
112 /* Make sure the FDO is started */
113 ASSERT(DeviceExtension->DeviceState == PciStarted);
114
115 /* Synchronize while we enumerate the bus */
116 Status = PciBeginStateTransition(DeviceExtension, PciSynchronizedOperation);
117 if (!NT_SUCCESS(Status)) return Status;
118
119 /* Scan all children PDO */
120 for (PdoExtension = DeviceExtension->ChildPdoList;
121 PdoExtension;
122 PdoExtension = PdoExtension->Next)
123 {
124 /* Invalidate them */
125 PdoExtension->NotPresent = TRUE;
126 }
127
128 /* Scan the PCI Bus */
129 Status = PciScanBus(DeviceExtension);
130 ASSERT(NT_SUCCESS(Status));
131
132 /* Enumerate all children PDO again */
133 for (PdoExtension = DeviceExtension->ChildPdoList;
134 PdoExtension;
135 PdoExtension = PdoExtension->Next)
136 {
137 /* Check for PDOs that are still invalidated */
138 if (PdoExtension->NotPresent)
139 {
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",
143 PdoExtension);
144 }
145 else
146 {
147 /* Increase count of detected PDOs */
148 PdoCount++;
149 }
150 }
151
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;
157
158 /* Allocate the device relations */
159 NewRelations = (PDEVICE_RELATIONS)ExAllocatePoolWithTag(0, Size, 'BicP');
160 if (!NewRelations)
161 {
162 /* Out of space, cancel the operation */
163 PciCancelStateTransition(DeviceExtension, PciSynchronizedOperation);
164 return STATUS_INSUFFICIENT_RESOURCES;
165 }
166
167 /* Check if there were any older relations */
168 NewRelations->Count = 0;
169 if (DeviceRelations)
170 {
171 /* Copy the old relations into the new buffer, then free the old one */
172 RtlCopyMemory(NewRelations,
173 DeviceRelations,
174 FIELD_OFFSET(DEVICE_RELATIONS, Objects) +
175 DeviceRelations->Count * sizeof(PDEVICE_OBJECT));
176 ExFreePoolWithTag(DeviceRelations, 0);
177 }
178
179 /* Print out that we're ready to dump relations */
180 DPRINT1("PCI QueryDeviceRelations/BusRelations FDOx %08x (bus 0x%02x)\n",
181 DeviceExtension,
182 DeviceExtension->BaseBus);
183
184 /* Loop the current PDO children and the device relation object array */
185 PdoExtension = DeviceExtension->ChildPdoList;
186 ObjectArray = &NewRelations->Objects[NewRelations->Count];
187 while (PdoExtension)
188 {
189 /* Dump this relation */
190 DPRINT1(" QDR PDO %08x (x %08x)%s\n",
191 PdoExtension->PhysicalDeviceObject,
192 PdoExtension,
193 PdoExtension->NotPresent ?
194 "<Omitted, device flaged not present>" : "");
195
196 /* Is this PDO present? */
197 if (!PdoExtension->NotPresent)
198 {
199 /* Reference it and add it to the array */
200 DeviceObject = PdoExtension->PhysicalDeviceObject;
201 ObfReferenceObject(DeviceObject);
202 *ObjectArray++ = DeviceObject;
203 }
204
205 /* Go to the next PDO */
206 PdoExtension = PdoExtension->Next;
207 }
208
209 /* Terminate dumping the relations */
210 DPRINT1(" QDR Total PDO count = %d (%d already in list)\n",
211 NewRelations->Count + PdoCount,
212 NewRelations->Count);
213
214 /* Return the final count and the new buffer */
215 NewRelations->Count += PdoCount;
216 *pDeviceRelations = NewRelations;
217 return STATUS_SUCCESS;
218 }
219
220 /* EOF */