Uso de dispersión y recopilación de DMA
Los controladores que realizan DMA basado en paquetes o sistema o bus pueden usar rutinas de soporte diseñadas especialmente para la dispersión y recopilación de DMA. En lugar de llamar a la secuencia de rutinas descritas en Using Packet-Based System DMA and Packet-Based Bus-Master DMA, un controlador puede usar GetScatterGatherList y PutScatterGatherList.
No es necesario que un dispositivo tenga compatibilidad integrada de dispersión o recopilación para que su controlador use estas rutinas.
Los controladores que usan DMA basado en paquetes llaman a la siguiente secuencia general de rutinas de soporte técnico para las operaciones de dispersión y recopilación:
MmGetMdlVirtualAddress para obtener un índice en MDL, necesario como parámetro en la llamada a GetScatterGatherList
GetScatterGatherList cuando el controlador está listo para programar su dispositivo para DMA y necesita el controlador DMA del sistema o el adaptador de bus-master
GetScatterGatherList asigna el controlador DMA del sistema o el adaptador bus-master, determina cuántos registros de mapa son necesarios y los asigna, rellena la lista de dispersión y recopilación, y llama a la rutina AdapterListControl del controlador cuando el controlador DMA o el adaptador y los registros de mapa están disponibles.
PutScatterGatherList tan pronto como se hayan transferido todos los datos solicitados o el controlador produce un error irP debido a un error de E/S del dispositivo.
PutScatterGatherList vacía los búferes del adaptador, libera los registros de mapa y libera la lista de dispersión y recopilación. El controlador debe llamar a PutScatterGatherList para poder acceder a los datos del búfer.
El puntero de objeto de adaptador devuelto por IoGetDmaAdapter es un parámetro obligatorio para cada una de estas rutinas, excepto MmGetMdlVirtualAddress, que requiere un puntero a MDL en Irp-MdlAddress>.
La rutina GetScatterGatherList incluye llamadas a AllocateAdapterChannel y MapTransfer, por lo que el controlador no tiene que realizar estas llamadas. La rutina toma lo siguiente como parámetros:
Puntero a la estructura DMA_ADAPTER devuelta por IoGetDmaAdapter
Puntero al objeto de dispositivo de destino para la operación DMA.
Puntero al MDL que describe el búfer en Irp-MdlAddress>
Puntero a la dirección virtual actual en el búfer descrito por Mdl.
Número de bytes que se van a asignar
Puntero a una rutina AdapterListControl que realiza la transferencia
Puntero a un área de contexto definida por el controlador que se va a pasar a la rutina AdapterListControl .
Valor booleano: TRUE para una transferencia al dispositivo; False en caso contrario
Después de determinar el número de registros de mapa necesarios, asignar el canal de adaptador y los registros de mapa, rellenar la lista de dispersión y recopilación y preparar la transferencia, GetScatterGatherList llama a la rutina AdapterListControl proporcionada por el controlador. La rutina AdapterListControl se ejecuta en un contexto de subproceso arbitrario en IRQL = DISPATCH_LEVEL.
La rutina AdapterListControl que proporciona un controlador en las llamadas a GetScatterGatherList difiere de la rutina AdapterControl pasada a AllocateAdapterChannel en los siguientes aspectos importantes:
La rutina AdapterListControl no tiene ningún valor devuelto, mientras que la rutina AdapterControl devuelve un IO_ALLOCATION_ACTION.
En lugar de un puntero a MapRegisterBase para los registros de mapa asignados por el sistema, el tercer parámetro a una rutina AdapterListControl apunta en su lugar a una estructura SCATTER_GATHER_LIST a través de la cual el controlador puede realizar DMA.
La rutina AdapterListControl realiza un subconjunto de las tareas necesarias en una rutina AdapterControl .
La rutina AdapterListControl no llama a AllocateAdapterChannel ni MapTransfer. Sus únicas responsabilidades son guardar el puntero de lista de dispersión y recopilación de entrada, configurar su dispositivo y usar la lista de dispersión y recopilación para realizar DMA.
La estructura de lista de dispersión y recopilación incluye una matriz de SCATTER_GATHER_ELEMENT y el número de elementos de la matriz. Cada elemento de la matriz proporciona la longitud y la dirección física inicial de una región de dispersión o recopilación físicamente contigua. Un controlador usa la longitud y la dirección en las transferencias de datos.
Un controlador puede usar GetScatterGatherList independientemente de si su dispositivo admite DMA de dispersión o recopilación. En el caso de un dispositivo que no admite la dispersión o recopilación de DMA, la lista de dispersión y recopilación solo contendrá un elemento.
El uso de las rutinas de dispersión y recopilación puede mejorar el rendimiento mediante una llamada a AllocateAdapterChannel (como se ha descrito anteriormente en Uso de DMA del sistema Packet-Based y Uso de Packet-Based Bus-Master DMA). A diferencia de las llamadas a AllocateAdapterChannel, se puede poner en cola más de una llamada a GetScatterGatherList para un objeto de dispositivo en cualquier momento. Un controlador puede llamar a GetScatterGatherList de nuevo para otra operación DMA en el mismo objeto de controlador antes de que su rutina AdapterListControl haya completado la ejecución.
A cambio de la rutina AdapterListControl proporcionada por el controlador, GetScatterGatherList mantiene los registros del mapa, pero libera la estructura del adaptador DMA.
Cuando el controlador ha satisfecho la solicitud de transferencia del IRP actual o debe producir un error irP debido a un error de E/S de dispositivo o bus, debe llamar a PutScatterGatherList para poder acceder a los datos transferidos en el búfer. PutScatterGatherList vacía los búferes del adaptador y libera los registros de mapa y la lista de dispersión y recopilación.