NTSTATUS XenPciPdo_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state) { NTSTATUS status = STATUS_SUCCESS; PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device); PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo); CHAR path[128]; FUNCTION_ENTER(); FUNCTION_MSG("path = %s\n", xppdd->path); switch (previous_state) { case WdfPowerDeviceD0: FUNCTION_MSG("WdfPowerDeviceD1\n"); break; case WdfPowerDeviceD1: FUNCTION_MSG("WdfPowerDeviceD1\n"); break; case WdfPowerDeviceD2: FUNCTION_MSG("WdfPowerDeviceD2\n"); break; case WdfPowerDeviceD3: FUNCTION_MSG("WdfPowerDeviceD3\n"); if (xppdd->hiber_usage_kludge) { FUNCTION_MSG("(but really WdfPowerDevicePrepareForHibernation)\n"); previous_state = WdfPowerDevicePrepareForHibernation; } break; case WdfPowerDeviceD3Final: FUNCTION_MSG("WdfPowerDeviceD3Final\n"); break; case WdfPowerDevicePrepareForHibernation: FUNCTION_MSG("WdfPowerDevicePrepareForHibernation\n"); break; default: FUNCTION_MSG("Unknown WdfPowerDevice state %d\n", previous_state); break; } status = XenPci_GetBackendDetails(device); if (!NT_SUCCESS(status)) { WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart); FUNCTION_EXIT_STATUS(status); return status; } if (previous_state == WdfPowerDevicePrepareForHibernation && xppdd->device_callback) { FUNCTION_MSG("Restoring watch %s\n", xppdd->device); RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path); XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackendStateCallback, xppdd); } if (!NT_SUCCESS(status)) { RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path); //XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device); WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart); FUNCTION_EXIT_STATUS(status); return status; } FUNCTION_EXIT(); return status; }
NTSTATUS NfcCxEvtHardwareEvent( _In_ PNFCCX_DRIVER_GLOBALS NfcCxGlobals, _In_ WDFDEVICE Device, _In_ PNFC_CX_HARDWARE_EVENT NciCxHardwareEventParams ) /*++ Routine Description: This routine is called by the CX client to indicate that a Hardware Event has occured. Arguments: NfcCxGlobal - CX global pointer Device - WDF device to initialize NciCxHardwareEventParams - A pointer to a hardware event description structure Return Value: NTSTATUS --*/ { NTSTATUS status = STATUS_SUCCESS; PNFCCX_FDO_CONTEXT fdoContext; TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE); if (!VerifyPrivateGlobals(NfcCxGlobals)) { TRACE_LINE(LEVEL_ERROR, "Invalid CX global pointer"); status = STATUS_INVALID_PARAMETER; goto Done; } fdoContext = NfcCxFdoGetContext(Device); TRACE_LINE(LEVEL_INFO, "Client signalled an event, %!STATUS!, %!NFC_CX_HOST_ACTION!", NciCxHardwareEventParams->HardwareStatus, NciCxHardwareEventParams->HostAction); switch (NciCxHardwareEventParams->HostAction) { case HostActionStart: status = NfcCxFdoInitialize(fdoContext); if (!NT_SUCCESS(status)) { NfcCxFdoDeInitialize(fdoContext); TRACE_LINE(LEVEL_ERROR, "Failed to initialize the Fdo, %!STATUS!", status); goto Done; } break; case HostActionStop: status = NfcCxFdoDeInitialize(fdoContext); if (!NT_SUCCESS(status)) { TRACE_LINE(LEVEL_ERROR, "Failed to NfcCxFdoDeInitialize the Fdo, %!STATUS!", status); goto Done; } break; case HostActionRestart: WdfDeviceSetFailed(Device, WdfDeviceFailedAttemptRestart); break; case HostActionUnload: WdfDeviceSetFailed(Device, WdfDeviceFailedNoRestart); break; default: TRACE_LINE(LEVEL_ERROR, "Invalid Host Action %d", NciCxHardwareEventParams->HostAction); break; } Done: TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status); TRACE_LOG_NTSTATUS_ON_FAILURE(status); return status; }
NTSTATUS NICReset( IN PFDO_DATA FdoData ) /*++ Routine Description: Function to reset the device. Arguments: FdoData Pointer to our adapter Return Value: NT Status code. Note: NICReset is called at DPC. Take advantage of this fact when acquiring or releasing spinlocks --*/ { NTSTATUS status; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_DPC, "---> MPReset\n"); WdfSpinLockAcquire(FdoData->Lock); WdfSpinLockAcquire(FdoData->SendLock); WdfSpinLockAcquire(FdoData->RcvLock); do { // // Is this adapter already doing a reset? // if (MP_TEST_FLAG(FdoData, fMP_ADAPTER_RESET_IN_PROGRESS)) { status = STATUS_SUCCESS; goto exit; } MP_SET_FLAG(FdoData, fMP_ADAPTER_RESET_IN_PROGRESS); // // Is this adapter doing link detection? // if (MP_TEST_FLAG(FdoData, fMP_ADAPTER_LINK_DETECTION)) { TraceEvents(TRACE_LEVEL_WARNING, DBG_DPC, "Reset is pended...\n"); status = STATUS_SUCCESS; goto exit; } // // Is this adapter going to be removed // if (MP_TEST_FLAG(FdoData, fMP_ADAPTER_NON_RECOVER_ERROR)) { status = STATUS_DEVICE_DATA_ERROR; if (MP_TEST_FLAG(FdoData, fMP_ADAPTER_REMOVE_IN_PROGRESS)) { goto exit; } // This is an unrecoverable hardware failure. // We need to tell NDIS to remove this miniport MP_SET_FLAG(FdoData, fMP_ADAPTER_REMOVE_IN_PROGRESS); MP_CLEAR_FLAG(FdoData, fMP_ADAPTER_RESET_IN_PROGRESS); WdfSpinLockRelease(FdoData->RcvLock); WdfSpinLockRelease(FdoData->SendLock); WdfSpinLockRelease(FdoData->Lock); // TODO: Log an entry into the eventlog WdfDeviceSetFailed(FdoData->WdfDevice, WdfDeviceFailedAttemptRestart); TraceEvents(TRACE_LEVEL_FATAL, DBG_DPC, "<--- MPReset, status=%x\n", status); return status; } // // Disable the interrupt and issue a reset to the NIC // NICDisableInterrupt(FdoData); NICIssueSelectiveReset(FdoData); // // Release all the locks and then acquire back the send lock // we are going to clean up the send queues // which may involve calling Ndis APIs // release all the locks before grabbing the send lock to // avoid deadlocks // WdfSpinLockRelease(FdoData->RcvLock); WdfSpinLockRelease(FdoData->SendLock); WdfSpinLockRelease(FdoData->Lock); WdfSpinLockAcquire(FdoData->SendLock); // // Free the packets on SendQueueList // NICFreeQueuedSendPackets(FdoData); // // Free the packets being actively sent & stopped // NICFreeBusySendPackets(FdoData); RtlZeroMemory(FdoData->MpTcbMem, FdoData->MpTcbMemSize); // // Re-initialize the send structures // NICInitSendBuffers(FdoData); WdfSpinLockRelease(FdoData->SendLock); // // get all the locks again in the right order // WdfSpinLockAcquire(FdoData->Lock); WdfSpinLockAcquire(FdoData->SendLock); WdfSpinLockAcquire(FdoData->RcvLock); // // Reset the RFD list and re-start RU // NICResetRecv(FdoData); status = NICStartRecv(FdoData); if (status != STATUS_SUCCESS) { // Are we having failures in a few consecutive resets? if (FdoData->HwErrCount < NIC_HARDWARE_ERROR_THRESHOLD) { // It's not over the threshold yet, let it to continue FdoData->HwErrCount++; } else { // This is an unrecoverable hardware failure. // We need to tell NDIS to remove this miniport MP_SET_FLAG(FdoData, fMP_ADAPTER_REMOVE_IN_PROGRESS); MP_CLEAR_FLAG(FdoData, fMP_ADAPTER_RESET_IN_PROGRESS); WdfSpinLockRelease(FdoData->RcvLock); WdfSpinLockRelease(FdoData->SendLock); WdfSpinLockRelease(FdoData->Lock); // TODO: Log an entry into the eventlog // // Tell the system that the device has failed. // WdfDeviceSetFailed(FdoData->WdfDevice, WdfDeviceFailedAttemptRestart); TraceEvents(TRACE_LEVEL_ERROR, DBG_DPC, "<--- MPReset, status=%x\n", status); return(status); } break; } FdoData->HwErrCount = 0; MP_CLEAR_FLAG(FdoData, fMP_ADAPTER_HARDWARE_ERROR); NICEnableInterrupt(FdoData->WdfInterrupt, FdoData); } WHILE (FALSE); MP_CLEAR_FLAG(FdoData, fMP_ADAPTER_RESET_IN_PROGRESS); exit: WdfSpinLockRelease(FdoData->RcvLock); WdfSpinLockRelease(FdoData->SendLock); WdfSpinLockRelease(FdoData->Lock); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_DPC, "<--- MPReset, status=%x\n", status); return(status); }