设备和适配器初始化

本主题介绍 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 对象。 有关详细信息,请参阅 框架对象上下文空间

建议将设备相关的数据放入 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 要求客户端驱动程序设置以下功能:

然后,驱动程序必须调用 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;
}