/*++ Module Name: POWER.C Abstract: This module contains contains the plugplay power calls for a serial port bus enumerator PNP / WDM driver. Environment: kernel mode only Notes: Revision History: --*/ #include #include #include "mxenum.h" #include "mxlog.h" static const PHYSICAL_ADDRESS SerialPhysicalZero = {0}; #ifdef ALLOC_PRAGMA #pragma alloc_text (PAGE, MxenumPowerDispatch) #pragma alloc_text (PAGE, MxenumFdoPowerDispatch) #pragma alloc_text (PAGE, MxenumPdoPowerDispatch) #endif NTSTATUS MxenumPowerDispatch ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ --*/ { PIO_STACK_LOCATION irpStack; NTSTATUS status; PCOMMON_DEVICE_DATA commonData; PAGED_CODE (); status = STATUS_SUCCESS; irpStack = IoGetCurrentIrpStackLocation (Irp); // ASSERT (IRP_MJ_POWER == irpStack->MajorFunction); commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension; if (commonData->IsFDO) { status = MxenumFdoPowerDispatch ((PFDO_DEVICE_DATA) DeviceObject->DeviceExtension, Irp); } else { status = MxenumPdoPowerDispatch ((PPDO_DEVICE_DATA) DeviceObject->DeviceExtension, Irp); } return status; } NTSTATUS MxenumFdoPowerComplete ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ); NTSTATUS MxenumFdoPowerDispatch( PFDO_DEVICE_DATA Data, PIRP Irp ) /*++ --*/ { NTSTATUS status; BOOLEAN hookit = FALSE; POWER_STATE powerState; POWER_STATE_TYPE powerType; PIO_STACK_LOCATION stack; UCHAR minorFunction; stack = IoGetCurrentIrpStackLocation (Irp); minorFunction = stack->MinorFunction; powerType = stack->Parameters.Power.Type; powerState = stack->Parameters.Power.State; PAGED_CODE (); status = MxenumIncIoCount (Data); if (!NT_SUCCESS (status)) { PoStartNextPowerIrp (Irp); Irp->IoStatus.Information = 0; Irp->IoStatus.Status = status; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } status = Irp->IoStatus.Status; switch (minorFunction) { case IRP_MN_SET_POWER: MxenumKdPrint( MXENUM_DBG_TRACE, ("Serenum-PnP Setting %s state to %d\n", ((powerType == SystemPowerState) ? "System" : "Device"), powerState.SystemState)); switch (powerType) { case DevicePowerState: status = Irp->IoStatus.Status = STATUS_SUCCESS; if (Data->DeviceState < powerState.DeviceState) { // // Powering down PoSetPowerState (Data->Self, powerType, powerState); Data->DeviceState = powerState.DeviceState; } else if (Data->DeviceState > powerState.DeviceState) { // // Powering Up // hookit = TRUE; } break; case SystemPowerState: MxenumKdPrint (MXENUM_DBG_TRACE, ("In SystemPowerState\n" " Current System state = %d\n" " Device started = %d\n" " System state to be set = %d\n" " Irql = %x\n", Data->SystemState, Data->Started, powerState.SystemState, KeGetCurrentIrql())); /* 3-22-01 by William if ((Data->SystemState == PowerSystemHibernate)&& */ if ((Data->SystemState != PowerSystemWorking)&& // (Data->Started == TRUE)&& (powerState.SystemState == PowerSystemWorking)){ ULONG i; MxenumKdPrint (MXENUM_DBG_TRACE,("Hook it\n")); // hookit = TRUE; MxenumKdPrint (MXENUM_DBG_TRACE, ("Start Device: Start to download\n")); i = 0; while (BoardDesc[Data->BoardType-1][i]) i++; i <<= 1; status = MxenumDownloadFirmware(Data,TRUE); MxenumKdPrint (MXENUM_DBG_TRACE, ("BoardDesc(%d)->%ws\n",i,BoardDesc[Data->BoardType-1])); if (status != 0) { ULONG j; j = 0; while (DownloadErrMsg[status-1][j]) j++; j <<= 1; MxenumKdPrint (MXENUM_DBG_TRACE, ("Start Device: Device started failure\n")); #if 0 MxenumLogError( DeviceObject->DriverObject, NULL, SerialPhysicalZero, SerialPhysicalZero, 0, 0, 0, 19, STATUS_SUCCESS, MXENUM_DOWNLOAD_FAIL, i + sizeof (WCHAR), BoardDesc[Data->BoardType -1], j + sizeof (WCHAR), DownloadErrMsg[status -1] ); #endif Data->Started = FALSE; } else { MxenumKdPrint (MXENUM_DBG_TRACE, ("Start Device: Device started successfully\n")); Data->Started = TRUE; } } status = STATUS_SUCCESS; // return SUCCESS anyway break; default: break; } // // Power IRPS come synchronously; drivers must call // PoStartNextPowerIrp, when they are ready for the next power // irp. This can be called here, or in the completetion // routine, but never the less must be called. // Irp->IoStatus.Status = status; Data->SystemState = powerState.SystemState; IoCopyCurrentIrpStackLocationToNext (Irp); PoStartNextPowerIrp (Irp); PoCallDriver (Data->TopOfStack, Irp); MxenumDecIoCount (Data); return status; case IRP_MN_QUERY_POWER: // Data->PowerQueryLock = TRUE; status = Irp->IoStatus.Status = STATUS_SUCCESS; break; default: break; } IoCopyCurrentIrpStackLocationToNext (Irp); if (hookit) { status = MxenumIncIoCount (Data); // ASSERT (STATUS_SUCCESS == status); IoSetCompletionRoutine (Irp, MxenumFdoPowerComplete, NULL, TRUE, TRUE, TRUE); PoCallDriver (Data->TopOfStack, Irp); } else { // // Power IRPS come synchronously; drivers must call // PoStartNextPowerIrp, when they are ready for the next power // irp. This can be called here, or in the completetion // routine, but never the less must be called. // PoStartNextPowerIrp (Irp); PoCallDriver (Data->TopOfStack, Irp); } #if 0 if ((minorFunction == IRP_MN_SET_POWER)&& (powerType == SystemPowerState)) { Data->SystemState = powerState.SystemState; } #endif MxenumDecIoCount (Data); return status; } NTSTATUS MxenumFdoPowerComplete ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) /*++ --*/ { POWER_STATE powerState; POWER_STATE_TYPE powerType; PIO_STACK_LOCATION stack; PFDO_DEVICE_DATA data; NTSTATUS status = STATUS_SUCCESS; UNREFERENCED_PARAMETER (Context); data = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension; stack = IoGetCurrentIrpStackLocation (Irp); powerType = stack->Parameters.Power.Type; powerState = stack->Parameters.Power.State; MxenumKdPrint (MXENUM_DBG_TRACE, ("MxenumFdoPowerComplete,irql=%x\n",KeGetCurrentIrql())); switch (stack->MinorFunction) { case IRP_MN_SET_POWER: switch (powerType) { case DevicePowerState: // // Powering Up // // ASSERT (powerState.DeviceState < data->DeviceState); data->DeviceState = powerState.DeviceState; PoSetPowerState (data->Self, powerType, powerState); break; case SystemPowerState: { ULONG i; MxenumKdPrint (MXENUM_DBG_TRACE, ("Start Device: Start to download\n")); i = 0; while (BoardDesc[data->BoardType-1][i]) i++; i <<= 1; status = MxenumDownloadFirmware(data,TRUE); MxenumKdPrint (MXENUM_DBG_TRACE, ("BoardDesc(%d)->%ws\n",i,BoardDesc[data->BoardType-1])); if (status != 0) { ULONG j; j = 0; while (DownloadErrMsg[status-1][j]) j++; j <<= 1; MxenumKdPrint (MXENUM_DBG_TRACE, ("Start Device: Device started failure\n")); MxenumLogError( DeviceObject->DriverObject, NULL, SerialPhysicalZero, SerialPhysicalZero, 0, 0, 0, 19, STATUS_SUCCESS, MXENUM_DOWNLOAD_FAIL, i + sizeof (WCHAR), BoardDesc[data->BoardType -1], j + sizeof (WCHAR), DownloadErrMsg[status -1] ); data->Started = FALSE; status = STATUS_UNSUCCESSFUL; } else { MxenumKdPrint (MXENUM_DBG_TRACE, ("Start Device: Device started successfully\n")); data->Started = TRUE; } break; } default: break; } break; case IRP_MN_QUERY_POWER: // ASSERT (IRP_MN_QUERY_POWER != stack->MinorFunction); break; default: // ASSERT (0xBADBAD == IRP_MN_QUERY_POWER); break; } PoStartNextPowerIrp (Irp); MxenumDecIoCount (data); return status; } VOID MxenumPdoPowerComplete ( IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Irp, IN PIO_STATUS_BLOCK IoStatus ); NTSTATUS MxenumPdoPowerDispatch ( PPDO_DEVICE_DATA PdoData, PIRP Irp ) /*++ --*/ { NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION stack; POWER_STATE powerState; POWER_STATE_TYPE powerType; PAGED_CODE(); status = Irp->IoStatus.Status; stack = IoGetCurrentIrpStackLocation (Irp); powerType = stack->Parameters.Power.Type; powerState = stack->Parameters.Power.State; switch (stack->MinorFunction) { case IRP_MN_SET_POWER: switch (powerType) { case DevicePowerState: if (PdoData->DeviceState > powerState.DeviceState) { PoSetPowerState (PdoData->Self, powerType, powerState); PdoData->DeviceState = powerState.DeviceState; } else if (PdoData->DeviceState < powerState.DeviceState) { // // Powering down. // PoSetPowerState (PdoData->Self, powerType, powerState); PdoData->DeviceState = powerState.DeviceState; } break; case SystemPowerState: status = STATUS_SUCCESS; break; default: // status = STATUS_NOT_IMPLEMENTED; break; } break; case IRP_MN_QUERY_POWER: PdoData->PowerQueryLock = TRUE; status = STATUS_SUCCESS; break; case IRP_MN_WAIT_WAKE: case IRP_MN_POWER_SEQUENCE: default: // status = STATUS_NOT_IMPLEMENTED; break; } Irp->IoStatus.Status = status; PoStartNextPowerIrp (Irp); IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; }