Dispersión/recopilación de DMA de NDIS
Precaución
En el caso de los procesadores Arm y Arm64, se recomienda encarecidamente que los escritores de controladores NDIS usen WDF DMA o WDM DMA en lugar de NDIS Scatter/Gather DMA.
Para obtener más información sobre WDF DMA, consulte Control de operaciones DMA en controladores kmdf.
Para obtener más información sobre WDM DMA, vea los temas secundarios relacionados con DMA de Administración de entradas y salidas para controladores.
Los controladores de minipuerto NDIS pueden usar el método Dispersión/Recopilación de DMA (SGDMA) para transferir datos entre una NIC y la memoria del sistema. Una transferencia de DMA correcta requiere que la dirección física de los datos esté en un intervalo de direcciones que admita la NIC. HAL proporciona un mecanismo para que los controladores obtengan la lista de direcciones físicas de una cadena MDL y, si es necesario, almacenarán en doble búfer los datos en un intervalo de direcciones físicos.
En las versiones de NDIS anteriores a NDIS 6.0, la compatibilidad con SGDMA en controladores de miniporte y NDIS está limitada en algunos aspectos y, en particular, no funciona bien en un escenario de envío de varios paquetes. La compatibilidad con SGDMA de NDIS 6.0 supera estas limitaciones, al tiempo que proporciona una interfaz sencilla para los controladores de minipuerto.
Historia de NDIS SGDMA
En las versiones de NDIS anteriores a NDIS 6.0, NDIS obtiene una lista de recopilación de dispersión (SG) para cada paquete antes de enviar el paquete al controlador de minipuerto. NDIS también controla el caso en el que se produce un error en el intento original de obtener la lista de SG debido a una fragmentación excesiva. En este caso, NDIS almacena en búfer doble el paquete en un búfer contiguo e intenta de nuevo. HAL también puede almacenar en doble búfer los datos en una dirección física que admite la NIC si, por ejemplo, la dirección física de los datos está por encima del máximo de 32 bits y la NIC no admite DMA de 64 bits.
Para evitar una situación de interbloqueo, NDIS obtiene una lista de SG para un paquete y envía un paquete a la vez. Si NDIS intenta asignar todos los paquetes antes de enviarlos al controlador de minipuerto, el sistema podría agotar los recursos. En este caso, NDIS esperaría a que los registros de mapa estuvieran disponibles mientras algunos registros de mapa están bloqueados para los paquetes que no se han enviado. No se pueden reutilizar los paquetes bloqueados.
Este enfoque para la compatibilidad con SGDMA tiene las siguientes limitaciones:
Dado que el paquete se asigna antes de que llegue al controlador de minipuerto, el controlador no puede optimizarse para paquetes pequeños o paquetes demasiado fragmentados. El controlador de minipuerto no puede duplicar el búfer del paquete en una dirección física conocida.
No hay ninguna garantía de que la matriz de direcciones físicas que NDIS pasa al controlador de miniporte se asigna a la dirección virtual de los datos originales. Por lo tanto, si el controlador cambia los datos en la dirección virtual de la cadena MDL antes de enviarlos, las modificaciones realizadas en los datos no se reflejan en los datos de las direcciones físicas. En este caso, la NIC envía los datos sin modificar.
NDIS se limita al envío de un paquete a la vez para evitar un interbloqueo debido a problemas de recursos. Esto no es tan eficaz como enviar varios paquetes.
Dado que NDIS no puede determinar las capacidades de transmisión de los controladores de minipuerto, no puede preasignar el almacenamiento para un búfer de lista de SG. Por lo tanto, NDIS debe asignar el almacenamiento necesario en tiempo de ejecución. Esto no es tan eficaz como la asignación previa del almacenamiento.
Las funciones HAL que asignan una lista de SG deben llamarse en IRQL = DISPATCH_LEVEL. NDIS no tiene la información de IRQL actual, por lo que debe establecer IRQL en DISPATCH_LEVEL incluso si ya está en DISPATCH_LEVEL. Esto no es eficaz si el IRQL ya está en DISPATCH_LEVEL.
Ventajas de la compatibilidad con NDIS SGDMA
En la interfaz NDIS 6.0 y versiones posteriores de SGDMA, NDIS no asigna el búfer de datos antes de enviarlo al controlador de minipuerto. En su lugar, NDIS proporciona una interfaz para que el controlador asigne los datos de red.
Este enfoque produce las siguientes ventajas:
Dado que NDIS proporciona la interfaz a HAL para asignar los datos de red, los controladores de minipuerto de NDIS a partir de la complejidad y los detalles del proceso de asignación.
Los controladores de minipuerto tienen acceso a los datos antes de asignarlos. Por lo tanto, los cambios realizados en los datos originales se reflejan en los datos representados por la lista sg, incluso si NDIS o HAL almacenan en búfer los datos.
Los controladores de minipuerto pueden optimizar la transmisión de paquetes pequeños o muy fragmentados copiandolos en un búfer preasignado con una dirección física conocida. Este enfoque evita la asignación que no es necesaria y, por tanto, mejora el rendimiento del sistema.
NDIS puede enviar varios búferes al controlador de miniporte de forma segura. Esto da como resultado menos llamadas a controladores de minipuerto y, por lo tanto, mejora el rendimiento del sistema.
Los controladores de minipuerto pueden asignar previamente la memoria de una lista de SG como parte de los bloques de descriptores de transmisión. Por lo tanto, los controladores NDIS o miniport no son necesarios para asignar memoria para las listas de SG en tiempo de ejecución.
Dado que los controladores de minipuerto se pueden ejecutar en IRQL = DISPATCH_LEVEL, los controladores de minipuerto pueden evitar llamadas innecesarias para elevar IRQL a DISPATCH_LEVEL. Por ejemplo, dado que la finalización de un envío se produce en el contexto de una DPC de interrupción, los controladores de minipuerto pueden liberar la lista sg sin generar irQL.
Registro y anulación del registro de canales DMA
Un controlador de miniporte NDIS llama a la función NdisMRegisterScatterGatherDma desde su función MiniportInitializeEx para registrar un canal DMA con NDIS.
El controlador de minipuerto pasa una descripción de DMA a NdisMRegisterScatterGatherDma en el parámetro DmaDescription . NdisMRegisterScatterGatherDma devuelve un tamaño para el búfer que debe ser lo suficientemente grande como para contener la lista de dispersión y recopilación. Los controladores de minipuerto deben usar este tamaño para preasignar el almacenamiento para las listas de dispersión y recopilación.
El controlador de minipuerto también pasa NdisMRegisterScatterGatherDma los puntos de entrada de las funciones MiniportXxx que NDIS llama para procesar la lista de dispersión y recopilación. NDIS llama a la función MiniportProcessSGList del controlador de miniporte después de que HAL haya creado la lista de dispersión y recopilación para un búfer. NdisMRegisterScatterGatherDma proporciona un identificador en el parámetro pNdisMiniportDmaHandle , que el controlador de minipuerto debe usar en llamadas posteriores a funciones de dispersión o recopilación de DMA de NDIS.
Un controlador de miniporte de NDIS llama a la función NdisMDeregisterScatterGatherDma desde su función MiniportHaltEx para liberar recursos de dispersión y recopilación de DMA.
Asignar y liberar listas de dispersión y recopilación
Un controlador de miniporte NDIS llama a la función NdisMAllocateNetBufferSGList en su función MiniportSendNetBufferLists . El controlador de minipuerto llama a NdisMAllocateNetBufferSGList una vez para cada estructura NET_BUFFER que debe asignar. Una vez que los recursos estén disponibles y HAL tenga lista de SG lista lista, NDIS llama a la función MiniportProcessSGList del controlador. NDIS puede llamar a MiniportProcessSGList antes o después de la llamada del controlador de miniporte a NdisMAllocateNetBufferSGList .
Para mejorar el rendimiento del sistema, la lista de dispersión y recopilación se genera a partir de los datos de red que comienzan al principio de la MDL que se especifica en el miembro CurrentMdl de la estructura de NET_BUFFER_DATA asociada. El inicio de los datos de red de la lista SG se desplaza desde el principio de la lista sg por el valor especificado en el miembro CurrentMdlOffset de la estructura de NET_BUFFER_DATA asociada.
Mientras controla un DPC para una interrupción de envío completa y, después de que el controlador de minipuerto no necesite la lista sg, el controlador de minipuerto debe llamar a la función NdisMFreeNetBufferSGList para liberar la lista sg.
Nota No llame a NdisMFreeNetBufferSGList mientras el controlador o hardware sigue teniendo acceso a la memoria descrita por la estructura de NET_BUFFER asociada a la lista de dispersión y recopilación.
Antes de acceder a los datos recibidos, los controladores de minipuerto deben llamar a NdisMFreeNetBufferSGList para vaciar la memoria caché.