예제 #1
0
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;
}
예제 #3
0
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);
}