/*++ Copyright (c) 1997 Microsoft Corporation Module Name: bus.c Abstract: This module contains the bus dispatcher for the ACPI driver, NT version Author: Stephane Plante (splante) Environment: NT Kernel Model Driver only --*/ #include "pch.h" #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, ACPIInternalDeviceClockIrpStartDevice) #pragma alloc_text(PAGE, ACPIInternalDeviceQueryCapabilities) #pragma alloc_text(PAGE, ACPIInternalDeviceQueryDeviceRelations) #endif NTSTATUS ACPIInternalDeviceClockIrpStartDevice( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This function is called to start the Real-Time Clock in the system. This is similar to starting all the other devices in the system, except that in this case, we send a WAIT_WAKE irp to the device Arguments: DeviceObject - The real-time clock object Irp - The start request Return Value: NTSTATUS --*/ { NTSTATUS status; PAGED_CODE(); // // Start the device // status = ACPIInitStartDevice( DeviceObject, NULL, ACPIInternalDeviceClockIrpStartDeviceCompletion, Irp, Irp ); if (NT_SUCCESS(status)) { return STATUS_PENDING; } else { return status; } } VOID ACPIInternalDeviceClockIrpStartDeviceCompletion( IN PDEVICE_EXTENSION DeviceExtension, IN PVOID Context, IN NTSTATUS Status ) /*++ Routine Description: This is the callback routine that is invoked when we have finished programming the resources Arguments: DeviceExtension - Extension of the device that was started Context - The Irp Status - The Result Return Value: None --*/ { KIRQL oldIrql; IO_STATUS_BLOCK ioStatus; PIRP irp = (PIRP) Context; POWER_STATE state; irp->IoStatus.Status = Status; if (NT_SUCCESS(Status)) { // // Remember that the device is started // DeviceExtension->DeviceState = Started; // // If the device doesn't support Wakeup, then we don't have to // anything else here // if ( !(DeviceExtension->Flags & DEV_CAP_WAKE) ) { goto ACPIInternalDeviceClockIrpStartDeviceCompletionExit; } // // Make sure that we are holding the power lock // KeAcquireSpinLock( &AcpiPowerLock, &oldIrql ); // // Remember the maximum state that the clock can wake the system // state.SystemState = DeviceExtension->PowerInfo.SystemWakeLevel; // // Done with the lock // KeReleaseSpinLock( &AcpiPowerLock, oldIrql ); // // Initialize the IO_STATUS_BLOCK that we will use to start the wait // wake loop // ioStatus.Status = STATUS_SUCCESS; ioStatus.Information = 0; // // Start the wait wake loop // Status = ACPIInternalWaitWakeLoop( DeviceExtension->DeviceObject, IRP_MN_WAIT_WAKE, state, NULL, &ioStatus ); if (!NT_SUCCESS(Status)) { irp->IoStatus.Status = Status; goto ACPIInternalDeviceClockIrpStartDeviceCompletionExit; } } ACPIInternalDeviceClockIrpStartDeviceCompletionExit: // // Complete the irp // IoCompleteRequest( irp, IO_NO_INCREMENT ); } NTSTATUS ACPIInternalDeviceQueryCapabilities( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine is the dispatch point for the IRP_MN_QUERY_CAPABILITIES requests sent to the PDO Arguments: DeviceObject - Pointer to the device object we received the request for Irp - Pointer to the request Return Value: NTSTATUS --*/ { NTSTATUS status = STATUS_SUCCESS; PDEVICE_CAPABILITIES capabilities; PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject); PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp ); PAGED_CODE(); // // Grab a pointer to the capabilities // capabilities = irpStack->Parameters.DeviceCapabilities.Capabilities; #ifndef HANDLE_BOGUS_CAPS if (capabilities->Version < 1) { // // do not touch irp! // status = Irp->IoStatus.Status; goto ACPIInternalDeviceQueryCapabilitiesExit; } #endif // // Set the current flags for the capabilities // capabilities->UniqueID = (deviceExtension->InstanceID == NULL ? FALSE : TRUE); capabilities->RawDeviceOK = (deviceExtension->Flags & DEV_CAP_RAW) ? TRUE : FALSE; capabilities->SilentInstall = TRUE; // // Do the power capabilities // status = ACPISystemPowerQueryDeviceCapabilities( deviceExtension, capabilities ); if (!NT_SUCCESS(status)) { ACPIDevPrint( ( ACPI_PRINT_CRITICAL, deviceExtension, " - Could query device capabilities - %08lx", status ) ); goto ACPIInternalDeviceQueryCapabilitiesExit; } ACPIInternalDeviceQueryCapabilitiesExit: // // Done... // Irp->IoStatus.Status = status; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; } NTSTATUS ACPIInternalDeviceQueryDeviceRelations( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine is the dispatch point for the IRP_MN_QUERY_DEVICE_RELATION PNP minor function Arguments: DeviceObject - The object that we care about Irp - The request in question Return Value: NTSTATUS --*/ { NTSTATUS status ; PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject); PDEVICE_RELATIONS deviceRelations = NULL; PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp ); UCHAR minorFunction = irpStack->MinorFunction; PAGED_CODE(); switch(irpStack->Parameters.QueryDeviceRelations.Type) { case TargetDeviceRelation: status = ACPIBusIrpQueryTargetRelation( DeviceObject, Irp, &deviceRelations ); break ; default: status = STATUS_NOT_SUPPORTED; ACPIDevPrint( ( ACPI_PRINT_IRP, deviceExtension, "(0x%08lx): %s - Unhandled Type %d\n", Irp, ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction), irpStack->Parameters.QueryDeviceRelations.Type ) ); break ; } // // If we succeeds, then we can always write to the irp // if (NT_SUCCESS(status)) { Irp->IoStatus.Status = status; Irp->IoStatus.Information = (ULONG_PTR) deviceRelations; } else if (status != STATUS_NOT_SUPPORTED) { // // If we haven't succeed the irp, then we can also fail it // Irp->IoStatus.Status = status; Irp->IoStatus.Information = (ULONG_PTR) NULL; } else { // // Grab our status from what is already present // status = Irp->IoStatus.Status; } // // Done with the irp // IoCompleteRequest( Irp, IO_NO_INCREMENT ); // // Done // ACPIDevPrint( ( ACPI_PRINT_IRP, deviceExtension, "(0x%08lx): %s = 0x%08lx\n", Irp, ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction), status ) ); return status; } NTSTATUS ACPIInternalWaitWakeLoop( IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus ) /*++ Routine Description: This routine is called after the WAIT_WAKE on the RTC has been completed Arguments: DeviceObject - The RTC PDO MinorFunction - IRP_MN_WAIT_WAKE PowerState - The Sleep state that it could wake from Context - NOT USED IoStatus - The status of the request Return Value: NTSTATUS --*/ { if (!NT_SUCCESS(IoStatus->Status)) { return IoStatus->Status; } // // In this case, we just cause the same thing to happen again // PoRequestPowerIrp( DeviceObject, MinorFunction, PowerState, ACPIInternalWaitWakeLoop, Context, NULL ); // // Done // return STATUS_SUCCESS; }