次の方法で共有


ユーザーによるデバイスの取り外し

ユーザーがシステムの動作中にデバイスを取り外す方法は 2 つあります。1 つは、ユーザーがデバイスを取り外そうとしていることを (たとえば Unplug プログラムまたは Eject Hardware プログラムを使用して) システムに通知する "正常な取り外し" で、もう 1 つは、ユーザーがシステムに通知せずにデバイスを取り外す "突然の取り外し" です。**バスが突然の取り外しをサポートしている場合 (USB の場合など)、デバイスのドライバーはデバイスの突然の消失に対処できる必要があります。

正常な取り外し

ユーザーは、システムの Unplug プログラムまたは Eject Hardware プログラムを使用するか、デバイス マネージャーを使用してデバイスを無効にするか、または取り出し可能デバイスの取り出しボタンを押して、取り外しを要求します。フレームワークは、ドライバーで次の処理を行っていた場合を除いて、デバイスの取り外しまたは無効化を許可します。

デバイスをサポートする各関数ドライバーおよびフィルター ドライバーについて、フレームワークは、ドライバー スタックでの順位が高いものから順に、1 ドライバーずつ次の処理を行います。

  1. ドライバーが自己管理 I/O を使用している場合は、ドライバーの EvtDeviceSelfManagedIoSuspend コールバック関数を呼び出します。

  2. デバイスの電源管理された I/O キューをすべて停止します。

  3. ハードウェアとドライバーが DMA をサポートしている場合は、作成された各 DMA チャネルについて、ドライバーの EvtDmaEnablerSelfManagedIoStopEvtDmaEnablerFlush、および EvtDmaEnablerDisable の各コールバック関数 (存在する場合) を呼び出します。

  4. ドライバーの EvtDeviceD0ExitPreInterruptsDisabled コールバック関数 (存在する場合)を呼び出してから、各割り込みに対してドライバーの EvtInterruptDisable コールバック関数 (存在する場合) を呼び出し、ドライバーがデバイスの割り込みを無効化できるようにします。

  5. ドライバーの EvtDeviceD0Exit コールバック関数 (存在する場合) を呼び出します。

  6. ドライバーが自己管理 I/O を使用している場合は、ドライバーの EvtDeviceSelfManagedIoFlush コールバック関数を呼び出します。

  7. ドライバーの EvtDeviceReleaseHardware コールバック関数 (存在する場合) を呼び出し、PnP マネージャーがデバイスに割り当てたハードウェア リソースのリストを渡します。

  8. ドライバーが自己管理 I/O を使用している場合は、ドライバーの EvtDeviceSelfManagedIoCleanup コールバック関数を呼び出します。

スタック内で最後に呼び出されるドライバーは、バス ドライバーです。フレームワークがバス ドライバーの EvtDeviceD0Exit コールバック関数を呼び出すと、そのコールバック関数によってデバイス (バスの子デバイス) の電源状態が D3 に設定されます。

突然の取り外し

ユーザーがデバイスを突然取り外します。デバイスのバス ドライバーはデバイスが消失したことを検出し、WdfChildListUpdateChildDescriptionAsMissing を呼び出します。

デバイスをサポートする各関数ドライバーおよびフィルター ドライバーについて、フレームワークは、ドライバー スタックでの順位が高いものから順に、1 ドライバーずつ次の処理を行います。

  1. ドライバーの EvtDeviceSurpriseRemoval コールバック関数 (存在する場合) を呼び出します。

  2. デバイスが取り外されたときに作業状態 (D0) だった場合は、デバイスの電源管理された I/O キューをすべて停止します。

  3. デバイスが取り外されたときに作業状態 (D0) で、ドライバーが自己管理 I/O を使用している場合は、ドライバーの EvtDeviceSelfManagedIoSuspend コールバック関数を呼び出します。

  4. ハードウェアとドライバーが DMA をサポートしている場合は、作成された各 DMA チャネルについて、ドライバーの EvtDmaEnablerSelfManagedIoStopEvtDmaEnablerFlush、および EvtDmaEnablerDisable の各コールバック関数 (存在する場合) を呼び出します。

  5. ドライバーの EvtDeviceD0ExitPreInterruptsDisabled コールバック関数および EvtInterruptDisable コールバック関数 (存在する場合) を呼び出して、ドライバーがデバイスの割り込みを無効化できるようにします。

  6. ドライバーの EvtDeviceD0Exit コールバック関数 (存在する場合) を呼び出します。

  7. ドライバーの EvtDeviceReleaseHardware コールバック関数 (存在する場合) を呼び出し、PnP マネージャーがデバイスに割り当てたハードウェア リソースのリストを渡します。

  8. ドライバーが自己管理 I/O を使用している場合は、ドライバーの EvtDeviceSelfManagedIoFlush コールバック関数を呼び出します。

  9. ドライバーが自己管理 I/O を使用している場合は、ドライバーの EvtDeviceSelfManagedIoCleanup コールバック関数を呼び出します。

デバイスが予期せず取り外される可能性は常にあります。したがって、フレームワークは、上記の手順で示した以外の場合にもドライバーの EvtDeviceSurpriseRemoval コールバック関数を呼び出すことができます。たとえば、デバイスが低電力状態に移行中にユーザーがデバイスを突然取り外した場合、フレームワークは EvtDeviceReleaseHardware コールバック関数を呼び出した後で EvtDeviceSurpriseRemoval コールバック関数を呼び出すことができます。EvtDeviceSurpriseRemoval コールバック関数については、このコールバック関数および他のコールバック関数が特定の順序で呼び出されることを前提にしてコーディングしないでください。

また、フレームワークは、デバイスの EvtDeviceSurpriseRemoval コールバック関数を、そのデバイスの上記の手順で示したどのコールバック関数とも同期しません。したがって、上記のコールバック関数の実行中に EvtDeviceSurpriseRemoval コールバック関数が同時に実行される場合があります。