デバイスとアダプターの初期化

このトピックでは、NetAdapterCx クライアント ドライバーが WDFDEVICE オブジェクトと NETADAPTER オブジェクトを初期化して起動する手順について説明します。 これらのオブジェクトとその関係の詳細については、「NetAdapterCx オブジェクトの概要」を参照してください。

EVT_WDF_DRIVER_DEVICE_ADD

NetAdapterCx クライアント ドライバーは、 DriverEntry ルーチンから WdfDriverCreate を呼び出すときに、その EVT_WDF_DRIVER_DEVICE_ADD コールバック関数を登録します。

EVT_WDF_DRIVER_DEVICE_ADDでは、NetAdapterCx クライアント ドライバーは、次の順序で実行する必要があります。

  1. NetDeviceInitConfig を呼び出します。

    status = NetDeviceInitConfig(DeviceInit);
    if (!NT_SUCCESS(status)) 
    {
        return status;
    }
    
  2. WdfDeviceCreate を呼び出 します。

    ヒント

    デバイスで複数の NETADAPTER がサポートされている場合は、各アダプターへのポインターをデバイス コンテキストに格納することをお勧めします。

  3. NETADAPTER オブジェクトを作成します。 これを行うために、クライアントは NetAdapterInitAllocate を呼び出し、その後にオプションの NetAdapterInitSetXxx メソッドを呼び出してアダプターの属性を初期化します。 最後に、クライアントは NetAdapterCreate を呼び出 します。

    次の例は、クライアント ドライバーが NETADAPTER オブジェクトを初期化する方法を示しています。 この例では、エラー処理が簡略化されていることに注意してください。

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attribs, MY_ADAPTER_CONTEXT);
    
    //
    // Allocate the initialization structure
    //
    PNETADAPTER_INIT adapterInit = NetAdapterInitAllocate(device);
    if(adapterInit == NULL)
    {
        return status;
    }        
    
    //
    // Optional: set additional attributes
    //
    
    // Datapath callbacks for creating packet queues
    NET_ADAPTER_DATAPATH_CALLBACKS datapathCallbacks;
    NET_ADAPTER_DATAPATH_CALLBACKS_INIT(&datapathCallbacks,
                                        MyEvtAdapterCreateTxQueue,
                                        MyEvtAdapterCreateRxQueue);
    NetAdapterInitSetDatapathCallbacks(adapterInit,
                                       datapathCallbacks);
    // 
    // Required: create the adapter
    //
    NETADAPTER* netAdapter;
    status = NetAdapterCreate(adapterInit, &attribs, netAdapter);
    if(!NT_SUCCESS(status))
    {
        NetAdapterInitFree(adapterInit);
        adapterInit = NULL;
        return status;
    }
    
    //
    // Required: free the adapter initialization object even 
    // if adapter creation succeeds
    //
    NetAdapterInitFree(adapterInit);
    adapterInit = NULL;
    
    //
    // Optional: initialize the adapter's context
    //
    PMY_ADAPTER_CONTEXT adapterContext = GetMyAdapterContext(&netAdapter);
    ...
    

必要に応じて、NETADAPTER オブジェクトにコンテキスト空間を追加できます。 任意の WDF オブジェクトにコンテキストを設定できるため、WDFDEVICE オブジェクトと NETADAPTER オブジェクトに個別のコンテキスト空間を追加できます。 手順 3 の例では、クライアントは NETADAPTER オブジェクトに MY_ADAPTER_CONTEXT を追加 します。 詳細については、「フレームワーク オブジェクト コンテキスト空間」を参照してください。

デバイス関連のデータを WDFDEVICE のコンテキストに配置し、ネットワーク関連のデータ (リンク レイヤー アドレスなど) を NETADAPTER コンテキストに配置することをお勧めします。 既存の NDIS 6.x ドライバーを移植する場合は、ネットワーク関連とデバイス関連のデータを 1 つのデータ構造に結合する 1 つのミニポートAdapterContext があります。 移植プロセスを簡略化するには、その構造体全体を WDFDEVICE コンテキストに変換し、NETADAPTER のコンテキストを WDFDEVICE のコンテキストを指す小さな構造体にします。

必要に応じて、 NET_ADAPTER_DATAPATH_CALLBACKS_INIT メソッドに 2 つのコールバックを指定できます。

これらのコールバックの実装で提供する内容の詳細については、個々のリファレンス ページを参照してください。

EVT_WDF_DEVICE_PREPARE_HARDWARE

多くの NetAdapterCx クライアント ドライバーは、 モバイル ブロードバンド クラス拡張クライアント ドライバーの注目すべき例外を除き、 EVT_WDF_DEVICE_PREPARE_HARDWARE コールバック関数内からアダプターを起動します。 EVT_WDF_DEVICE_PREPARE_HARDWARE コールバック関数を登録するには、NetAdapterCx クライアント ドライバーが WdfDeviceInitSetPnpPowerEventCallbacks を呼び出す必要があります。

EVT_WDF_DEVICE_PREPARE_HARDWARE内では、他のハードウェア準備タスクに加えて、クライアント ドライバーはアダプターの必須機能とオプション機能を設定します。

NetAdapterCx では、クライアント ドライバーで次の機能を設定する必要があります。

その後、ドライバーは、アダプターを起動するために NetAdapterStart を呼び出す必要があります。

次の例は、クライアント ドライバーが NETADAPTER オブジェクトを起動する方法を示しています。 各アダプター機能メソッドを設定するために必要なコードは簡潔でわかりやすくするために省略され、エラー処理が簡略化されることに注意してください。

PMY_DEVICE_CONTEXT deviceContext = GetMyDeviceContext(device);

NETADAPTER netAdapter = deviceContext->NetAdapter;

PMY_ADAPTER_CONTEXT adapterContext = GetMyAdapterContext(netAdapter);

//
// Set required adapter capabilities
//

// Link layer capabilities
...
NetAdapterSetDatapathCapabilities(netAdapter,
                                  &txCapabilities,
                                  &rxCapabilities);
...
NetAdapterSetLinkLayerCapabilities(netAdapter,
                                   &linkLayerCapabilities);
...
NetAdapterSetLinkLayerMtuSize(netAdapter,
                              MY_MAX_PACKET_SIZE - ETHERNET_HEADER_LENGTH);

//
// Set optional adapter capabilities
//

// Link layer capabilities
...
NetAdapterSetPermanentLinkLayerAddress(netAdapter,
                                       &adapterContext->PermanentAddress);
...
NetAdapterSetCurrentLinkLayerAddress(netAdapter,
                                     &adapterContext->CurrentAddress);

// Datapath capabilities
...
NetAdapterSetDatapathCapabilities(netAdapter,
                                  &txCapabilities,
                                  &rxCapabilities);

// Receive scaling capabilities
...
NetAdapterSetReceiveScalingCapabilities(netAdapter,
                                        &receiveScalingCapabilities);

// Hardware offload capabilities
...
NetAdapterOffloadSetChecksumCapabilities(netAdapter,
                                         &checksumCapabilities);
...
NetAdapterOffloadSetLsoCapabilities(netAdapter,
                                    &lsoCapabilities);
...
NetAdapterOffloadSetRscCapabilities(netAdapter,
                                    &rscCapabilities);

//
// Required: start the adapter
//
status = NetAdapterStart(netAdapter);
if(!NT_SUCCESS(status))
{
    return status;
}