[WINSOCK]
[reactos.git] / reactos / drivers / bus / pcix / fdo.c
1 /*
2 * PROJECT: ReactOS PCI Bus Driver
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/bus/pci/fdo.c
5 * PURPOSE: FDO Device Management
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 SINGLE_LIST_ENTRY PciFdoExtensionListHead;
18 BOOLEAN PciBreakOnDefault;
19
20 PCI_MN_DISPATCH_TABLE PciFdoDispatchPowerTable[] =
21 {
22 {IRP_DISPATCH, PciFdoWaitWake},
23 {IRP_DOWNWARD, PciIrpNotSupported},
24 {IRP_DOWNWARD, PciFdoSetPowerState},
25 {IRP_DOWNWARD, PciFdoIrpQueryPower},
26 {IRP_DOWNWARD, PciIrpNotSupported}
27 };
28
29 PCI_MN_DISPATCH_TABLE PciFdoDispatchPnpTable[] =
30 {
31 {IRP_UPWARD, PciFdoIrpStartDevice},
32 {IRP_DOWNWARD, PciFdoIrpQueryRemoveDevice},
33 {IRP_DISPATCH, PciFdoIrpRemoveDevice},
34 {IRP_DOWNWARD, PciFdoIrpCancelRemoveDevice},
35 {IRP_DOWNWARD, PciFdoIrpStopDevice},
36 {IRP_DOWNWARD, PciFdoIrpQueryStopDevice},
37 {IRP_DOWNWARD, PciFdoIrpCancelStopDevice},
38 {IRP_DOWNWARD, PciFdoIrpQueryDeviceRelations},
39 {IRP_DISPATCH, PciFdoIrpQueryInterface},
40 {IRP_UPWARD, PciFdoIrpQueryCapabilities},
41 {IRP_DOWNWARD, PciIrpNotSupported},
42 {IRP_DOWNWARD, PciIrpNotSupported},
43 {IRP_DOWNWARD, PciIrpNotSupported},
44 {IRP_DOWNWARD, PciIrpNotSupported},
45 {IRP_DOWNWARD, PciIrpNotSupported},
46 {IRP_DOWNWARD, PciIrpNotSupported},
47 {IRP_DOWNWARD, PciIrpNotSupported},
48 {IRP_DOWNWARD, PciIrpNotSupported},
49 {IRP_DOWNWARD, PciIrpNotSupported},
50 {IRP_DOWNWARD, PciIrpNotSupported},
51 {IRP_DOWNWARD, PciIrpNotSupported},
52 {IRP_DOWNWARD, PciIrpNotSupported},
53 {IRP_UPWARD, PciFdoIrpDeviceUsageNotification},
54 {IRP_DOWNWARD, PciFdoIrpSurpriseRemoval},
55 {IRP_DOWNWARD, PciFdoIrpQueryLegacyBusInformation},
56 {IRP_DOWNWARD, PciIrpNotSupported}
57 };
58
59 PCI_MJ_DISPATCH_TABLE PciFdoDispatchTable =
60 {
61 IRP_MN_QUERY_LEGACY_BUS_INFORMATION,
62 PciFdoDispatchPnpTable,
63 IRP_MN_QUERY_POWER,
64 PciFdoDispatchPowerTable,
65 IRP_DOWNWARD,
66 PciIrpNotSupported,
67 IRP_DOWNWARD,
68 PciIrpNotSupported
69 };
70
71 /* FUNCTIONS ******************************************************************/
72
73 NTSTATUS
74 NTAPI
75 PciFdoIrpStartDevice(IN PIRP Irp,
76 IN PIO_STACK_LOCATION IoStackLocation,
77 IN PPCI_FDO_EXTENSION DeviceExtension)
78 {
79 UNIMPLEMENTED;
80 while (TRUE);
81 return STATUS_NOT_SUPPORTED;
82 }
83
84 NTSTATUS
85 NTAPI
86 PciFdoIrpQueryRemoveDevice(IN PIRP Irp,
87 IN PIO_STACK_LOCATION IoStackLocation,
88 IN PPCI_FDO_EXTENSION DeviceExtension)
89 {
90 UNIMPLEMENTED;
91 while (TRUE);
92 return STATUS_NOT_SUPPORTED;
93 }
94
95 NTSTATUS
96 NTAPI
97 PciFdoIrpRemoveDevice(IN PIRP Irp,
98 IN PIO_STACK_LOCATION IoStackLocation,
99 IN PPCI_FDO_EXTENSION DeviceExtension)
100 {
101 UNIMPLEMENTED;
102 while (TRUE);
103 return STATUS_NOT_SUPPORTED;
104 }
105
106 NTSTATUS
107 NTAPI
108 PciFdoIrpCancelRemoveDevice(IN PIRP Irp,
109 IN PIO_STACK_LOCATION IoStackLocation,
110 IN PPCI_FDO_EXTENSION DeviceExtension)
111 {
112 UNIMPLEMENTED;
113 while (TRUE);
114 return STATUS_NOT_SUPPORTED;
115 }
116
117 NTSTATUS
118 NTAPI
119 PciFdoIrpStopDevice(IN PIRP Irp,
120 IN PIO_STACK_LOCATION IoStackLocation,
121 IN PPCI_FDO_EXTENSION DeviceExtension)
122 {
123 UNIMPLEMENTED;
124 while (TRUE);
125 return STATUS_NOT_SUPPORTED;
126 }
127
128 NTSTATUS
129 NTAPI
130 PciFdoIrpQueryStopDevice(IN PIRP Irp,
131 IN PIO_STACK_LOCATION IoStackLocation,
132 IN PPCI_FDO_EXTENSION DeviceExtension)
133 {
134 UNIMPLEMENTED;
135 while (TRUE);
136 return STATUS_NOT_SUPPORTED;
137 }
138
139 NTSTATUS
140 NTAPI
141 PciFdoIrpCancelStopDevice(IN PIRP Irp,
142 IN PIO_STACK_LOCATION IoStackLocation,
143 IN PPCI_FDO_EXTENSION DeviceExtension)
144 {
145 UNIMPLEMENTED;
146 while (TRUE);
147 return STATUS_NOT_SUPPORTED;
148 }
149
150 NTSTATUS
151 NTAPI
152 PciFdoIrpQueryDeviceRelations(IN PIRP Irp,
153 IN PIO_STACK_LOCATION IoStackLocation,
154 IN PPCI_FDO_EXTENSION DeviceExtension)
155 {
156 UNIMPLEMENTED;
157 while (TRUE);
158 return STATUS_NOT_SUPPORTED;
159 }
160
161 NTSTATUS
162 NTAPI
163 PciFdoIrpQueryInterface(IN PIRP Irp,
164 IN PIO_STACK_LOCATION IoStackLocation,
165 IN PPCI_FDO_EXTENSION DeviceExtension)
166 {
167 UNIMPLEMENTED;
168 while (TRUE);
169 return STATUS_NOT_SUPPORTED;
170 }
171
172 NTSTATUS
173 NTAPI
174 PciFdoIrpQueryCapabilities(IN PIRP Irp,
175 IN PIO_STACK_LOCATION IoStackLocation,
176 IN PPCI_FDO_EXTENSION DeviceExtension)
177 {
178 UNIMPLEMENTED;
179 while (TRUE);
180 return STATUS_NOT_SUPPORTED;
181 }
182
183 NTSTATUS
184 NTAPI
185 PciFdoIrpDeviceUsageNotification(IN PIRP Irp,
186 IN PIO_STACK_LOCATION IoStackLocation,
187 IN PPCI_FDO_EXTENSION DeviceExtension)
188 {
189 UNIMPLEMENTED;
190 while (TRUE);
191 return STATUS_NOT_SUPPORTED;
192 }
193
194 NTSTATUS
195 NTAPI
196 PciFdoIrpSurpriseRemoval(IN PIRP Irp,
197 IN PIO_STACK_LOCATION IoStackLocation,
198 IN PPCI_FDO_EXTENSION DeviceExtension)
199 {
200 UNIMPLEMENTED;
201 while (TRUE);
202 return STATUS_NOT_SUPPORTED;
203 }
204
205 NTSTATUS
206 NTAPI
207 PciFdoIrpQueryLegacyBusInformation(IN PIRP Irp,
208 IN PIO_STACK_LOCATION IoStackLocation,
209 IN PPCI_FDO_EXTENSION DeviceExtension)
210 {
211 UNIMPLEMENTED;
212 while (TRUE);
213 return STATUS_NOT_SUPPORTED;
214 }
215
216 VOID
217 NTAPI
218 PciGetHotPlugParameters(IN PPCI_FDO_EXTENSION FdoExtension)
219 {
220 ACPI_EVAL_INPUT_BUFFER InputBuffer;
221 PACPI_EVAL_OUTPUT_BUFFER OutputBuffer;
222 ULONG Length;
223 NTSTATUS Status;
224 PAGED_CODE();
225
226 /* We should receive 4 parameters, per the HPP specification */
227 Length = sizeof(ACPI_EVAL_OUTPUT_BUFFER) + 4 * sizeof(ACPI_METHOD_ARGUMENT);
228
229 /* Allocate the buffer to hold the parameters */
230 OutputBuffer = ExAllocatePoolWithTag(PagedPool, Length, PCI_POOL_TAG);
231 if (!OutputBuffer) return;
232
233 /* Initialize the output and input buffers. The method is _HPP */
234 RtlZeroMemory(OutputBuffer, Length);
235 *(PULONG)InputBuffer.MethodName = 'PPH_';
236 InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
237 do
238 {
239 /* Send the IOCTL to the ACPI driver */
240 Status = PciSendIoctl(FdoExtension->PhysicalDeviceObject,
241 IOCTL_ACPI_EVAL_METHOD,
242 &InputBuffer,
243 sizeof(InputBuffer),
244 OutputBuffer,
245 Length);
246 if (!NT_SUCCESS(Status))
247 {
248 /* The method failed, check if we can salvage data from parent */
249 if (!PCI_IS_ROOT_FDO(FdoExtension))
250 {
251 /* Copy the root bus' hot plug parameters */
252 FdoExtension->HotPlugParameters = FdoExtension->ParentFdoExtension->HotPlugParameters;
253 }
254
255 /* Nothing more to do on this path */
256 break;
257 }
258
259 /* ACPI sent back some data. 4 parameters are expected in the output */
260 if (OutputBuffer->Count != 4) break;
261
262 /* HotPlug PCI Support not yet implemented */
263 UNIMPLEMENTED;
264 while (TRUE);
265 } while (FALSE);
266
267 /* Free the buffer and return */
268 ExFreePoolWithTag(OutputBuffer, 0);
269 }
270
271 VOID
272 NTAPI
273 PciInitializeFdoExtensionCommonFields(PPCI_FDO_EXTENSION FdoExtension,
274 IN PDEVICE_OBJECT DeviceObject,
275 IN PDEVICE_OBJECT PhysicalDeviceObject)
276 {
277 /* Initialize the extension */
278 RtlZeroMemory(FdoExtension, sizeof(PCI_FDO_EXTENSION));
279
280 /* Setup the common fields */
281 FdoExtension->PhysicalDeviceObject = PhysicalDeviceObject;
282 FdoExtension->FunctionalDeviceObject = DeviceObject;
283 FdoExtension->ExtensionType = PciFdoExtensionType;
284 FdoExtension->PowerState.CurrentSystemState = PowerSystemWorking;
285 FdoExtension->PowerState.CurrentDeviceState = PowerDeviceD0;
286 FdoExtension->IrpDispatchTable = &PciFdoDispatchTable;
287
288 /* Initialize the extension locks */
289 KeInitializeEvent(&FdoExtension->SecondaryExtLock, SynchronizationEvent, TRUE);
290 KeInitializeEvent(&FdoExtension->ChildListLock, SynchronizationEvent, TRUE);
291
292 /* Initialize the default state */
293 PciInitializeState(FdoExtension);
294 }
295
296 NTSTATUS
297 NTAPI
298 PciAddDevice(IN PDRIVER_OBJECT DriverObject,
299 IN PDEVICE_OBJECT PhysicalDeviceObject)
300 {
301 PCM_RESOURCE_LIST Descriptor;
302 PDEVICE_OBJECT AttachedTo;
303 PPCI_FDO_EXTENSION FdoExtension;
304 PPCI_FDO_EXTENSION ParentExtension;
305 PDEVICE_OBJECT DeviceObject;
306 UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
307 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)Buffer;
308 NTSTATUS Status;
309 HANDLE KeyHandle;
310 UNICODE_STRING ValueName;
311 ULONG ResultLength;
312 PAGED_CODE();
313 DPRINT1("PCI - AddDevice (a new bus). PDO: %p (Driver: %wZ)\n",
314 PhysicalDeviceObject, &PhysicalDeviceObject->DriverObject->DriverName);
315
316 /* Zero out variables so failure path knows what to do */
317 AttachedTo = NULL;
318 do
319 {
320 /* Check if there's already a device extension for this bus */
321 ParentExtension = PciFindParentPciFdoExtension(PhysicalDeviceObject,
322 &PciGlobalLock);
323 if (ParentExtension)
324 {
325 /* More than one PCI bus, this is not expected yet */
326 UNIMPLEMENTED;
327 while (TRUE);
328 }
329
330 /* Create the FDO for the bus */
331 Status = IoCreateDevice(DriverObject,
332 sizeof(PCI_FDO_EXTENSION),
333 NULL,
334 FILE_DEVICE_BUS_EXTENDER,
335 0,
336 0,
337 &DeviceObject);
338 if (!NT_SUCCESS(Status)) break;
339
340 /* Initialize the extension for the FDO */
341 FdoExtension = DeviceObject->DeviceExtension;
342 PciInitializeFdoExtensionCommonFields(DeviceObject->DeviceExtension,
343 DeviceObject,
344 PhysicalDeviceObject);
345
346 /* Attach to the root PDO */
347 Status = STATUS_NO_SUCH_DEVICE;
348 AttachedTo = IoAttachDeviceToDeviceStack(DeviceObject,
349 PhysicalDeviceObject);
350 ASSERT(AttachedTo != NULL);
351 if (!AttachedTo) break;
352 FdoExtension->AttachedDeviceObject = AttachedTo;
353 if (ParentExtension)
354 {
355 /* More than one PCI bus, this is not expected yet */
356 UNIMPLEMENTED;
357 while (TRUE);
358 }
359 else
360 {
361 /* Query the boot configuration */
362 Status = PciGetDeviceProperty(PhysicalDeviceObject,
363 DevicePropertyBootConfiguration,
364 (PVOID*)&Descriptor);
365 if (!NT_SUCCESS(Status))
366 {
367 /* No configuration has been set */
368 Descriptor = NULL;
369 }
370 else
371 {
372 /* Root PDO in ReactOS does not assign boot resources */
373 UNIMPLEMENTED;
374 while (TRUE);
375 }
376
377 if (Descriptor)
378 {
379 /* Root PDO in ReactOS does not assign boot resources */
380 UNIMPLEMENTED;
381 while (TRUE);
382 }
383 else
384 {
385 /* Default configuration isn't the normal path on Windows */
386 if (PciBreakOnDefault)
387 {
388 /* If a second bus is found and there's still no data, crash */
389 KeBugCheckEx(PCI_BUS_DRIVER_INTERNAL,
390 0xDEAD0010u,
391 (ULONG_PTR)DeviceObject,
392 0,
393 0);
394 }
395
396 /* Warn that a default configuration will be used, and set bus 0 */
397 DPRINT1("PCI Will use default configuration.\n");
398 PciBreakOnDefault = TRUE;
399 FdoExtension->BaseBus = 0;
400 }
401
402 /* This is the root bus */
403 FdoExtension->BusRootFdoExtension = FdoExtension;
404 }
405
406 /* Get the HAL or ACPI Bus Handler Callbacks for Configuration Access */
407 Status = PciGetConfigHandlers(FdoExtension);
408 if (!NT_SUCCESS(Status)) break;
409
410 /* Initialize all the supported PCI arbiters */
411 Status = PciInitializeArbiters(FdoExtension);
412 if (!NT_SUCCESS(Status)) break;
413
414 /* This is a real FDO, insert it into the list */
415 FdoExtension->Fake = FALSE;
416 PciInsertEntryAtTail(&PciFdoExtensionListHead,
417 FdoExtension,
418 &PciGlobalLock);
419
420 /* Open the device registry key so that we can query the errata flags */
421 IoOpenDeviceRegistryKey(DeviceObject,
422 PLUGPLAY_REGKEY_DEVICE,
423 KEY_ALL_ACCESS,
424 &KeyHandle),
425
426 /* Open the value that contains errata flags for this bus instance */
427 RtlInitUnicodeString(&ValueName, L"HackFlags");
428 Status = ZwQueryValueKey(KeyHandle,
429 &ValueName,
430 KeyValuePartialInformation,
431 ValueInfo,
432 sizeof(Buffer),
433 &ResultLength);
434 ZwClose(KeyHandle);
435 if (NT_SUCCESS(Status))
436 {
437 /* Make sure the data is of expected type and size */
438 if ((ValueInfo->Type == REG_DWORD) &&
439 (ValueInfo->DataLength == sizeof(ULONG)))
440 {
441 /* Read the flags for this bus */
442 FdoExtension->BusHackFlags = *(PULONG)&ValueInfo->Data;
443 }
444 }
445
446 /* Query ACPI for PCI HotPlug Support */
447 PciGetHotPlugParameters(FdoExtension);
448
449 /* The Bus FDO is now initialized */
450 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
451 DPRINT1("PCI Root FDO Added: %p %p\n", DeviceObject, FdoExtension);
452 return STATUS_SUCCESS;
453 } while (FALSE);
454
455 /* This is the failure path */
456 ASSERT(!NT_SUCCESS(Status));
457 if (AttachedTo) IoDetachDevice(AttachedTo);
458 if (DeviceObject) IoDeleteDevice(DeviceObject);
459 return Status;
460 }
461
462 /* EOF */