裝置和配接器初始化
本主題描述 NetAdapterCx 用戶端驅動程式初始化和啟動 WDFDEVICE 和 NETADAPTER 物件的步驟。 如需這些物件及其關聯性的詳細資訊,請參閱 NetAdapterCx 物件的摘要。
EVT_WDF_DRIVER_DEVICE_ADD
NetAdapterCx 用戶端驅動程式從其 DriverEntry 例程呼叫 WdfDriverCreate 時,會註冊其EVT_WDF_DRIVER_DEVICE_ADD回呼函式。
在 EVT_WDF_DRIVER_DEVICE_ADD 中,NetAdapterCx 用戶端驅動程序應該依序執行下列動作:
-
status = NetDeviceInitConfig(DeviceInit); if (!NT_SUCCESS(status)) { return status; }
呼叫 WdfDeviceCreate。
提示
如果您的裝置支援多個 NETADAPTER,建議您將指標儲存到裝置內容中的每個適配卡。
建立 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_PREPARE_HARDWARE
許多 NetAdapterCx 用戶端驅動程式會從其EVT_WDF_DEVICE_PREPARE_HARDWARE回呼函式內啟動其配接器,但行動寬頻類別擴充用戶端驅動程序的顯著例外。 若要註冊EVT_WDF_DEVICE_PREPARE_HARDWARE回呼函式,NetAdapterCx 用戶端驅動程序必須呼叫 WdfDeviceInitSetPnpPowerEventCallbacks。
在 EVT_WDF_DEVICE_PREPARE_HARDWARE 中,除了其他硬體準備工作之外,客戶端驅動程式也會設定適配卡的必要和選擇性功能。
NetAdapterCx 需要用戶端驅動程式來設定下列功能:
數據路徑功能。 驅動程式會呼叫 NetAdapterSetDataPathCapabilities 來設定這些功能。 如需詳細資訊,請參閱 網路數據緩衝區管理。
連結層功能。 驅動程式會呼叫 NetAdapterSetLinkLayerCapabilities 來設定這些功能。
連結層最大傳輸單位 (MTU) 大小。 驅動程式會呼叫 NetAdapterSetLinkLayerMtuSize 來設定 MTU 大小。
然後,驅動程式必須呼叫 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;
}