디바이스 및 어댑터 초기화

이 항목에서는 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단계의 예제에서 클라이언트는 NETADAPTER 개체에 를 추가 MY_ADAPTER_CONTEXT 합니다. 자세한 내용은 프레임워크 개체 컨텍스트 공간을 참조하세요.

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