Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Cuidado
Para processadores Arm e Arm64, é altamente recomendável que os desenvolvedores de drivers NDIS utilizem DMA do WDF ou DMA do WDM em vez de DMA Scatter/Gather do NDIS.
Para obter mais informações sobre o DMA do WDF, consulte tratando operações de DMA em drivers KMDF.
Para obter mais informações sobre o DMA do WDM, consulte os tópicos filho relacionados ao DMA de gerenciamento de entrada/saída para drivers.
Os drivers de miniporto NDIS podem usar o método SGDMA (Scatter/Gather DMA) para transferir dados entre uma NIC e a memória do sistema. Uma transferência de DMA bem-sucedida requer que o endereço físico dos dados esteja em um intervalo de endereços compatível com a NIC. O HAL fornece um mecanismo para que os drivers obtenham a lista de endereços físicos para uma cadeia de MDL e, se necessário, utilizará buffer duplo nos dados em um intervalo de endereços físicos.
Em versões do NDIS anteriores ao NDIS 6.0, o suporte a SGDMA em drivers de miniport e NDIS é limitado em alguns aspectos e, em particular, não funciona bem em um cenário de envio de vários pacotes. O suporte ao SGDMA do NDIS 6.0 supera essas limitações, fornecendo uma interface simples para drivers de miniport.
Histórico do SGDMA do NDIS
Em versões do NDIS anteriores ao NDIS 6.0, o NDIS obtém uma lista de coleta de dispersão (SG) para cada pacote antes de enviar o pacote para o driver de miniport. O NDIS também exerce a função de lidar com o caso em que a tentativa inicial de obter a lista de SG falha devido à fragmentação excessiva. Nesse caso, o NDIS armazena o pacote em buffer duplo em um buffer contíguo e tenta novamente. HAL também pode realizar buffer duplo nos dados em um endereço físico que a NIC suporta se, por exemplo, o endereço físico dos dados for superior ao limite de 32 bits e a NIC não oferecer suporte a DMA de 64 bits.
Para evitar uma situação de deadlock, o NDIS obtém uma lista SG para um pacote e envia um pacote por vez. Se o NDIS tentar mapear todos os pacotes antes de enviá-los para o driver de miniporto, o sistema poderá esgotar os recursos. Nesse caso, o NDIS estaria aguardando que os registros de mapa ficassem disponíveis enquanto alguns registros de mapa são bloqueados para os pacotes que não foram enviados. Os pacotes bloqueados não podem ser reutilizados.
Essa abordagem para o suporte ao SGDMA tem as seguintes limitações:
Como o pacote é mapeado antes de chegar ao driver de miniporto, o driver não pode otimizar para pacotes pequenos ou pacotes muito fragmentados. O driver de miniporto não pode fazer buffer duplo do pacote em um endereço físico conhecido.
Não há garantia de que a matriz de endereços físicos que o NDIS passou para o miniport driver corresponde ao endereço virtual dos dados originais. Portanto, se o driver alterar os dados no endereço virtual na cadeia de MDL antes de enviá-los, as modificações feitas nos dados não serão refletidas nos dados nos endereços físicos. Nesse caso, a NIC envia os dados não modificados.
O NDIS é limitado ao envio de um pacote por vez para evitar um deadlock devido a problemas de recurso. Isso não é tão eficiente quanto enviar vários pacotes.
Como o NDIS não pode determinar as capacidades de transmissão dos drivers miniport, ele não pode pré-alocar o armazenamento para um buffer de lista SG. Portanto, o NDIS deve alocar o armazenamento necessário em tempo de execução. Isso não é tão eficiente quanto pré-alocar o armazenamento.
As funções HAL que alocam uma lista SG devem ser chamadas em IRQL = DISPATCH_LEVEL. O NDIS não possui as informações atuais do IRQL, portanto, precisa ajustar o IRQL para DISPATCH_LEVEL mesmo que já esteja nesse nível. Isso não será eficiente se o IRQL já estiver em DISPATCH_LEVEL.
Benefícios do suporte do NDIS para SGDMA
Na interface SGDMA do NDIS 6.0 e versões posteriores, o NDIS não mapeia o buffer de dados antes de enviá-lo para o driver de miniport. Em vez disso, o NDIS fornece uma interface para o driver mapear os dados de rede.
Essa abordagem gera os seguintes benefícios:
Como o NDIS fornece a interface para HAL mapear os dados de rede, o NDIS protege os drivers de miniporta da complexidade e dos detalhes do processo de mapeamento.
Os drivers de miniport têm acesso aos dados antes de serem mapeados. Portanto, todas as alterações feitas nos dados originais são refletidas nos dados representados pela lista de SG, mesmo que o NDIS ou o HAL faça o buffering duplo dos dados.
Os drivers de miniport podem otimizar a transmissão de pacotes pequenos ou altamente fragmentados copiando-os para um buffer pré-alocado com um endereço físico conhecido. Essa abordagem evita o mapeamento que não é necessário e, portanto, melhora o desempenho do sistema.
O NDIS pode enviar vários buffers para o miniport driver com segurança. Isso resulta em menos chamadas para drivers de miniport e, portanto, melhora o desempenho do sistema.
Os drivers de miniport podem pré-alocar a memória de uma lista SG como parte dos blocos de descritor de transmissão. Portanto, não é necessário que os drivers NDIS ou miniport alocem memória para listas de SG em tempo de execução.
Como os drivers de miniporto podem estar em execução em IRQL = DISPATCH_LEVEL, os drivers de miniport podem evitar chamadas desnecessárias para elevar o IRQL para DISPATCH_LEVEL. Por exemplo, como a conclusão de um envio ocorre no contexto de uma interrupção de DPC, os drivers de miniporto podem liberar a lista SG sem elevar o IRQL.
Registrando e desregistrando canais de DMA
Um driver de miniporto NDIS chama a função NdisMRegisterScatterGatherDma de sua função MiniportInitializeEx para registrar um canal DMA com NDIS.
O driver de miniporta passa uma descrição de DMA para NdisMRegisterScatterGatherDma no parâmetro DmaDescription. NdisMRegisterScatterGatherDma retorna um tamanho para o buffer que deve ser grande o suficiente para conter a lista de dispersão/coleta. Os drivers de miniport devem usar esse tamanho para pré-alocar o armazenamento para listas de dispersão/coleta.
O driver de miniporto também passa NdisMRegisterScatterGatherDma os pontos de entrada para as funções MiniportXxx que o NDIS chama para processar a lista de dispersão/coleta. O NDIS chama a função MiniportProcessSGList do driver de miniport depois que HAL criou a lista de dispersão/coleta para um buffer. NdisMRegisterScatterGatherDma fornece um identificador no parâmetro pNdisMiniportDmaHandle , que o driver de miniporto deve usar em chamadas subsequentes para funções DMA de dispersão/coleta de NDIS.
Um driver de miniporto NDIS chama a função NdisMDeregisterScatterGatherDma de sua função MiniportHaltEx para liberar recursos de dispersão/coleta de DMA.
Alocando e liberando listas de dispersão/coleta
Um driver de miniporto NDIS chama a função NdisMAllocateNetBufferSGList em sua função MiniportSendNetBufferLists. O driver de miniporto chama NdisMAllocateNetBufferSGList uma vez para cada estrutura NET_BUFFER que ele deve mapear. Depois que os recursos estiverem disponíveis e o HAL tiver a lista de SG pronta, o NDIS chamará a função MiniportProcessSGList do driver. O NDIS pode chamar MiniportProcessSGList antes ou depois que a chamada do driver de miniporto para NdisMAllocateNetBufferSGList retornar.
Para melhorar o desempenho do sistema, a lista de dispersão/coleta é gerada a partir dos dados de rede começando no início do MDL especificado no membro CurrentMdl da estrutura de NET_BUFFER_DATA associada. O início dos dados de rede na lista SG é deslocado do início da lista SG pelo valor especificado no membro CurrentMdlOffset da estrutura NET_BUFFER_DATA associada.
Ao manipular um DPC para uma interrupção completa de envio e depois que o driver de miniport não precisar mais da lista de SG, o driver de miniporto deve chamar a função NdisMFreeNetBufferSGList para liberar a lista SG.
Nota Não chame NdisMFreeNetBufferSGList enquanto o driver ou hardware ainda estiver acessando a memória descrita pela estrutura NET_BUFFER associada à lista de dispersão/coleta.
Antes de acessar os dados recebidos, os drivers de miniport devem chamar NdisMFreeNetBufferSGList para liberar o cache de memória.