7 #include <acpi_drivers.h>
15 struct acpi_device
*Device
,
16 PFDO_DEVICE_DATA FdoData
20 #pragma alloc_text (PAGE, Bus_PnP)
21 #pragma alloc_text (PAGE, Bus_PlugInDevice)
22 #pragma alloc_text (PAGE, Bus_InitializePdo)
23 #pragma alloc_text (PAGE, Bus_DestroyPdo)
24 #pragma alloc_text (PAGE, Bus_FDO_PnP)
25 #pragma alloc_text (PAGE, Bus_StartFdo)
26 #pragma alloc_text (PAGE, Bus_SendIrpSynchronously)
33 PDEVICE_OBJECT DeviceObject
,
37 PIO_STACK_LOCATION irpStack
;
39 PCOMMON_DEVICE_DATA commonData
;
43 irpStack
= IoGetCurrentIrpStackLocation (Irp
);
44 ASSERT (IRP_MJ_PNP
== irpStack
->MajorFunction
);
46 commonData
= (PCOMMON_DEVICE_DATA
) DeviceObject
->DeviceExtension
;
49 if (commonData
->IsFDO
) {
50 DPRINT("FDO %s IRP:0x%p\n",
51 PnPMinorFunctionString(irpStack
->MinorFunction
),
54 // Request is for the bus FDO
56 status
= Bus_FDO_PnP (
60 (PFDO_DEVICE_DATA
) commonData
);
62 DPRINT("PDO %s IRP: 0x%p\n",
63 PnPMinorFunctionString(irpStack
->MinorFunction
),
66 // Request is for the child PDO.
68 status
= Bus_PDO_PnP (
72 (PPDO_DEVICE_DATA
) commonData
);
80 PDEVICE_OBJECT DeviceObject
,
82 PIO_STACK_LOCATION IrpStack
,
83 PFDO_DEVICE_DATA DeviceData
87 ULONG length
, prevcount
, numPdosPresent
;
89 PPDO_DEVICE_DATA pdoData
;
90 PDEVICE_RELATIONS relations
, oldRelations
;
94 switch (IrpStack
->MinorFunction
) {
96 case IRP_MN_START_DEVICE
:
98 status
= Bus_StartFdo (DeviceData
, Irp
);
102 // We must now complete the IRP, since we stopped it in the
103 // completion routine with MORE_PROCESSING_REQUIRED.
106 Irp
->IoStatus
.Status
= status
;
107 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
111 case IRP_MN_QUERY_STOP_DEVICE
:
114 // The PnP manager is trying to stop the device
115 // for resource rebalancing.
117 SET_NEW_PNP_STATE(DeviceData
->Common
, StopPending
);
118 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
121 case IRP_MN_CANCEL_STOP_DEVICE
:
124 // The PnP Manager sends this IRP, at some point after an
125 // IRP_MN_QUERY_STOP_DEVICE, to inform the drivers for a
126 // device that the device will not be stopped for
127 // resource reconfiguration.
130 // First check to see whether you have received cancel-stop
131 // without first receiving a query-stop. This could happen if
132 // someone above us fails a query-stop and passes down the subsequent
136 if (StopPending
== DeviceData
->Common
.DevicePnPState
)
139 // We did receive a query-stop, so restore.
141 RESTORE_PREVIOUS_PNP_STATE(DeviceData
->Common
);
142 ASSERT(DeviceData
->Common
.DevicePnPState
== Started
);
144 Irp
->IoStatus
.Status
= STATUS_SUCCESS
; // We must not fail the IRP.
147 case IRP_MN_QUERY_DEVICE_RELATIONS
:
149 DPRINT("\tQueryDeviceRelation Type: %s\n",
150 DbgDeviceRelationString(\
151 IrpStack
->Parameters
.QueryDeviceRelations
.Type
));
153 if (BusRelations
!= IrpStack
->Parameters
.QueryDeviceRelations
.Type
) {
155 // We don't support any other Device Relations
161 ExAcquireFastMutex (&DeviceData
->Mutex
);
163 oldRelations
= (PDEVICE_RELATIONS
) Irp
->IoStatus
.Information
;
165 prevcount
= oldRelations
->Count
;
166 if (!DeviceData
->NumPDOs
) {
168 // There is a device relations struct already present and we have
169 // nothing to add to it, so just call IoSkip and IoCall
171 ExReleaseFastMutex (&DeviceData
->Mutex
);
180 // Calculate the number of PDOs actually present on the bus
183 for (entry
= DeviceData
->ListOfPDOs
.Flink
;
184 entry
!= &DeviceData
->ListOfPDOs
;
185 entry
= entry
->Flink
) {
186 pdoData
= CONTAINING_RECORD (entry
, PDO_DEVICE_DATA
, Link
);
191 // Need to allocate a new relations structure and add our
195 length
= sizeof(DEVICE_RELATIONS
) +
196 (((numPdosPresent
+ prevcount
) - 1) * sizeof (PDEVICE_OBJECT
));
198 relations
= (PDEVICE_RELATIONS
) ExAllocatePoolWithTag (PagedPool
,
201 if (NULL
== relations
) {
205 ExReleaseFastMutex (&DeviceData
->Mutex
);
206 Irp
->IoStatus
.Status
= status
= STATUS_INSUFFICIENT_RESOURCES
;
207 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
213 // Copy in the device objects so far
216 RtlCopyMemory (relations
->Objects
, oldRelations
->Objects
,
217 prevcount
* sizeof (PDEVICE_OBJECT
));
220 relations
->Count
= prevcount
+ numPdosPresent
;
223 // For each PDO present on this bus add a pointer to the device relations
224 // buffer, being sure to take out a reference to that object.
225 // The Plug & Play system will dereference the object when it is done
226 // with it and free the device relations buffer.
229 for (entry
= DeviceData
->ListOfPDOs
.Flink
;
230 entry
!= &DeviceData
->ListOfPDOs
;
231 entry
= entry
->Flink
) {
233 pdoData
= CONTAINING_RECORD (entry
, PDO_DEVICE_DATA
, Link
);
234 relations
->Objects
[prevcount
] = pdoData
->Common
.Self
;
235 ObReferenceObject (pdoData
->Common
.Self
);
239 DPRINT("\t#PDOs present = %d\n\t#PDOs reported = %d\n",
240 DeviceData
->NumPDOs
, relations
->Count
);
243 // Replace the relations structure in the IRP with the new
247 ExFreePool (oldRelations
);
249 Irp
->IoStatus
.Information
= (ULONG_PTR
) relations
;
251 ExReleaseFastMutex (&DeviceData
->Mutex
);
254 // Set up and pass the IRP further down the stack
256 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
262 // In the default case we merely call the next driver.
263 // We must not modify Irp->IoStatus.Status or complete the IRP.
269 IoSkipCurrentIrpStackLocation (Irp
);
270 status
= IoCallDriver (DeviceData
->NextLowerDriver
, Irp
);
271 return STATUS_SUCCESS
;
276 PFDO_DEVICE_DATA FdoData
,
279 NTSTATUS status
= STATUS_SUCCESS
;
280 POWER_STATE powerState
;
281 ACPI_STATUS AcpiStatus
;
285 FdoData
->Common
.DevicePowerState
= PowerDeviceD0
;
286 powerState
.DeviceState
= PowerDeviceD0
;
287 PoSetPowerState ( FdoData
->Common
.Self
, DevicePowerState
, powerState
);
289 SET_NEW_PNP_STATE(FdoData
->Common
, Started
);
291 AcpiStatus
= AcpiInitializeSubsystem();
292 if(ACPI_FAILURE(AcpiStatus
)){
293 DPRINT1("Unable to AcpiInitializeSubsystem\n");
294 return STATUS_UNSUCCESSFUL
;
298 AcpiStatus
= AcpiInitializeTables(NULL
, 16, 0);
299 if (ACPI_FAILURE(status
)){
300 DPRINT1("Unable to AcpiInitializeSubsystem\n");
301 return STATUS_UNSUCCESSFUL
;
304 AcpiStatus
= AcpiLoadTables();
305 if(ACPI_FAILURE(AcpiStatus
)){
306 DPRINT1("Unable to AcpiLoadTables\n");
308 return STATUS_UNSUCCESSFUL
;
311 DPRINT("Acpi subsystem init\n");
312 /* Initialize ACPI bus manager */
313 AcpiStatus
= acpi_init();
314 if (!ACPI_SUCCESS(AcpiStatus
)) {
315 DPRINT1("acpi_init() failed with status 0x%X\n", AcpiStatus
);
317 return STATUS_UNSUCCESSFUL
;
319 status
= ACPIEnumerateDevices(FdoData
);
325 Bus_SendIrpSynchronously (
326 PDEVICE_OBJECT DeviceObject
,
335 KeInitializeEvent(&event
, NotificationEvent
, FALSE
);
337 IoCopyCurrentIrpStackLocationToNext(Irp
);
339 IoSetCompletionRoutine(Irp
,
340 Bus_CompletionRoutine
,
347 status
= IoCallDriver(DeviceObject
, Irp
);
350 // Wait for lower drivers to be done with the Irp.
351 // Important thing to note here is when you allocate
352 // the memory for an event in the stack you must do a
353 // KernelMode wait instead of UserMode to prevent
354 // the stack from getting paged out.
357 if (status
== STATUS_PENDING
) {
358 KeWaitForSingleObject(&event
,
364 status
= Irp
->IoStatus
.Status
;
372 Bus_CompletionRoutine(
373 PDEVICE_OBJECT DeviceObject
,
378 UNREFERENCED_PARAMETER (DeviceObject
);
381 // If the lower driver didn't return STATUS_PENDING, we don't need to
382 // set the event because we won't be waiting on it.
383 // This optimization avoids grabbing the dispatcher lock and improves perf.
385 if (Irp
->PendingReturned
== TRUE
) {
387 KeSetEvent ((PKEVENT
) Context
, IO_NO_INCREMENT
, FALSE
);
389 return STATUS_MORE_PROCESSING_REQUIRED
; // Keep this IRP
394 PDEVICE_OBJECT Device
,
395 PPDO_DEVICE_DATA PdoData
401 // BusEnum does not queue any irps at this time so we have nothing to do.
405 // Free any resources.
408 if (PdoData
->HardwareIDs
) {
409 ExFreePoolWithTag (PdoData
->HardwareIDs
, 'IPCA');
410 PdoData
->HardwareIDs
= NULL
;
413 DPRINT("\tDeleting PDO: 0x%p\n", Device
);
414 IoDeleteDevice (Device
);
415 return STATUS_SUCCESS
;
422 PFDO_DEVICE_DATA FdoData
425 PPDO_DEVICE_DATA pdoData
;
427 DEVICE_POWER_STATE ntState
;
431 pdoData
= (PPDO_DEVICE_DATA
) Pdo
->DeviceExtension
;
433 DPRINT("pdo 0x%p, extension 0x%p\n", Pdo
, pdoData
);
435 if (pdoData
->AcpiHandle
)
436 acpi_bus_get_power(pdoData
->AcpiHandle
, &acpistate
);
438 acpistate
= ACPI_STATE_D0
;
443 ntState
= PowerDeviceD0
;
446 ntState
= PowerDeviceD1
;
449 ntState
= PowerDeviceD2
;
452 ntState
= PowerDeviceD3
;
455 DPRINT1("Unknown power state (%d) returned by acpi\n",acpistate
);
456 ntState
= PowerDeviceUnspecified
;
461 // Initialize the rest
463 pdoData
->Common
.IsFDO
= FALSE
;
464 pdoData
->Common
.Self
= Pdo
;
466 pdoData
->ParentFdo
= FdoData
->Common
.Self
;
469 INITIALIZE_PNP_STATE(pdoData
->Common
);
471 pdoData
->Common
.DevicePowerState
= ntState
;
472 pdoData
->Common
.SystemPowerState
= FdoData
->Common
.SystemPowerState
;
474 Pdo
->Flags
|= DO_POWER_PAGABLE
;
476 ExAcquireFastMutex (&FdoData
->Mutex
);
477 InsertTailList(&FdoData
->ListOfPDOs
, &pdoData
->Link
);
479 ExReleaseFastMutex (&FdoData
->Mutex
);
481 // This should be the last step in initialization.
482 Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
489 PnPMinorFunctionString (
493 switch (MinorFunction
)
495 case IRP_MN_START_DEVICE
:
496 return "IRP_MN_START_DEVICE";
497 case IRP_MN_QUERY_REMOVE_DEVICE
:
498 return "IRP_MN_QUERY_REMOVE_DEVICE";
499 case IRP_MN_REMOVE_DEVICE
:
500 return "IRP_MN_REMOVE_DEVICE";
501 case IRP_MN_CANCEL_REMOVE_DEVICE
:
502 return "IRP_MN_CANCEL_REMOVE_DEVICE";
503 case IRP_MN_STOP_DEVICE
:
504 return "IRP_MN_STOP_DEVICE";
505 case IRP_MN_QUERY_STOP_DEVICE
:
506 return "IRP_MN_QUERY_STOP_DEVICE";
507 case IRP_MN_CANCEL_STOP_DEVICE
:
508 return "IRP_MN_CANCEL_STOP_DEVICE";
509 case IRP_MN_QUERY_DEVICE_RELATIONS
:
510 return "IRP_MN_QUERY_DEVICE_RELATIONS";
511 case IRP_MN_QUERY_INTERFACE
:
512 return "IRP_MN_QUERY_INTERFACE";
513 case IRP_MN_QUERY_CAPABILITIES
:
514 return "IRP_MN_QUERY_CAPABILITIES";
515 case IRP_MN_QUERY_RESOURCES
:
516 return "IRP_MN_QUERY_RESOURCES";
517 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
518 return "IRP_MN_QUERY_RESOURCE_REQUIREMENTS";
519 case IRP_MN_QUERY_DEVICE_TEXT
:
520 return "IRP_MN_QUERY_DEVICE_TEXT";
521 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
:
522 return "IRP_MN_FILTER_RESOURCE_REQUIREMENTS";
523 case IRP_MN_READ_CONFIG
:
524 return "IRP_MN_READ_CONFIG";
525 case IRP_MN_WRITE_CONFIG
:
526 return "IRP_MN_WRITE_CONFIG";
528 return "IRP_MN_EJECT";
529 case IRP_MN_SET_LOCK
:
530 return "IRP_MN_SET_LOCK";
531 case IRP_MN_QUERY_ID
:
532 return "IRP_MN_QUERY_ID";
533 case IRP_MN_QUERY_PNP_DEVICE_STATE
:
534 return "IRP_MN_QUERY_PNP_DEVICE_STATE";
535 case IRP_MN_QUERY_BUS_INFORMATION
:
536 return "IRP_MN_QUERY_BUS_INFORMATION";
537 case IRP_MN_DEVICE_USAGE_NOTIFICATION
:
538 return "IRP_MN_DEVICE_USAGE_NOTIFICATION";
539 case IRP_MN_SURPRISE_REMOVAL
:
540 return "IRP_MN_SURPRISE_REMOVAL";
541 case IRP_MN_QUERY_LEGACY_BUS_INFORMATION
:
542 return "IRP_MN_QUERY_LEGACY_BUS_INFORMATION";
544 return "unknown_pnp_irp";
549 DbgDeviceRelationString(
550 DEVICE_RELATION_TYPE Type
556 return "BusRelations";
557 case EjectionRelations
:
558 return "EjectionRelations";
559 case RemovalRelations
:
560 return "RemovalRelations";
561 case TargetDeviceRelation
:
562 return "TargetDeviceRelation";
564 return "UnKnown Relation";
570 BUS_QUERY_ID_TYPE Type
575 case BusQueryDeviceID
:
576 return "BusQueryDeviceID";
577 case BusQueryHardwareIDs
:
578 return "BusQueryHardwareIDs";
579 case BusQueryCompatibleIDs
:
580 return "BusQueryCompatibleIDs";
581 case BusQueryInstanceID
:
582 return "BusQueryInstanceID";
583 case BusQueryDeviceSerialNumber
:
584 return "BusQueryDeviceSerialNumber";