Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Cuando AllocateAdapterChannel transfiere el control a la rutina AdapterControl de un controlador, el controlador "posee" el controlador DMA del sistema y un conjunto de registros de mapa. A continuación, el controlador debe configurar el controlador DMA para una operación de transferencia, como se muestra en la ilustración siguiente.
Si el controlador tiene una rutina StartIo, AllocateAdapterChannel pasa un puntero a DeviceObject-CurrentIrp> en el parámetro PIrp a la rutina AdapterControl. Sin embargo, si el controlador administra su propia cola de IRP, el controlador debe incluir un puntero al IRP actual como parte del contexto que pasa a AdapterControl.
Como se muestra en la ilustración anterior, la rutina AdapterControl del controlador configura la transferencia DMA, como se indica a continuación:
La rutina AdapterControl obtiene la dirección en la que se inicia la transferencia. Para la transferencia inicial necesaria para satisfacer un IRP, la rutina AdapterControl llama a MmGetMdlVirtualAddress, pasando un puntero al MDL en Irp-MdlAddress>, que describe el búfer de esta transferencia DMA.
MmGetMdlVirtualAddress devuelve una dirección virtual que el controlador puede usar como índice para la dirección física del sistema donde se debe iniciar la transferencia.
Si el IRP requiere más de una operación de transferencia, el controlador calcula una dirección inicial actualizada, como se describe más adelante en esta sección.
La rutina AdapterControl guarda la dirección devuelta por MmGetMdlVirtualAddress o calculada en el paso 1. Esta dirección es un parámetro necesario (CurrentVa) para MapTransfer.
La rutina AdapterControl llama a MapTransfer para configurar el controlador DMA del sistema, proporcionando los parámetros siguientes:
Puntero de objeto de adaptador devuelto por IoGetDmaAdapter
Puntero (Mdl) al MDL en Irp-MdlAddress> para el IRP actual
El identificador MapRegisterBase pasado a la rutina AdapterControl del controlador por AllocateAdapterChannel
Valor (CurrentVa) devuelto por MmGetMdlVirtualAddress si se trata de la primera llamada a MapTransfer para irP
De lo contrario, el controlador proporciona un valor CurrentVa actualizado, que indica dónde debe iniciarse en el búfer la siguiente operación de transferencia.
Puntero a una variable (Length) que indica el número de bytes para esta transferencia
Si el controlador puede transferir todos los datos solicitados con una sola llamada a MapTransfer y no tiene restricciones específicas del dispositivo en sus operaciones DMA, Length se puede establecer en el valor de Length en la ubicación de pila de E/S del controlador del IRP. Como máximo, la longitud en bytes puede ser (PAGE_SIZE * los NumberOfMapRegisters devueltos por IoGetDmaAdapter). De lo contrario, el controlador debe dividir la solicitud, como se explica en Dividir solicitudes de transferencia y debe actualizar el valor de Length en llamadas posteriores a MapTransfer para el IRP actual.
Valor booleano (WriteToDevice), que indica la dirección de la operación de transferencia (TRUE para transferir datos de la memoria del sistema al dispositivo)
MapTransfer devuelve una dirección lógica. Los controladores que usan DMA del sistema deben omitir este valor.
La rutina AdapterControl configura el dispositivo para la operación DMA.
La rutina AdapterControl devuelve KeepObject.
Cuando el dispositivo indica que se ha completado su operación DMA actual, el controlador debe llamar a FlushAdapterBuffers, normalmente desde la rutina DpcForIsr del controlador.
La rutina DpcForIsr u otra rutina de controlador que completa una operación DMA llama a FlushAdapterBuffers para asegurarse de que los datos almacenados en caché en el controlador DMA del sistema se leen en la memoria del sistema o se escriben en el dispositivo. La misma rutina también debe llamar a MapTransfer de nuevo si es necesario volver a programar el controlador DMA del sistema para transferir más datos para el IRP actual. Del mismo modo, debe llamar a FlushAdapterBuffers de nuevo después de cada operación de transferencia.
Si un controlador debe llamar a MapTransfer más de una vez para el IRP actual, proporciona el mismo puntero de objeto de adaptador, puntero Mdl , identificador MapRegisterBase y dirección de transferencia en cada llamada. Sin embargo, el controlador debe actualizar los parámetros CurrentVa y Length antes de realizar la segunda y cualquier llamada posterior a MapTransfer. Para calcular un valor actualizado para cada uno de estos parámetros, use las fórmulas siguientes:
CurrentVa = CurrentVa + (Longitud solicitada en la llamada anterior a MapTransfer)
Length = Minimum ( longitud restante que se va a transferir, (PAGE_SIZE * NumberOfMapRegisters devuelto por IoGetDmaAdapter))
La información de contexto que cada controlador debe mantener sobre sus transferencias DMA depende de las necesidades de su dispositivo concreto. El contexto típico podría incluir la dirección virtual actual en MDL (CurrentVa), el número de bytes transferidos hasta ahora, el número de bytes restantes para transferir, posiblemente un puntero al IRP actual y cualquier otra información que el escritor de controladores considere útil.
Una vez completada la transferencia solicitada, o si el controlador debe devolver un estado de error para irP, el controlador debe llamar a FreeAdapterChannel rápidamente para liberar el controlador DMA del sistema para otros controladores y este controlador que se va a usar.