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:
Chamar NetDeviceInitConfig.
status = NetDeviceInitConfig(DeviceInit); if (!NT_SUCCESS(status)) { return status; }
Chamar WdfDeviceCreate.
Dica
Se o dispositivo comportar mais de um NETADAPTER, recomendamos armazenar ponteiros para cada adaptador no contexto do dispositivo.
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:
Recursos de caminho de dados. O driver chama NetAdapterSetDataPathCapabilities para definir esses recursos. Para obter mais informações, consulte Gerenciamento de buffer de dados de rede.
Recursos de camada de link. O driver chama NetAdapterSetLinkLayerCapabilities para definir esses recursos.
Tamanho da unidade máxima de transmissão (MTU) de camada de link. O driver chama NetAdapterSetLinkLayerMtuSize para definir o tamanho de MTU.
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;
}