7 #include <acpi_drivers.h>
14 #pragma alloc_text (PAGE, Bus_PnP)
15 #pragma alloc_text (PAGE, Bus_PlugInDevice)
16 #pragma alloc_text (PAGE, Bus_InitializePdo)
17 #pragma alloc_text (PAGE, Bus_UnPlugDevice)
18 #pragma alloc_text (PAGE, Bus_DestroyPdo)
19 #pragma alloc_text (PAGE, Bus_FDO_PnP)
20 #pragma alloc_text (PAGE, Bus_StartFdo)
21 #pragma alloc_text (PAGE, Bus_SendIrpSynchronously)
28 PDEVICE_OBJECT DeviceObject
,
32 PIO_STACK_LOCATION irpStack
;
34 PCOMMON_DEVICE_DATA commonData
;
38 irpStack
= IoGetCurrentIrpStackLocation (Irp
);
39 ASSERT (IRP_MJ_PNP
== irpStack
->MajorFunction
);
41 commonData
= (PCOMMON_DEVICE_DATA
) DeviceObject
->DeviceExtension
;
44 if (commonData
->IsFDO
) {
45 DPRINT("FDO %s IRP:0x%p\n",
46 PnPMinorFunctionString(irpStack
->MinorFunction
),
49 // Request is for the bus FDO
51 status
= Bus_FDO_PnP (
55 (PFDO_DEVICE_DATA
) commonData
);
57 DPRINT("PDO %s IRP: 0x%p\n",
58 PnPMinorFunctionString(irpStack
->MinorFunction
),
61 // Request is for the child PDO.
63 status
= Bus_PDO_PnP (
67 (PPDO_DEVICE_DATA
) commonData
);
75 PDEVICE_OBJECT DeviceObject
,
77 PIO_STACK_LOCATION IrpStack
,
78 PFDO_DEVICE_DATA DeviceData
82 ULONG length
, prevcount
, numPdosPresent
;
84 PPDO_DEVICE_DATA pdoData
;
85 PDEVICE_RELATIONS relations
, oldRelations
;
89 switch (IrpStack
->MinorFunction
) {
91 case IRP_MN_START_DEVICE
:
93 status
= Bus_StartFdo (DeviceData
, Irp
);
97 // We must now complete the IRP, since we stopped it in the
98 // completion routine with MORE_PROCESSING_REQUIRED.
101 Irp
->IoStatus
.Status
= status
;
102 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
106 case IRP_MN_QUERY_STOP_DEVICE
:
109 // The PnP manager is trying to stop the device
110 // for resource rebalancing.
112 SET_NEW_PNP_STATE(DeviceData
->Common
, StopPending
);
113 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
116 case IRP_MN_CANCEL_STOP_DEVICE
:
119 // The PnP Manager sends this IRP, at some point after an
120 // IRP_MN_QUERY_STOP_DEVICE, to inform the drivers for a
121 // device that the device will not be stopped for
122 // resource reconfiguration.
125 // First check to see whether you have received cancel-stop
126 // without first receiving a query-stop. This could happen if
127 // someone above us fails a query-stop and passes down the subsequent
131 if (StopPending
== DeviceData
->Common
.DevicePnPState
)
134 // We did receive a query-stop, so restore.
136 RESTORE_PREVIOUS_PNP_STATE(DeviceData
->Common
);
137 ASSERT(DeviceData
->Common
.DevicePnPState
== Started
);
139 Irp
->IoStatus
.Status
= STATUS_SUCCESS
; // We must not fail the IRP.
142 case IRP_MN_QUERY_DEVICE_RELATIONS
:
144 DPRINT("\tQueryDeviceRelation Type: %s\n",
145 DbgDeviceRelationString(\
146 IrpStack
->Parameters
.QueryDeviceRelations
.Type
));
148 if (BusRelations
!= IrpStack
->Parameters
.QueryDeviceRelations
.Type
) {
150 // We don't support any other Device Relations
156 ExAcquireFastMutex (&DeviceData
->Mutex
);
158 oldRelations
= (PDEVICE_RELATIONS
) Irp
->IoStatus
.Information
;
160 prevcount
= oldRelations
->Count
;
161 if (!DeviceData
->NumPDOs
) {
163 // There is a device relations struct already present and we have
164 // nothing to add to it, so just call IoSkip and IoCall
166 ExReleaseFastMutex (&DeviceData
->Mutex
);
175 // Calculate the number of PDOs actually present on the bus
178 for (entry
= DeviceData
->ListOfPDOs
.Flink
;
179 entry
!= &DeviceData
->ListOfPDOs
;
180 entry
= entry
->Flink
) {
181 pdoData
= CONTAINING_RECORD (entry
, PDO_DEVICE_DATA
, Link
);
186 // Need to allocate a new relations structure and add our
190 length
= sizeof(DEVICE_RELATIONS
) +
191 ((numPdosPresent
+ prevcount
) * sizeof (PDEVICE_OBJECT
)) -1;
193 relations
= (PDEVICE_RELATIONS
) ExAllocatePoolWithTag (PagedPool
,
196 if (NULL
== relations
) {
200 ExReleaseFastMutex (&DeviceData
->Mutex
);
201 Irp
->IoStatus
.Status
= status
= STATUS_INSUFFICIENT_RESOURCES
;
202 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
208 // Copy in the device objects so far
211 RtlCopyMemory (relations
->Objects
, oldRelations
->Objects
,
212 prevcount
* sizeof (PDEVICE_OBJECT
));
215 relations
->Count
= prevcount
+ numPdosPresent
;
218 // For each PDO present on this bus add a pointer to the device relations
219 // buffer, being sure to take out a reference to that object.
220 // The Plug & Play system will dereference the object when it is done
221 // with it and free the device relations buffer.
224 for (entry
= DeviceData
->ListOfPDOs
.Flink
;
225 entry
!= &DeviceData
->ListOfPDOs
;
226 entry
= entry
->Flink
) {
228 pdoData
= CONTAINING_RECORD (entry
, PDO_DEVICE_DATA
, Link
);
229 relations
->Objects
[prevcount
] = pdoData
->Common
.Self
;
230 ObReferenceObject (pdoData
->Common
.Self
);
234 DPRINT("\t#PDOs present = %d\n\t#PDOs reported = %d\n",
235 DeviceData
->NumPDOs
, relations
->Count
);
238 // Replace the relations structure in the IRP with the new
242 ExFreePool (oldRelations
);
244 Irp
->IoStatus
.Information
= (ULONG_PTR
) relations
;
246 ExReleaseFastMutex (&DeviceData
->Mutex
);
249 // Set up and pass the IRP further down the stack
251 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
257 // In the default case we merely call the next driver.
258 // We must not modify Irp->IoStatus.Status or complete the IRP.
264 IoSkipCurrentIrpStackLocation (Irp
);
265 status
= IoCallDriver (DeviceData
->NextLowerDriver
, Irp
);
266 return STATUS_SUCCESS
;
271 PFDO_DEVICE_DATA FdoData
,
274 NTSTATUS status
= STATUS_SUCCESS
;
275 POWER_STATE powerState
;
276 ACPI_STATUS AcpiStatus
;
280 FdoData
->Common
.DevicePowerState
= PowerDeviceD0
;
281 powerState
.DeviceState
= PowerDeviceD0
;
282 PoSetPowerState ( FdoData
->Common
.Self
, DevicePowerState
, powerState
);
284 SET_NEW_PNP_STATE(FdoData
->Common
, Started
);
286 AcpiStatus
= AcpiInitializeSubsystem();
287 if(ACPI_FAILURE(AcpiStatus
)){
288 DPRINT1("Unable to AcpiInitializeSubsystem\n");
289 return STATUS_UNSUCCESSFUL
;
293 AcpiStatus
= AcpiInitializeTables(NULL
, 16, 0);
294 if (ACPI_FAILURE(status
)){
295 DPRINT1("Unable to AcpiInitializeSubsystem\n");
296 return STATUS_UNSUCCESSFUL
;
299 AcpiStatus
= AcpiLoadTables();
300 if(ACPI_FAILURE(AcpiStatus
)){
301 DPRINT1("Unable to AcpiLoadTables\n");
303 return STATUS_UNSUCCESSFUL
;
306 DPRINT("Acpi subsystem init\n");
307 /* Initialize ACPI bus manager */
308 AcpiStatus
= acpi_init();
309 if (!ACPI_SUCCESS(AcpiStatus
)) {
310 DPRINT("acpi_init() failed with status 0x%X\n", AcpiStatus
);
312 return STATUS_UNSUCCESSFUL
;
314 status
= ACPIEnumerateDevices(FdoData
);
320 Bus_SendIrpSynchronously (
321 PDEVICE_OBJECT DeviceObject
,
330 KeInitializeEvent(&event
, NotificationEvent
, FALSE
);
332 IoCopyCurrentIrpStackLocationToNext(Irp
);
334 IoSetCompletionRoutine(Irp
,
335 Bus_CompletionRoutine
,
342 status
= IoCallDriver(DeviceObject
, Irp
);
345 // Wait for lower drivers to be done with the Irp.
346 // Important thing to note here is when you allocate
347 // the memory for an event in the stack you must do a
348 // KernelMode wait instead of UserMode to prevent
349 // the stack from getting paged out.
352 if (status
== STATUS_PENDING
) {
353 KeWaitForSingleObject(&event
,
359 status
= Irp
->IoStatus
.Status
;
366 Bus_CompletionRoutine(
367 PDEVICE_OBJECT DeviceObject
,
372 UNREFERENCED_PARAMETER (DeviceObject
);
375 // If the lower driver didn't return STATUS_PENDING, we don't need to
376 // set the event because we won't be waiting on it.
377 // This optimization avoids grabbing the dispatcher lock and improves perf.
379 if (Irp
->PendingReturned
== TRUE
) {
381 KeSetEvent ((PKEVENT
) Context
, IO_NO_INCREMENT
, FALSE
);
383 return STATUS_MORE_PROCESSING_REQUIRED
; // Keep this IRP
388 PDEVICE_OBJECT Device
,
389 PPDO_DEVICE_DATA PdoData
395 // BusEnum does not queue any irps at this time so we have nothing to do.
399 // Free any resources.
402 if (PdoData
->HardwareIDs
) {
403 ExFreePool (PdoData
->HardwareIDs
);
404 PdoData
->HardwareIDs
= NULL
;
407 DPRINT("\tDeleting PDO: 0x%p\n", Device
);
408 IoDeleteDevice (Device
);
409 return STATUS_SUCCESS
;
416 PFDO_DEVICE_DATA FdoData
419 PPDO_DEVICE_DATA pdoData
;
423 pdoData
= (PPDO_DEVICE_DATA
) Pdo
->DeviceExtension
;
425 DPRINT("pdo 0x%p, extension 0x%p\n", Pdo
, pdoData
);
428 // Initialize the rest
430 pdoData
->Common
.IsFDO
= FALSE
;
431 pdoData
->Common
.Self
= Pdo
;
433 pdoData
->ParentFdo
= FdoData
->Common
.Self
;
436 INITIALIZE_PNP_STATE(pdoData
->Common
);
439 // PDO's usually start their life at D3
442 pdoData
->Common
.DevicePowerState
= PowerDeviceD3
;
443 pdoData
->Common
.SystemPowerState
= PowerSystemWorking
;
445 Pdo
->Flags
|= DO_POWER_PAGABLE
;
447 ExAcquireFastMutex (&FdoData
->Mutex
);
448 InsertTailList(&FdoData
->ListOfPDOs
, &pdoData
->Link
);
450 ExReleaseFastMutex (&FdoData
->Mutex
);
452 // This should be the last step in initialization.
453 Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
460 PnPMinorFunctionString (
464 switch (MinorFunction
)
466 case IRP_MN_START_DEVICE
:
467 return "IRP_MN_START_DEVICE";
468 case IRP_MN_QUERY_REMOVE_DEVICE
:
469 return "IRP_MN_QUERY_REMOVE_DEVICE";
470 case IRP_MN_REMOVE_DEVICE
:
471 return "IRP_MN_REMOVE_DEVICE";
472 case IRP_MN_CANCEL_REMOVE_DEVICE
:
473 return "IRP_MN_CANCEL_REMOVE_DEVICE";
474 case IRP_MN_STOP_DEVICE
:
475 return "IRP_MN_STOP_DEVICE";
476 case IRP_MN_QUERY_STOP_DEVICE
:
477 return "IRP_MN_QUERY_STOP_DEVICE";
478 case IRP_MN_CANCEL_STOP_DEVICE
:
479 return "IRP_MN_CANCEL_STOP_DEVICE";
480 case IRP_MN_QUERY_DEVICE_RELATIONS
:
481 return "IRP_MN_QUERY_DEVICE_RELATIONS";
482 case IRP_MN_QUERY_INTERFACE
:
483 return "IRP_MN_QUERY_INTERFACE";
484 case IRP_MN_QUERY_CAPABILITIES
:
485 return "IRP_MN_QUERY_CAPABILITIES";
486 case IRP_MN_QUERY_RESOURCES
:
487 return "IRP_MN_QUERY_RESOURCES";
488 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
489 return "IRP_MN_QUERY_RESOURCE_REQUIREMENTS";
490 case IRP_MN_QUERY_DEVICE_TEXT
:
491 return "IRP_MN_QUERY_DEVICE_TEXT";
492 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
:
493 return "IRP_MN_FILTER_RESOURCE_REQUIREMENTS";
494 case IRP_MN_READ_CONFIG
:
495 return "IRP_MN_READ_CONFIG";
496 case IRP_MN_WRITE_CONFIG
:
497 return "IRP_MN_WRITE_CONFIG";
499 return "IRP_MN_EJECT";
500 case IRP_MN_SET_LOCK
:
501 return "IRP_MN_SET_LOCK";
502 case IRP_MN_QUERY_ID
:
503 return "IRP_MN_QUERY_ID";
504 case IRP_MN_QUERY_PNP_DEVICE_STATE
:
505 return "IRP_MN_QUERY_PNP_DEVICE_STATE";
506 case IRP_MN_QUERY_BUS_INFORMATION
:
507 return "IRP_MN_QUERY_BUS_INFORMATION";
508 case IRP_MN_DEVICE_USAGE_NOTIFICATION
:
509 return "IRP_MN_DEVICE_USAGE_NOTIFICATION";
510 case IRP_MN_SURPRISE_REMOVAL
:
511 return "IRP_MN_SURPRISE_REMOVAL";
512 case IRP_MN_QUERY_LEGACY_BUS_INFORMATION
:
513 return "IRP_MN_QUERY_LEGACY_BUS_INFORMATION";
515 return "unknown_pnp_irp";
520 DbgDeviceRelationString(
521 DEVICE_RELATION_TYPE Type
527 return "BusRelations";
528 case EjectionRelations
:
529 return "EjectionRelations";
530 case RemovalRelations
:
531 return "RemovalRelations";
532 case TargetDeviceRelation
:
533 return "TargetDeviceRelation";
535 return "UnKnown Relation";
541 BUS_QUERY_ID_TYPE Type
546 case BusQueryDeviceID
:
547 return "BusQueryDeviceID";
548 case BusQueryHardwareIDs
:
549 return "BusQueryHardwareIDs";
550 case BusQueryCompatibleIDs
:
551 return "BusQueryCompatibleIDs";
552 case BusQueryInstanceID
:
553 return "BusQueryInstanceID";
554 case BusQueryDeviceSerialNumber
:
555 return "BusQueryDeviceSerialNumber";