Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpnp.c
Go to the documentation of this file.
00001 #include <ntddk.h> 00002 00003 #include <acpi.h> 00004 00005 #include <acpisys.h> 00006 #include <acpi_bus.h> 00007 #include <acpi_drivers.h> 00008 00009 #include <wdmguid.h> 00010 #define NDEBUG 00011 #include <debug.h> 00012 00013 NTSTATUS 00014 Bus_PlugInDevice ( 00015 struct acpi_device *Device, 00016 PFDO_DEVICE_DATA FdoData 00017 ); 00018 00019 #ifdef ALLOC_PRAGMA 00020 #pragma alloc_text (PAGE, Bus_PnP) 00021 #pragma alloc_text (PAGE, Bus_PlugInDevice) 00022 #pragma alloc_text (PAGE, Bus_InitializePdo) 00023 #pragma alloc_text (PAGE, Bus_DestroyPdo) 00024 #pragma alloc_text (PAGE, Bus_FDO_PnP) 00025 #pragma alloc_text (PAGE, Bus_StartFdo) 00026 #pragma alloc_text (PAGE, Bus_SendIrpSynchronously) 00027 #endif 00028 00029 00030 NTSTATUS 00031 NTAPI 00032 Bus_PnP ( 00033 PDEVICE_OBJECT DeviceObject, 00034 PIRP Irp 00035 ) 00036 { 00037 PIO_STACK_LOCATION irpStack; 00038 NTSTATUS status; 00039 PCOMMON_DEVICE_DATA commonData; 00040 00041 PAGED_CODE (); 00042 00043 irpStack = IoGetCurrentIrpStackLocation (Irp); 00044 ASSERT (IRP_MJ_PNP == irpStack->MajorFunction); 00045 00046 commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension; 00047 00048 00049 if (commonData->IsFDO) { 00050 DPRINT("FDO %s IRP:0x%p\n", 00051 PnPMinorFunctionString(irpStack->MinorFunction), 00052 Irp); 00053 // 00054 // Request is for the bus FDO 00055 // 00056 status = Bus_FDO_PnP ( 00057 DeviceObject, 00058 Irp, 00059 irpStack, 00060 (PFDO_DEVICE_DATA) commonData); 00061 } else { 00062 DPRINT("PDO %s IRP: 0x%p\n", 00063 PnPMinorFunctionString(irpStack->MinorFunction), 00064 Irp); 00065 // 00066 // Request is for the child PDO. 00067 // 00068 status = Bus_PDO_PnP ( 00069 DeviceObject, 00070 Irp, 00071 irpStack, 00072 (PPDO_DEVICE_DATA) commonData); 00073 } 00074 00075 return status; 00076 } 00077 00078 NTSTATUS 00079 Bus_FDO_PnP ( 00080 PDEVICE_OBJECT DeviceObject, 00081 PIRP Irp, 00082 PIO_STACK_LOCATION IrpStack, 00083 PFDO_DEVICE_DATA DeviceData 00084 ) 00085 { 00086 NTSTATUS status; 00087 ULONG length, prevcount, numPdosPresent; 00088 PLIST_ENTRY entry; 00089 PPDO_DEVICE_DATA pdoData; 00090 PDEVICE_RELATIONS relations, oldRelations; 00091 00092 PAGED_CODE (); 00093 00094 switch (IrpStack->MinorFunction) { 00095 00096 case IRP_MN_START_DEVICE: 00097 00098 status = Bus_StartFdo (DeviceData, Irp); 00099 00100 00101 // 00102 // We must now complete the IRP, since we stopped it in the 00103 // completion routine with MORE_PROCESSING_REQUIRED. 00104 // 00105 00106 Irp->IoStatus.Status = status; 00107 IoCompleteRequest (Irp, IO_NO_INCREMENT); 00108 00109 return status; 00110 00111 case IRP_MN_QUERY_STOP_DEVICE: 00112 00113 // 00114 // The PnP manager is trying to stop the device 00115 // for resource rebalancing. 00116 // 00117 SET_NEW_PNP_STATE(DeviceData->Common, StopPending); 00118 Irp->IoStatus.Status = STATUS_SUCCESS; 00119 break; 00120 00121 case IRP_MN_CANCEL_STOP_DEVICE: 00122 00123 // 00124 // The PnP Manager sends this IRP, at some point after an 00125 // IRP_MN_QUERY_STOP_DEVICE, to inform the drivers for a 00126 // device that the device will not be stopped for 00127 // resource reconfiguration. 00128 // 00129 // 00130 // First check to see whether you have received cancel-stop 00131 // without first receiving a query-stop. This could happen if 00132 // someone above us fails a query-stop and passes down the subsequent 00133 // cancel-stop. 00134 // 00135 00136 if (StopPending == DeviceData->Common.DevicePnPState) 00137 { 00138 // 00139 // We did receive a query-stop, so restore. 00140 // 00141 RESTORE_PREVIOUS_PNP_STATE(DeviceData->Common); 00142 ASSERT(DeviceData->Common.DevicePnPState == Started); 00143 } 00144 Irp->IoStatus.Status = STATUS_SUCCESS; // We must not fail the IRP. 00145 break; 00146 00147 case IRP_MN_QUERY_DEVICE_RELATIONS: 00148 00149 DPRINT("\tQueryDeviceRelation Type: %s\n", 00150 DbgDeviceRelationString(\ 00151 IrpStack->Parameters.QueryDeviceRelations.Type)); 00152 00153 if (BusRelations != IrpStack->Parameters.QueryDeviceRelations.Type) { 00154 // 00155 // We don't support any other Device Relations 00156 // 00157 break; 00158 } 00159 00160 00161 ExAcquireFastMutex (&DeviceData->Mutex); 00162 00163 oldRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information; 00164 if (oldRelations) { 00165 prevcount = oldRelations->Count; 00166 if (!DeviceData->NumPDOs) { 00167 // 00168 // There is a device relations struct already present and we have 00169 // nothing to add to it, so just call IoSkip and IoCall 00170 // 00171 ExReleaseFastMutex (&DeviceData->Mutex); 00172 break; 00173 } 00174 } 00175 else { 00176 prevcount = 0; 00177 } 00178 00179 // 00180 // Calculate the number of PDOs actually present on the bus 00181 // 00182 numPdosPresent = 0; 00183 for (entry = DeviceData->ListOfPDOs.Flink; 00184 entry != &DeviceData->ListOfPDOs; 00185 entry = entry->Flink) { 00186 pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link); 00187 numPdosPresent++; 00188 } 00189 00190 // 00191 // Need to allocate a new relations structure and add our 00192 // PDOs to it. 00193 // 00194 00195 length = sizeof(DEVICE_RELATIONS) + 00196 (((numPdosPresent + prevcount) - 1) * sizeof (PDEVICE_OBJECT)); 00197 00198 relations = (PDEVICE_RELATIONS) ExAllocatePoolWithTag (PagedPool, 00199 length, 'IPCA'); 00200 00201 if (NULL == relations) { 00202 // 00203 // Fail the IRP 00204 // 00205 ExReleaseFastMutex (&DeviceData->Mutex); 00206 Irp->IoStatus.Status = status = STATUS_INSUFFICIENT_RESOURCES; 00207 IoCompleteRequest (Irp, IO_NO_INCREMENT); 00208 return status; 00209 00210 } 00211 00212 // 00213 // Copy in the device objects so far 00214 // 00215 if (prevcount) { 00216 RtlCopyMemory (relations->Objects, oldRelations->Objects, 00217 prevcount * sizeof (PDEVICE_OBJECT)); 00218 } 00219 00220 relations->Count = prevcount + numPdosPresent; 00221 00222 // 00223 // For each PDO present on this bus add a pointer to the device relations 00224 // buffer, being sure to take out a reference to that object. 00225 // The Plug & Play system will dereference the object when it is done 00226 // with it and free the device relations buffer. 00227 // 00228 00229 for (entry = DeviceData->ListOfPDOs.Flink; 00230 entry != &DeviceData->ListOfPDOs; 00231 entry = entry->Flink) { 00232 00233 pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link); 00234 relations->Objects[prevcount] = pdoData->Common.Self; 00235 ObReferenceObject (pdoData->Common.Self); 00236 prevcount++; 00237 } 00238 00239 DPRINT("\t#PDOs present = %d\n\t#PDOs reported = %d\n", 00240 DeviceData->NumPDOs, relations->Count); 00241 00242 // 00243 // Replace the relations structure in the IRP with the new 00244 // one. 00245 // 00246 if (oldRelations) { 00247 ExFreePool (oldRelations); 00248 } 00249 Irp->IoStatus.Information = (ULONG_PTR) relations; 00250 00251 ExReleaseFastMutex (&DeviceData->Mutex); 00252 00253 // 00254 // Set up and pass the IRP further down the stack 00255 // 00256 Irp->IoStatus.Status = STATUS_SUCCESS; 00257 break; 00258 00259 default: 00260 00261 // 00262 // In the default case we merely call the next driver. 00263 // We must not modify Irp->IoStatus.Status or complete the IRP. 00264 // 00265 00266 break; 00267 } 00268 00269 IoSkipCurrentIrpStackLocation (Irp); 00270 status = IoCallDriver (DeviceData->NextLowerDriver, Irp); 00271 return STATUS_SUCCESS; 00272 } 00273 00274 NTSTATUS 00275 Bus_StartFdo ( 00276 PFDO_DEVICE_DATA FdoData, 00277 PIRP Irp ) 00278 { 00279 NTSTATUS status = STATUS_SUCCESS; 00280 POWER_STATE powerState; 00281 ACPI_STATUS AcpiStatus; 00282 00283 PAGED_CODE (); 00284 00285 FdoData->Common.DevicePowerState = PowerDeviceD0; 00286 powerState.DeviceState = PowerDeviceD0; 00287 PoSetPowerState ( FdoData->Common.Self, DevicePowerState, powerState ); 00288 00289 SET_NEW_PNP_STATE(FdoData->Common, Started); 00290 00291 AcpiStatus = AcpiInitializeSubsystem(); 00292 if(ACPI_FAILURE(AcpiStatus)){ 00293 DPRINT1("Unable to AcpiInitializeSubsystem\n"); 00294 return STATUS_UNSUCCESSFUL; 00295 } 00296 00297 00298 AcpiStatus = AcpiInitializeTables(NULL, 16, 0); 00299 if (ACPI_FAILURE(status)){ 00300 DPRINT1("Unable to AcpiInitializeSubsystem\n"); 00301 return STATUS_UNSUCCESSFUL; 00302 } 00303 00304 AcpiStatus = AcpiLoadTables(); 00305 if(ACPI_FAILURE(AcpiStatus)){ 00306 DPRINT1("Unable to AcpiLoadTables\n"); 00307 AcpiTerminate(); 00308 return STATUS_UNSUCCESSFUL; 00309 } 00310 00311 DPRINT("Acpi subsystem init\n"); 00312 /* Initialize ACPI bus manager */ 00313 AcpiStatus = acpi_init(); 00314 if (!ACPI_SUCCESS(AcpiStatus)) { 00315 DPRINT1("acpi_init() failed with status 0x%X\n", AcpiStatus); 00316 AcpiTerminate(); 00317 return STATUS_UNSUCCESSFUL; 00318 } 00319 status = ACPIEnumerateDevices(FdoData); 00320 00321 return status; 00322 } 00323 00324 NTSTATUS 00325 Bus_SendIrpSynchronously ( 00326 PDEVICE_OBJECT DeviceObject, 00327 PIRP Irp 00328 ) 00329 { 00330 KEVENT event; 00331 NTSTATUS status; 00332 00333 PAGED_CODE(); 00334 00335 KeInitializeEvent(&event, NotificationEvent, FALSE); 00336 00337 IoCopyCurrentIrpStackLocationToNext(Irp); 00338 00339 IoSetCompletionRoutine(Irp, 00340 Bus_CompletionRoutine, 00341 &event, 00342 TRUE, 00343 TRUE, 00344 TRUE 00345 ); 00346 00347 status = IoCallDriver(DeviceObject, Irp); 00348 00349 // 00350 // Wait for lower drivers to be done with the Irp. 00351 // Important thing to note here is when you allocate 00352 // the memory for an event in the stack you must do a 00353 // KernelMode wait instead of UserMode to prevent 00354 // the stack from getting paged out. 00355 // 00356 00357 if (status == STATUS_PENDING) { 00358 KeWaitForSingleObject(&event, 00359 Executive, 00360 KernelMode, 00361 FALSE, 00362 NULL 00363 ); 00364 status = Irp->IoStatus.Status; 00365 } 00366 00367 return status; 00368 } 00369 00370 NTSTATUS 00371 NTAPI 00372 Bus_CompletionRoutine( 00373 PDEVICE_OBJECT DeviceObject, 00374 PIRP Irp, 00375 PVOID Context 00376 ) 00377 { 00378 UNREFERENCED_PARAMETER (DeviceObject); 00379 00380 // 00381 // If the lower driver didn't return STATUS_PENDING, we don't need to 00382 // set the event because we won't be waiting on it. 00383 // This optimization avoids grabbing the dispatcher lock and improves perf. 00384 // 00385 if (Irp->PendingReturned == TRUE) { 00386 00387 KeSetEvent ((PKEVENT) Context, IO_NO_INCREMENT, FALSE); 00388 } 00389 return STATUS_MORE_PROCESSING_REQUIRED; // Keep this IRP 00390 } 00391 00392 NTSTATUS 00393 Bus_DestroyPdo ( 00394 PDEVICE_OBJECT Device, 00395 PPDO_DEVICE_DATA PdoData 00396 ) 00397 { 00398 PAGED_CODE (); 00399 00400 // 00401 // BusEnum does not queue any irps at this time so we have nothing to do. 00402 // 00403 00404 // 00405 // Free any resources. 00406 // 00407 00408 if (PdoData->HardwareIDs) { 00409 ExFreePoolWithTag (PdoData->HardwareIDs, 'IPCA'); 00410 PdoData->HardwareIDs = NULL; 00411 } 00412 00413 DPRINT("\tDeleting PDO: 0x%p\n", Device); 00414 IoDeleteDevice (Device); 00415 return STATUS_SUCCESS; 00416 } 00417 00418 00419 VOID 00420 Bus_InitializePdo ( 00421 PDEVICE_OBJECT Pdo, 00422 PFDO_DEVICE_DATA FdoData 00423 ) 00424 { 00425 PPDO_DEVICE_DATA pdoData; 00426 int acpistate; 00427 DEVICE_POWER_STATE ntState; 00428 00429 PAGED_CODE (); 00430 00431 pdoData = (PPDO_DEVICE_DATA) Pdo->DeviceExtension; 00432 00433 DPRINT("pdo 0x%p, extension 0x%p\n", Pdo, pdoData); 00434 00435 if (pdoData->AcpiHandle) 00436 acpi_bus_get_power(pdoData->AcpiHandle, &acpistate); 00437 else 00438 acpistate = ACPI_STATE_D0; 00439 00440 switch(acpistate) 00441 { 00442 case ACPI_STATE_D0: 00443 ntState = PowerDeviceD0; 00444 break; 00445 case ACPI_STATE_D1: 00446 ntState = PowerDeviceD1; 00447 break; 00448 case ACPI_STATE_D2: 00449 ntState = PowerDeviceD2; 00450 break; 00451 case ACPI_STATE_D3: 00452 ntState = PowerDeviceD3; 00453 break; 00454 default: 00455 DPRINT1("Unknown power state (%d) returned by acpi\n",acpistate); 00456 ntState = PowerDeviceUnspecified; 00457 break; 00458 } 00459 00460 // 00461 // Initialize the rest 00462 // 00463 pdoData->Common.IsFDO = FALSE; 00464 pdoData->Common.Self = Pdo; 00465 00466 pdoData->ParentFdo = FdoData->Common.Self; 00467 00468 00469 INITIALIZE_PNP_STATE(pdoData->Common); 00470 00471 pdoData->Common.DevicePowerState = ntState; 00472 pdoData->Common.SystemPowerState = FdoData->Common.SystemPowerState; 00473 00474 Pdo->Flags |= DO_POWER_PAGABLE; 00475 00476 ExAcquireFastMutex (&FdoData->Mutex); 00477 InsertTailList(&FdoData->ListOfPDOs, &pdoData->Link); 00478 FdoData->NumPDOs++; 00479 ExReleaseFastMutex (&FdoData->Mutex); 00480 00481 // This should be the last step in initialization. 00482 Pdo->Flags &= ~DO_DEVICE_INITIALIZING; 00483 00484 } 00485 00486 #if DBG 00487 00488 PCHAR 00489 PnPMinorFunctionString ( 00490 UCHAR MinorFunction 00491 ) 00492 { 00493 switch (MinorFunction) 00494 { 00495 case IRP_MN_START_DEVICE: 00496 return "IRP_MN_START_DEVICE"; 00497 case IRP_MN_QUERY_REMOVE_DEVICE: 00498 return "IRP_MN_QUERY_REMOVE_DEVICE"; 00499 case IRP_MN_REMOVE_DEVICE: 00500 return "IRP_MN_REMOVE_DEVICE"; 00501 case IRP_MN_CANCEL_REMOVE_DEVICE: 00502 return "IRP_MN_CANCEL_REMOVE_DEVICE"; 00503 case IRP_MN_STOP_DEVICE: 00504 return "IRP_MN_STOP_DEVICE"; 00505 case IRP_MN_QUERY_STOP_DEVICE: 00506 return "IRP_MN_QUERY_STOP_DEVICE"; 00507 case IRP_MN_CANCEL_STOP_DEVICE: 00508 return "IRP_MN_CANCEL_STOP_DEVICE"; 00509 case IRP_MN_QUERY_DEVICE_RELATIONS: 00510 return "IRP_MN_QUERY_DEVICE_RELATIONS"; 00511 case IRP_MN_QUERY_INTERFACE: 00512 return "IRP_MN_QUERY_INTERFACE"; 00513 case IRP_MN_QUERY_CAPABILITIES: 00514 return "IRP_MN_QUERY_CAPABILITIES"; 00515 case IRP_MN_QUERY_RESOURCES: 00516 return "IRP_MN_QUERY_RESOURCES"; 00517 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: 00518 return "IRP_MN_QUERY_RESOURCE_REQUIREMENTS"; 00519 case IRP_MN_QUERY_DEVICE_TEXT: 00520 return "IRP_MN_QUERY_DEVICE_TEXT"; 00521 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: 00522 return "IRP_MN_FILTER_RESOURCE_REQUIREMENTS"; 00523 case IRP_MN_READ_CONFIG: 00524 return "IRP_MN_READ_CONFIG"; 00525 case IRP_MN_WRITE_CONFIG: 00526 return "IRP_MN_WRITE_CONFIG"; 00527 case IRP_MN_EJECT: 00528 return "IRP_MN_EJECT"; 00529 case IRP_MN_SET_LOCK: 00530 return "IRP_MN_SET_LOCK"; 00531 case IRP_MN_QUERY_ID: 00532 return "IRP_MN_QUERY_ID"; 00533 case IRP_MN_QUERY_PNP_DEVICE_STATE: 00534 return "IRP_MN_QUERY_PNP_DEVICE_STATE"; 00535 case IRP_MN_QUERY_BUS_INFORMATION: 00536 return "IRP_MN_QUERY_BUS_INFORMATION"; 00537 case IRP_MN_DEVICE_USAGE_NOTIFICATION: 00538 return "IRP_MN_DEVICE_USAGE_NOTIFICATION"; 00539 case IRP_MN_SURPRISE_REMOVAL: 00540 return "IRP_MN_SURPRISE_REMOVAL"; 00541 case IRP_MN_QUERY_LEGACY_BUS_INFORMATION: 00542 return "IRP_MN_QUERY_LEGACY_BUS_INFORMATION"; 00543 default: 00544 return "unknown_pnp_irp"; 00545 } 00546 } 00547 00548 PCHAR 00549 DbgDeviceRelationString( 00550 DEVICE_RELATION_TYPE Type 00551 ) 00552 { 00553 switch (Type) 00554 { 00555 case BusRelations: 00556 return "BusRelations"; 00557 case EjectionRelations: 00558 return "EjectionRelations"; 00559 case RemovalRelations: 00560 return "RemovalRelations"; 00561 case TargetDeviceRelation: 00562 return "TargetDeviceRelation"; 00563 default: 00564 return "UnKnown Relation"; 00565 } 00566 } 00567 00568 PCHAR 00569 DbgDeviceIDString( 00570 BUS_QUERY_ID_TYPE Type 00571 ) 00572 { 00573 switch (Type) 00574 { 00575 case BusQueryDeviceID: 00576 return "BusQueryDeviceID"; 00577 case BusQueryHardwareIDs: 00578 return "BusQueryHardwareIDs"; 00579 case BusQueryCompatibleIDs: 00580 return "BusQueryCompatibleIDs"; 00581 case BusQueryInstanceID: 00582 return "BusQueryInstanceID"; 00583 case BusQueryDeviceSerialNumber: 00584 return "BusQueryDeviceSerialNumber"; 00585 default: 00586 return "UnKnown ID"; 00587 } 00588 } 00589 00590 #endif 00591 00592 Generated on Mon May 28 2012 04:17:37 for ReactOS by
1.7.6.1
|