- Add support for PnP IRP to PDO: IRP_MN_QUERY_BUS_INFORMATION (PciQueryBusInformatio...
[reactos.git] / reactos / drivers / bus / pcix / pdo.c
1 /*
2 * PROJECT: ReactOS PCI Bus Driver
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/bus/pci/pdo.c
5 * PURPOSE: PDO 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 LONG PciPdoSequenceNumber;
18
19 C_ASSERT(FIELD_OFFSET(PCI_FDO_EXTENSION, DeviceState) == FIELD_OFFSET(PCI_PDO_EXTENSION, DeviceState));
20 C_ASSERT(FIELD_OFFSET(PCI_FDO_EXTENSION, TentativeNextState) == FIELD_OFFSET(PCI_PDO_EXTENSION, TentativeNextState));
21 C_ASSERT(FIELD_OFFSET(PCI_FDO_EXTENSION, List) == FIELD_OFFSET(PCI_PDO_EXTENSION, Next));
22
23 PCI_MN_DISPATCH_TABLE PciPdoDispatchPowerTable[] =
24 {
25 {IRP_DISPATCH, (PCI_DISPATCH_FUNCTION)PciPdoWaitWake},
26 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
27 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoSetPowerState},
28 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryPower},
29 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported}
30 };
31
32 PCI_MN_DISPATCH_TABLE PciPdoDispatchPnpTable[] =
33 {
34 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpStartDevice},
35 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryRemoveDevice},
36 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpRemoveDevice},
37 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpCancelRemoveDevice},
38 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpStopDevice},
39 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryStopDevice},
40 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpCancelStopDevice},
41 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryDeviceRelations},
42 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryInterface},
43 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryCapabilities},
44 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryResources},
45 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryResourceRequirements},
46 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryDeviceText},
47 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
48 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
49 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpReadConfig},
50 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpWriteConfig},
51 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
52 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
53 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryId},
54 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryDeviceState},
55 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryBusInformation},
56 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpDeviceUsageNotification},
57 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpSurpriseRemoval},
58 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryLegacyBusInformation},
59 {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported}
60 };
61
62 PCI_MJ_DISPATCH_TABLE PciPdoDispatchTable =
63 {
64 IRP_MN_QUERY_LEGACY_BUS_INFORMATION,
65 PciPdoDispatchPnpTable,
66 IRP_MN_QUERY_POWER,
67 PciPdoDispatchPowerTable,
68 IRP_COMPLETE,
69 (PCI_DISPATCH_FUNCTION)PciIrpNotSupported,
70 IRP_COMPLETE,
71 (PCI_DISPATCH_FUNCTION)PciIrpInvalidDeviceRequest
72 };
73
74 /* FUNCTIONS ******************************************************************/
75
76 NTSTATUS
77 NTAPI
78 PciPdoWaitWake(IN PIRP Irp,
79 IN PIO_STACK_LOCATION IoStackLocation,
80 IN PPCI_PDO_EXTENSION DeviceExtension)
81 {
82 UNIMPLEMENTED;
83 while (TRUE);
84 return STATUS_NOT_SUPPORTED;
85 }
86
87 NTSTATUS
88 NTAPI
89 PciPdoSetPowerState(IN PIRP Irp,
90 IN PIO_STACK_LOCATION IoStackLocation,
91 IN PPCI_PDO_EXTENSION DeviceExtension)
92 {
93 UNIMPLEMENTED;
94 while (TRUE);
95 return STATUS_NOT_SUPPORTED;
96 }
97
98 NTSTATUS
99 NTAPI
100 PciPdoIrpQueryPower(IN PIRP Irp,
101 IN PIO_STACK_LOCATION IoStackLocation,
102 IN PPCI_PDO_EXTENSION DeviceExtension)
103 {
104 UNIMPLEMENTED;
105 while (TRUE);
106 return STATUS_NOT_SUPPORTED;
107 }
108
109 NTSTATUS
110 NTAPI
111 PciPdoIrpStartDevice(IN PIRP Irp,
112 IN PIO_STACK_LOCATION IoStackLocation,
113 IN PPCI_PDO_EXTENSION DeviceExtension)
114 {
115 UNIMPLEMENTED;
116 while (TRUE);
117 return STATUS_NOT_SUPPORTED;
118 }
119
120 NTSTATUS
121 NTAPI
122 PciPdoIrpQueryRemoveDevice(IN PIRP Irp,
123 IN PIO_STACK_LOCATION IoStackLocation,
124 IN PPCI_PDO_EXTENSION DeviceExtension)
125 {
126 UNIMPLEMENTED;
127 while (TRUE);
128 return STATUS_NOT_SUPPORTED;
129 }
130
131 NTSTATUS
132 NTAPI
133 PciPdoIrpRemoveDevice(IN PIRP Irp,
134 IN PIO_STACK_LOCATION IoStackLocation,
135 IN PPCI_PDO_EXTENSION DeviceExtension)
136 {
137 UNIMPLEMENTED;
138 while (TRUE);
139 return STATUS_NOT_SUPPORTED;
140 }
141
142 NTSTATUS
143 NTAPI
144 PciPdoIrpCancelRemoveDevice(IN PIRP Irp,
145 IN PIO_STACK_LOCATION IoStackLocation,
146 IN PPCI_PDO_EXTENSION DeviceExtension)
147 {
148 UNIMPLEMENTED;
149 while (TRUE);
150 return STATUS_NOT_SUPPORTED;
151 }
152
153 NTSTATUS
154 NTAPI
155 PciPdoIrpStopDevice(IN PIRP Irp,
156 IN PIO_STACK_LOCATION IoStackLocation,
157 IN PPCI_PDO_EXTENSION DeviceExtension)
158 {
159 UNIMPLEMENTED;
160 while (TRUE);
161 return STATUS_NOT_SUPPORTED;
162 }
163
164 NTSTATUS
165 NTAPI
166 PciPdoIrpQueryStopDevice(IN PIRP Irp,
167 IN PIO_STACK_LOCATION IoStackLocation,
168 IN PPCI_PDO_EXTENSION DeviceExtension)
169 {
170 UNIMPLEMENTED;
171 while (TRUE);
172 return STATUS_NOT_SUPPORTED;
173 }
174
175 NTSTATUS
176 NTAPI
177 PciPdoIrpCancelStopDevice(IN PIRP Irp,
178 IN PIO_STACK_LOCATION IoStackLocation,
179 IN PPCI_PDO_EXTENSION DeviceExtension)
180 {
181 UNIMPLEMENTED;
182 while (TRUE);
183 return STATUS_NOT_SUPPORTED;
184 }
185
186 NTSTATUS
187 NTAPI
188 PciPdoIrpQueryInterface(IN PIRP Irp,
189 IN PIO_STACK_LOCATION IoStackLocation,
190 IN PPCI_PDO_EXTENSION DeviceExtension)
191 {
192 UNIMPLEMENTED;
193 while (TRUE);
194 return STATUS_NOT_SUPPORTED;
195 }
196
197 NTSTATUS
198 NTAPI
199 PciPdoIrpQueryDeviceRelations(IN PIRP Irp,
200 IN PIO_STACK_LOCATION IoStackLocation,
201 IN PPCI_PDO_EXTENSION DeviceExtension)
202 {
203 NTSTATUS Status;
204 PAGED_CODE();
205
206 /* Are ejection relations being queried? */
207 if (IoStackLocation->Parameters.QueryDeviceRelations.Type == EjectionRelations)
208 {
209 /* Call the worker function */
210 Status = PciQueryEjectionRelations(DeviceExtension,
211 (PDEVICE_RELATIONS*)&Irp->
212 IoStatus.Information);
213 }
214 else if (IoStackLocation->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation)
215 {
216 /* The only other relation supported is the target device relation */
217 Status = PciQueryTargetDeviceRelations(DeviceExtension,
218 (PDEVICE_RELATIONS*)&Irp->
219 IoStatus.Information);
220 }
221 else
222 {
223 /* All other relations are unsupported */
224 Status = STATUS_NOT_SUPPORTED;
225 }
226
227 /* Return either the result of the worker function, or unsupported status */
228 return Status;
229 }
230
231 NTSTATUS
232 NTAPI
233 PciPdoIrpQueryCapabilities(IN PIRP Irp,
234 IN PIO_STACK_LOCATION IoStackLocation,
235 IN PPCI_PDO_EXTENSION DeviceExtension)
236 {
237 PAGED_CODE();
238
239 /* Call the worker function */
240 return PciQueryCapabilities(DeviceExtension,
241 IoStackLocation->
242 Parameters.DeviceCapabilities.Capabilities);
243 }
244
245 NTSTATUS
246 NTAPI
247 PciPdoIrpQueryResources(IN PIRP Irp,
248 IN PIO_STACK_LOCATION IoStackLocation,
249 IN PPCI_PDO_EXTENSION DeviceExtension)
250 {
251 PAGED_CODE();
252
253 /* Call the worker function */
254 return PciQueryResources(DeviceExtension,
255 (PCM_RESOURCE_LIST*)&Irp->IoStatus.Information);
256 }
257
258 NTSTATUS
259 NTAPI
260 PciPdoIrpQueryResourceRequirements(IN PIRP Irp,
261 IN PIO_STACK_LOCATION IoStackLocation,
262 IN PPCI_PDO_EXTENSION DeviceExtension)
263 {
264 PAGED_CODE();
265
266 /* Call the worker function */
267 return PciQueryRequirements(DeviceExtension,
268 (PIO_RESOURCE_REQUIREMENTS_LIST*)&Irp->
269 IoStatus.Information);
270 }
271
272 NTSTATUS
273 NTAPI
274 PciPdoIrpQueryDeviceText(IN PIRP Irp,
275 IN PIO_STACK_LOCATION IoStackLocation,
276 IN PPCI_PDO_EXTENSION DeviceExtension)
277 {
278 PAGED_CODE();
279
280 /* Call the worker function */
281 return PciQueryDeviceText(DeviceExtension,
282 IoStackLocation->
283 Parameters.QueryDeviceText.DeviceTextType,
284 IoStackLocation->
285 Parameters.QueryDeviceText.LocaleId,
286 (PWCHAR*)&Irp->IoStatus.Information);
287 }
288
289 NTSTATUS
290 NTAPI
291 PciPdoIrpQueryId(IN PIRP Irp,
292 IN PIO_STACK_LOCATION IoStackLocation,
293 IN PPCI_PDO_EXTENSION DeviceExtension)
294 {
295 PAGED_CODE();
296
297 /* Call the worker function */
298 return PciQueryId(DeviceExtension,
299 IoStackLocation->Parameters.QueryId.IdType,
300 (PWCHAR*)&Irp->IoStatus.Information);
301 }
302
303 NTSTATUS
304 NTAPI
305 PciPdoIrpQueryBusInformation(IN PIRP Irp,
306 IN PIO_STACK_LOCATION IoStackLocation,
307 IN PPCI_PDO_EXTENSION DeviceExtension)
308 {
309 PAGED_CODE();
310
311 /* Call the worker function */
312 return PciQueryBusInformation(DeviceExtension,
313 (PPNP_BUS_INFORMATION*)&Irp->
314 IoStatus.Information);
315 }
316
317 NTSTATUS
318 NTAPI
319 PciPdoIrpReadConfig(IN PIRP Irp,
320 IN PIO_STACK_LOCATION IoStackLocation,
321 IN PPCI_PDO_EXTENSION DeviceExtension)
322 {
323 UNIMPLEMENTED;
324 while (TRUE);
325 return STATUS_NOT_SUPPORTED;
326 }
327
328 NTSTATUS
329 NTAPI
330 PciPdoIrpWriteConfig(IN PIRP Irp,
331 IN PIO_STACK_LOCATION IoStackLocation,
332 IN PPCI_PDO_EXTENSION DeviceExtension)
333 {
334 UNIMPLEMENTED;
335 while (TRUE);
336 return STATUS_NOT_SUPPORTED;
337 }
338
339 NTSTATUS
340 NTAPI
341 PciPdoIrpQueryDeviceState(IN PIRP Irp,
342 IN PIO_STACK_LOCATION IoStackLocation,
343 IN PPCI_PDO_EXTENSION DeviceExtension)
344 {
345 UNIMPLEMENTED;
346 while (TRUE);
347 return STATUS_NOT_SUPPORTED;
348 }
349
350 NTSTATUS
351 NTAPI
352 PciPdoIrpDeviceUsageNotification(IN PIRP Irp,
353 IN PIO_STACK_LOCATION IoStackLocation,
354 IN PPCI_PDO_EXTENSION DeviceExtension)
355 {
356 UNIMPLEMENTED;
357 while (TRUE);
358 return STATUS_NOT_SUPPORTED;
359 }
360
361 NTSTATUS
362 NTAPI
363 PciPdoIrpSurpriseRemoval(IN PIRP Irp,
364 IN PIO_STACK_LOCATION IoStackLocation,
365 IN PPCI_PDO_EXTENSION DeviceExtension)
366 {
367 UNIMPLEMENTED;
368 while (TRUE);
369 return STATUS_NOT_SUPPORTED;
370 }
371
372 NTSTATUS
373 NTAPI
374 PciPdoIrpQueryLegacyBusInformation(IN PIRP Irp,
375 IN PIO_STACK_LOCATION IoStackLocation,
376 IN PPCI_PDO_EXTENSION DeviceExtension)
377 {
378 UNIMPLEMENTED;
379 while (TRUE);
380 return STATUS_NOT_SUPPORTED;
381 }
382
383 NTSTATUS
384 NTAPI
385 PciPdoCreate(IN PPCI_FDO_EXTENSION DeviceExtension,
386 IN PCI_SLOT_NUMBER Slot,
387 OUT PDEVICE_OBJECT *PdoDeviceObject)
388 {
389 WCHAR DeviceName[32];
390 UNICODE_STRING DeviceString;
391 NTSTATUS Status;
392 PDEVICE_OBJECT DeviceObject;
393 PPCI_PDO_EXTENSION PdoExtension;
394 ULONG SequenceNumber;
395 PAGED_CODE();
396
397 /* Pick an atomically unique sequence number for this device */
398 SequenceNumber = InterlockedIncrement(&PciPdoSequenceNumber);
399
400 /* Create the standard PCI device name for a PDO */
401 swprintf(DeviceName, L"\\Device\\NTPNP_PCI%04d", SequenceNumber);
402 RtlInitUnicodeString(&DeviceString, DeviceName);
403
404 /* Create the actual device now */
405 Status = IoCreateDevice(DeviceExtension->FunctionalDeviceObject->DriverObject,
406 sizeof(PCI_PDO_EXTENSION),
407 &DeviceString,
408 FILE_DEVICE_BUS_EXTENDER,
409 0,
410 0,
411 &DeviceObject);
412 ASSERT(NT_SUCCESS(Status));
413
414 /* Get the extension for it */
415 PdoExtension = (PPCI_PDO_EXTENSION)DeviceObject->DeviceExtension;
416 DPRINT1("PCI: New PDO (b=0x%x, d=0x%x, f=0x%x) @ %p, ext @ %p\n",
417 DeviceExtension->BaseBus,
418 Slot.u.bits.DeviceNumber,
419 Slot.u.bits.FunctionNumber,
420 DeviceObject,
421 DeviceObject->DeviceExtension);
422
423 /* Configure the extension */
424 PdoExtension->ExtensionType = PciPdoExtensionType;
425 PdoExtension->IrpDispatchTable = &PciPdoDispatchTable;
426 PdoExtension->PhysicalDeviceObject = DeviceObject;
427 PdoExtension->Slot = Slot;
428 PdoExtension->PowerState.CurrentSystemState = PowerDeviceD0;
429 PdoExtension->PowerState.CurrentDeviceState = PowerDeviceD0;
430 PdoExtension->ParentFdoExtension = DeviceExtension;
431
432 /* Initialize the lock for arbiters and other interfaces */
433 KeInitializeEvent(&PdoExtension->SecondaryExtLock, SynchronizationEvent, TRUE);
434
435 /* Initialize the state machine */
436 PciInitializeState((PPCI_FDO_EXTENSION)PdoExtension);
437
438 /* Add the PDO to the parent's list */
439 PdoExtension->Next = NULL;
440 PciInsertEntryAtTail((PSINGLE_LIST_ENTRY)&DeviceExtension->ChildPdoList,
441 (PPCI_FDO_EXTENSION)PdoExtension,
442 &DeviceExtension->ChildListLock);
443
444 /* And finally return it to the caller */
445 *PdoDeviceObject = DeviceObject;
446 return STATUS_SUCCESS;
447 }
448
449 /* EOF */