Compartilhar via


Inicialização de dispositivos e adaptadores

Este tópico descreve as etapas para inicializar um driver de cliente NetAdapterCx e iniciar objetos WDFDEVICE e NETADAPTER. Para obter mais informações sobre esses objetos e suas relações, consulte Resumo de objetos NetAdapterCx.

EVT_WDF_DRIVER_DEVICE_ADD

Um driver de cliente NetAdapterCx registra sua função de retorno de chamada EVT_WDF_DRIVER_DEVICE_ADD quando chama WdfDriverCreate de sua rotina DriverEntry.

Em EVT_WDF_DRIVER_DEVICE_ADD, um driver de cliente NetAdapterCx deve fazer o seguinte na ordem:

  1. Chamar NetDeviceInitConfig.

    status = NetDeviceInitConfig(DeviceInit);
    if (!NT_SUCCESS(status)) 
    {
        return status;
    }
    
  2. Chamar WdfDeviceCreate.

    Dica

    Se o dispositivo comportar mais de um NETADAPTER, recomendamos armazenar ponteiros para cada adaptador no contexto do dispositivo.

  3. Criar o objeto NETADAPTER. Para fazer isso, o cliente chama NetAdapterInitAllocate, seguido por métodos opcionais NetAdapterInitSetXxx para inicializar os atributos do adaptador. Por último, o cliente chama NetAdapterCreate.

    O exemplo a seguir mostra como um driver de cliente pode inicializar um objeto NETADAPTER. Observe que o tratamento de erro é simplificado nesse exemplo.

    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);
    ...
    

Se quiser, você pode adicionar espaço de contexto ao objeto NETADAPTER. Como você pode definir um contexto em qualquer objeto WDF, é possível adicionar um espaço de contexto separado para os objetos WDFDEVICE e NETADAPTER. No exemplo da etapa 3, o cliente adiciona MY_ADAPTER_CONTEXT ao objeto NETADAPTER. Para obter mais informações, consulte Espaço de contexto do objeto de estrutura.

Recomendamos colocar os dados relacionados ao dispositivo no contexto de WDFDEVICE e os dados relacionados à rede, como endereços de camada de link, no contexto de NETADAPTER. Se você estiver portando um driver NDIS 6.x existente, provavelmente terá um único MiniportAdapterContext que combina os dados relacionados à rede e ao dispositivo em uma única estrutura de dados. Para simplificar o processo de portabilidade, basta converter toda essa estrutura para o contexto de WDFDEVICE e tornar o contexto de NETADAPTER uma pequena estrutura que aponte para o contexto de WDFDEVICE.

Opcionalmente, você pode fornecer dois retornos de chamada para o método NET_ADAPTER_DATAPATH_CALLBACKS_INIT:

Para obter detalhes sobre o que fornecer nas implementações desses retornos de chamada, consulte as respectivas páginas de referência.

EVT_WDF_DEVICE_PREPARE_HARDWARE

Muitos drivers de cliente NetAdapterCx iniciam seus adaptadores de dentro da função de retorno de chamada EVT_WDF_DEVICE_PREPARE_HARDWARE, com a notável exceção dos drivers de cliente de extensão de classe de banda larga móvel. Para registrar uma função de retorno de chamada EVT_WDF_DEVICE_PREPARE_HARDWARE, um driver de cliente NetAdapterCx deve chamar WdfDeviceInitSetPnpPowerEventCallbacks.

Dentro de EVT_WDF_DEVICE_PREPARE_HARDWARE, além de outras tarefas de preparação de hardware, o driver de cliente define os recursos necessários e opcionais do adaptador.

NetAdapterCx requer que o driver de cliente defina os seguintes recursos:

O driver deve chamar NetAdapterStart para iniciar o adaptador.

O exemplo a seguir mostra como um driver de cliente pode iniciar um objeto NETADAPTER. O código necessário para configurar cada método de recursos de adaptador é deixado de fora para fins de brevidade e clareza, e o tratamento de erro é simplificado.

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