Dela via


Initialisering av enhet och adapter

I det här avsnittet beskrivs stegen för en NetAdapterCx-klientdrivrutin för att initiera och starta WDFDEVICE- och NETADAPTER-objekt. Mer information om dessa objekt och deras relation finns i Sammanfattning av NetAdapterCx-objekt.

EVT_WDF_DRIVER_DEVICE_ADD

En NetAdapterCx-klientdrivrutin registrerar sin EVT_WDF_DRIVER_DEVICE_ADD återanropsfunktion när den anropar WdfDriverCreate från sin DriverEntry-rutin .

I EVT_WDF_DRIVER_DEVICE_ADD bör en NetAdapterCx-klientdrivrutin göra följande i ordning:

  1. Anropa NetDeviceInitConfig.

    status = NetDeviceInitConfig(DeviceInit);
    if (!NT_SUCCESS(status)) 
    {
        return status;
    }
    
  2. Anropa WdfDeviceSkapa.

    Tips/Råd

    Om enheten stöder mer än en NETADAPTER rekommenderar vi att du lagrar pekare till varje adapter i enhetskontexten.

  3. Skapa NETADAPTER-objektet. För att göra det anropar klienten NetAdapterInitAllocate, följt av valfria NetAdapterInitSetXxx-metoder för att initiera adapterns attribut. Slutligen anropar klienten NetAdapterCreate.

    I följande exempel visas hur en klientdrivrutin kan initiera ett NETADAPTER-objekt. Observera att felhanteringen förenklas i det här exemplet.

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

Du kan också lägga till kontextutrymme i NETADAPTER-objektet. Eftersom du kan ange en kontext för valfritt WDF-objekt kan du lägga till separat kontextutrymme för WDFDEVICE- och NETADAPTER-objekten. I exemplet i steg 3 lägger klienten till MY_ADAPTER_CONTEXT i NETADAPTER-objektet. Mer information finns i Kontextutrymme för ramverksobjekt.

Vi rekommenderar att du placerar enhetsrelaterade data i kontexten för din WDFDEVICE och nätverksrelaterade data, till exempel länkskiktsadresser i NETADAPTER-kontexten. Om du porterar en befintlig NDIS 6.x-drivrutin har du förmodligen en enda MiniportAdapterContext som kombinerar nätverksrelaterade och enhetsrelaterade data till en enda datastruktur. För att förenkla portningsprocessen konverterar du bara hela strukturen till WDFDEVICE-kontexten och gör NETADAPTER-kontexten till en liten struktur som pekar på WDFDEVICE-kontexten.

Du kan också ange två återanrop till metoden NET_ADAPTER_DATAPATH_CALLBACKS_INIT :

Mer information om vad du kan ange i dina implementeringar av dessa återanrop finns på de enskilda referenssidorna.

EVT_WDF_DEVICE_PREPARE_HARDWARE

Många NetAdapterCx-klientdrivrutiner startar sina kort inifrån sin EVT_WDF_DEVICE_PREPARE_HARDWARE återanropsfunktion, med det anmärkningsvärda undantaget klientdrivrutiner för mobile broadband-klasstillägg. Om du vill registrera en EVT_WDF_DEVICE_PREPARE_HARDWARE återanropsfunktion måste en NetAdapterCx-klientdrivrutin anropa WdfDeviceInitSetPnpPowerEventCallbacks.

I EVT_WDF_DEVICE_PREPARE_HARDWARE, förutom andra maskinvaruförberedelseuppgifter, anger klientdrivrutinen adapterns nödvändiga och valfria funktioner.

NetAdapterCx kräver att klientdrivrutinen anger följande funktioner:

Drivrutinen måste sedan anropa NetAdapterStart för att starta sin adapter.

I följande exempel visas hur en klientdrivrutin kan starta ett NETADAPTER-objekt. Observera att den kod som krävs för att konfigurera varje metod för adapterfunktioner utelämnas för korthet och tydlighet, och felhanteringen förenklas.

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