Инициализация устройства и адаптера
В этом разделе описаны шаги для драйвера клиента NetAdapterCx для инициализации и запуска объектов WDFDEVICE и NETADAPTER. Дополнительные сведения об этих объектах и их отношениях см. в сводке объектов NetAdapterCx.
EVT_WDF_DRIVER_DEVICE_ADD
Драйвер клиента NetAdapterCx регистрирует свою функцию обратного вызова EVT_WDF_DRIVER_DEVICE_ADD при вызове WdfDriverCreate из подпрограммы DriverEntry.
В EVT_WDF_DRIVER_DEVICE_ADD драйвер клиента NetAdapterCx должен выполнять следующие действия:
Вызов NetDeviceInitConfig.
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. Дополнительные сведения см. в разделе "Пространство контекста объектов Платформы".
Рекомендуется поместить данные, связанные с устройством, в контекст для WDFDEVICE и сетевые данные, такие как адреса слоя ссылок в контекст NETADAPTER. Если вы переносите существующий драйвер NDIS 6.x, скорее всего, у вас будет один MiniportAdapterContext, который объединяет данные, связанные с сетью и устройства, в одну структуру данных. Чтобы упростить процесс переноса, просто преобразуйте всю структуру в контекст WDFDEVICE и сделайте контекст NETADAPTER небольшой структурой, которая указывает на контекст WDFDEVICE.
При необходимости можно предоставить 2 обратных вызова для метода NET_ADAPTER_DATAPATH_CALLBACKS_INIT:
Дополнительные сведения о том, что следует предоставить в реализации этих обратных вызовов, см. на отдельных справочных страницах.
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). Драйвер вызывает NetAdapterSetLayerMtuSize , чтобы задать размер 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;
}