ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pnp.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.