다음을 통해 공유


디바이스 및 어댑터 초기화

이 항목에서는 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 . 자세한 내용은 Framework 개체 컨텍스트 공간을 참조 하세요.

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를 사용하려면 클라이언트 드라이버가 다음 기능을 설정해야 합니다.

  • 데이터 경로 기능. 드라이버는 NetAdapterSetDataPathCapabilities를 호출하여 이러한 기능을 설정합니다. 자세한 내용은 네트워크 데이터 버퍼 관리를 참조하세요.

  • 링크 계층 기능. 드라이버는 NetAdapterSetLinkLayerCapabilities를 호출하여 이러한 기능을 설정합니다.

  • 링크 계층 MTU(최대 전송 단위) 크기입니다. 드라이버는 NetAdapterSetLinkLayerMtuSize를 호출하여 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;
}