共用方式為


裝置和配接器初始化

本主題描述 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 的範例中,用戶端會將 MY_ADAPTER_CONTEXT 新增至 NETADAPTER 物件。 如需詳細資訊,請參閱 Framework 物件內容空間

我們建議您將設備相關資料放入 WDFDEVICE 的內容中,而將網路相關資料,例如連結層位址,放入 NETADAPTER 的內容中。 如果您要移植現有的 NDIS 6.x 驅動程式,您可能會有一個 MiniportAdapterContext,可將網路相關和裝置相關數據合併成單一數據結構。 為了簡化移植程式,只要將該整個結構轉換成 WDFDEVICE 內容,並將 NETADAPTER 的內容設為指向 WDFDEVICE 內容的小型結構。

您可以選擇性地為 NET_ADAPTER_DATAPATH_CALLBACKS_INIT 方法提供 2 個回呼:

如需這些回呼功能的實作詳細資訊,請參閱各個參考頁面。

EVT_WDF_DEVICE_準備硬體

許多 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;
}