Device and adapter initialization

Warning

Some information in this topic relates to prereleased product, which may be substantially modified before it's commercially released. Microsoft makes no warranties, express or implied, with respect to the information provided here.

NetAdapterCx is preview only in Windows 10, version 1809.

This topic describes the steps for a NetAdapterCx client driver to initialize and start WDFDEVICE and NETADAPTER objects. For more info about these objects and their relationship, see Summary of NetAdapterCx objects.

EVT_WDF_DRIVER_DEVICE_ADD

A NetAdapterCx client driver registers its EVT_WDF_DRIVER_DEVICE_ADD callback function when it calls WdfDriverCreate from its DriverEntry routine.

In EVT_WDF_DRIVER_DEVICE_ADD, a NetAdapterCx client driver should do the following in order:

  1. Call NetAdapterDeviceInitConfig.

    status = NetAdapterDeviceInitConfig(DeviceInit);
    if (!NT_SUCCESS(status)) 
    {
        return status;
    }
    
  2. Call WdfDeviceCreate.

    Tip

    If your device supports more than one NETADAPTER, we recommend storing pointers to each adapter in your device context.

  3. Create the NETADAPTER object. To do so, the client calls either NetDefaultAdapterInitAllocate or NetAdapterInitAllocate, followed by optional NetAdapterInitSetXxx methods to initailize the adapter's attributes. Finally, the client calls NetAdapterCreate.

    The following example shows how a client driver might initialize a default NETADAPTER object. Note that error handling is simplified in this example.

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attribs, MY_ADAPTER_CONTEXT);
    
    //
    // Allocate the initialization structure
    //
    PNETADAPTER_INIT adapterInit = NetDefaultAdapterInitAllocate(device);
    if(adapterInit == NULL)
    {
        return status;
    }        
    
    //
    // Optional: set additional attributes
    //
    
    // Datapath callbacks for creating packet queues
    PNET_ADAPTER_DATAPATH_CALLBACKS datapathCallbacks;
    NET_ADAPTER_DATAPATH_CALLBACKS_INIT(datapathCallbacks,
                                        MyEvtAdapterCreateTxQueue,
                                        MyEvtAdapterCreateRxQueue);
    NetAdapterInitSetDatapathCallbacks(adapterInit,
                                        datapathCallbacks);
    
    // Power settings attributes
    NetAdapterInitSetNetPowerSettingsAttributes(adapterInit,
                                                attribs);
    
    // Net request attributes
    NetAdapterInitSetNetRequestAttributes(adapterInit,
                                            attribs);
    
    // 
    // 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);
    ...
    

Optionally, you can add context space to the NETADAPTER object. Since you can set a context on any WDF object, you could add separate context space for the WDFDEVICE and the NETADAPTER objects. In the example in step 3, the client adds MY_ADAPTER_CONTEXT to the NETADAPTER object. For more info, see Framework Object Context Space.

We recommend that you put device-related data in the context for your WDFDEVICE, and networking-related data such as link layer addresses into your NETADAPTER context. If you are porting an existing NDIS 6.x driver, you'll likely have a single MiniportAdapterContext that combines networking-related and device-related data into a single data structure. To simplify the porting process, just convert that entire structure to the WDFDEVICE context, and make the NETADAPTER's context a small structure that points to the WDFDEVICE's context.

You can optionally provide 2 callbacks to the NET_ADAPTER_DATAPATH_CALLBACKS_INIT method:

For details on what to provide in your implementations of these callbacks, see the individual reference pages.

EVT_WDF_DEVICE_PREPARE_HARDWARE

Many NetAdapterCx client drivers start their adapters from within their EVT_WDF_DEVICE_PREPARE_HARDWARE callback function, with the notable exception of Mobile Broadband class extension client drivers. To register an EVT_WDF_DEVICE_PREPARE_HARDWARE callback function, a NetAdapterCx client driver must call WdfDeviceInitSetPnpPowerEventCallbacks.

In EVT_WDF_DEVICE_PREPARE_HARDWARE, in addition to other hardware preparation tasks the client driver must call NetAdapterStart. Before doing so, the driver can optionally set the adapter's capabilities.

The following example shows how a client driver might start a NETADAPTER object. Note that code required for setting up each adapter capabilities method is left out for brevity and clarity, and error handling is simplified.

PMY_DEVICE_CONTEXT deviceContext = GetMyDeviceContext(device);

NETADAPTER netAdapter = deviceContext->NetAdapter;

PMY_ADAPTER_CONTEXT adapterContext = GetMyAdapterContext(netAdapter);

//
// Optional: set adapter capabilities
//

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

NetAdapterSetLinkLayerMtuSize(netAdapter,
                              MY_MAX_PACKET_SIZE - ETHERNET_HEADER_LENGTH);

NetAdapterSetPermanentLinkLayerAddress(netAdapter,
                                       &adapterContext->PermanentAddress);

NetAdapterSetCurrentLinkLayerAddress(netAdapter,
                                     &adapterContext->CurrentAddress);

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

// Power capabilities
...
NetAdapterSetPowerCapabilities(netAdapter,
                               &powerCapabilities);

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

// Hardware offload capabilities
...
NetAdapterOffloadSetChecksumCapabilities(netAdapter,
                                         &checksumCapabilities,
                                         EvtAdapterOffloadSetChecksum);
...
NetAdapterOffloadSetLsoCapabilities(netAdapter,
                                    &lsoCapabilities,
                                    EvtAdapterOffloadSetLso);

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