PortCls オーディオ ドライバー用に PnP 再調整を実装する

PnP 再調整は、メモリ リソースを再割り当てする必要がある特定の PCI シナリオで使用されます。

再調整は、次の 2 つの主なシナリオでトリガーできます。

  1. PCIホットプラグ:ユーザーがデバイスを接続すると、PCI バスには新しいデバイスのドライバーをロードするための十分なリソースがありません。 このカテゴリに分類されるデバイスの例としては、Thunderbolt、USB-C、NVME ストレージなどがあります。 このシナリオでは、追加するデバイスをサポートするため、メモリ リソースを再配置して統合 (再調整) する必要があります。
  2. PCI サイズ変更可能な BAR:デバイスのドライバーがメモリに正常に読み込まれると、追加のリソースが要求されます。 デバイスの例としては、ハイエンドのグラフィックス カードやストレージ デバイスなどがあります。 ビデオ ドライバーのサポートについて詳しくは、「サイズ変更可能な BAR のサポート」をご覧ください。 このトピックでは、PortCls オーディオ ドライバーの PnP 再調整を実装するために何を行う必要があるかについて説明します。

PnP 再調整は、Windows 10 バージョン 1511 以降の Windows バージョンで利用できます。

再調整の要件

Portcls オーディオ ドライバーは、次の条件が満たされた場合に再調整をサポートすることができます。

  • ミニポートは、IAdapterPnpManagement インターフェイスを Portcls に登録する必要があります。
  • ミニポートは、IAdapterPnpManagement::GetSupportedRebalanceType から PcRebalanceRemoveSubdevices を返す必要があります。
  • トポロジと WaveRT は、サポートされている 2 種類のポートです。

アクティブなオーディオ ストリームがある場合に再調整をサポートするには、portcls オーディオ ドライバーがこれら 2 つの追加要件のいずれかを満たしている必要があります。

OR

再調整が発生したときのオーディオ ストリームの動作

再調整がトリガーされた場合に、アクティブなオーディオ ストリームがあり、ドライバーによりアクティブなオーディオ ストリームの再調整がサポートされている場合、アクティブなオーディオ ストリームがすべて停止され、自動的には再起動されません。

IPortClsPnp COM インターフェイス

IPortClsPnp は、ポート クラス ドライバー (PortCls) がアダプターに公開する PnP 管理インターフェイスです。

IPortClsPnpIUnknown から継承され、次のメソッドもサポートします。

オーディオ ミニポート ドライバーは、Portcls エクスポートを使用するか、WaveRT ポート オブジェクトで公開されている IPortClsPnp COM インターフェイスを通じて PNP 通知インターフェイスを登録できます。 登録と登録解除には、IPortClsPnp::RegisterAdapterPnpManagementIPortClsPnp::UnregisterAdapterPnpManagement を使用します。

必要な PortCls エクスポート DDI

IAdapterPnpManagement は、アダプターが PnP 管理メッセージを受信する場合に実装および登録する必要があるインターフェイスです。 PcRegisterAdapterPnpManagement を使用して、このインターフェイスを PortCls に登録します。 PcUnregisterAdapterPnpManagement を使用して、PortCls からこのインターフェイスを登録解除します。

必須ドライバー DDI

再調整をサポートするには、次の IAdapterPnpManagement DDI を実装する必要があります。

  • IAdapterPnpManagement::GetSupportedRebalanceType は、QueryStop の処理中に Portcls によって呼び出されます。 ミニポートは、PC_REBALANCE_TYPE 列挙型で定義されている、サポートされる再調整型を返します。

    Portcls は、この呼び出しを行う前にデバイスのグローバル ロックを取得します。したがって、ミニポートは、可能な限りすばやくこの呼び出しを実行する必要があります。

  • IAdapterPnpManagement::P npQueryStop は、QueryStop IRP に成功する直前に portcls によって呼び出されます。 これは単なる通知であるため、呼び出しは値を返しません。

    Portcls は、この呼び出しを行う前にデバイスのグローバル ロックを取得します。したがって、ミニポートは、可能な限りすばやくこの呼び出しを実行する必要があります。 Stop が保留中の間、Portcls は新しい作成要求をブロック (保留) します。

  • IAdapterPnpManagement::P npCancelStop は、CanceStop IRP の処理中に portcls により呼び出されます。 これは通知にすぎません。 以前に PnpQueryStop 通知を受信したことがなくても、ミニポートが PnpCancelStop を受け取る可能性があります。 ミニポートは、この動作に対応するよう記述する必要があります。 たとえば、これは、Portcls がこの通知をミニポートに転送する機会を持つ前に、QueryStop ロジックが IRP に失敗した場合などです。 このシナリオでは、PnP マネージャーは引き続き PnP Cancel Stop を呼び出します。

    Portcls は、この呼び出しを行う前にデバイスのグローバル ロックを取得します。したがって、ミニポートは、可能な限りすばやくこの呼び出しを実行する必要があります。 Stop が保留中の間、Portcls は新しい作成要求をブロック (保留) します。 PortCls は、保留中の Stop が取り消されると、保留になった作成要求をすべて再開します。

  • IAdapterPnpManagement::PnpStop は、すべての Ioctl 操作を停止し、アクティブなストリームを [run|pause|acquire] 状態から [stop] 状態に移行した後、Portcls によって呼び出されます。 この呼び出しは、デバイスのグローバル ロックを保持している間は行われません。 したがって、ミニポートには、非同期操作 (作業項目、dpc、非同期スレッド) を待機し、そのオーディオ サブデバイスを登録解除する機会があります。 この呼び出しから戻る前に、ミニポートは、すべてのハードウェア リソースが解放されていることを確認する必要があります。

    既存のオーディオ クライアントが現在のハンドルをいつ解放かは不明であるため、ミニポートは現在のミニポート/ストリーム オブジェクトが削除されるのを待つ必要があります。 PnpStop スレッドは、システムをクラッシュさせることなく永久にブロックすることはできません。つまり、これは PnP/Power スレッドです。

IMiniportPnpNotify

IMiniportPnpNotify は、ミニポート オブジェクト (オーディオ サブデバイス) が PnP 状態変更通知を受信できるようにする省略可能なインターフェイスです。

ミニポートには、登録された各オーディオ サブデバイスの PnP 停止通知を受信する機会があります。 この通知を受信するには、サブデバイスが IMiniportPnpNotify をサポートしている必要があります。 このインターフェイスでは、IMiniportPnpNotify::PnpStop 通知のみが定義されます。

使用可能な IMiniportPnpNotify インターフェイスは、WaveRT とトポロジの両方にあります。

Portcls は、この呼び出しを行う前にデバイスのグローバル ロックを取得するため、ミニポートは、可能な限りすばやくこの呼び出しを実行する必要があります。 ミニポートは、他のスレッド/作業項目がデバイスのグローバル ロックを待機しているときにデッドロックを防ぐため、この呼び出しの処理中に他のアクティビティを待機してはなりません。 必要に応じて、ミニポートは IAdapterPnpManagement::PnpStop 呼び出しで待機できます。