Coordinación de solicitudes de E/S con estado de energía de componente
[Solo se aplica a KMDF]
Un controlador KMDF para un dispositivo de varios componentes solo debe enviar solicitudes a componentes que estén en un estado activo. Normalmente, el controlador asigna colas de E/S a componentes o conjuntos de componentes.
Considere primero una cola asignada a un único componente. El controlador inicia la cola cuando el componente se activa y detiene la cola cuando el componente deja de estar inactivo. Por lo tanto, cuando KMDF llama a un controlador de solicitudes para la cola, el dispositivo está en su estado completo en (D0) y el componente necesario está activo. El controlador de solicitudes puede acceder de forma segura al hardware de los componentes.
El mismo concepto se aplica a una cola que se asigna a un conjunto de componentes. En este caso, el controlador inicia la cola cuando todos los componentes del conjunto están activos. El controlador detiene la cola cuando alguno de los componentes deja de estar inactivo.
En este tema se describe cómo un controlador KMDF para un dispositivo de varios componentes podría implementar dicha compatibilidad en una situación que implica varios tipos de solicitud que requieren diferentes combinaciones de componentes.
Ejemplo
Para cada tipo de solicitud admitido por el controlador, identifique los componentes necesarios. Por ejemplo, considere un dispositivo que tenga tres componentes: 0, 1 y 2, para los que el controlador recibe tres tipos de solicitudes: A, B y C. Los requisitos de componente de las solicitudes son los siguientes:
Tipo de solicitud | Componentes necesarios |
---|---|
A | 0,2 |
B | 1 |
C | 0,1,2 |
En este ejemplo, hay tres conjuntos distintos de componentes, uno para cada tipo de solicitud. El controlador proporciona una cola de E/S administrada por energía predeterminada para el dispositivo, así como una cola administrada por energía adicional correspondiente a cada conjunto de componentes. En el ejemplo anterior, el controlador crea una cola principal y tres colas secundarias, una correspondiente a cada conjunto de componentes. Esta configuración de cola se muestra en el diagrama siguiente:
El controlador mantiene una máscara de bits para cada conjunto de componentes. Cada bit de la máscara de bits representa el estado activo/inactivo de uno de los componentes. Si se establece el bit, el componente está activo. Si se borra el bit, el componente está inactivo.
Cuando llega una solicitud, un controlador de solicitudes para la cola de nivel superior determina qué componentes necesita la solicitud y llama a PoFxActivateComponent para cada uno. A continuación, el controlador de solicitudes reenvía la solicitud a la cola de E/S secundaria correspondiente al conjunto de ese componente.
Cuando un componente se activa, el marco de administración de energía (PoFx) llama a la rutina ComponentActiveConditionCallback del controlador. En esta devolución de llamada, el controlador establece el bit correspondiente al componente especificado, en cada máscara de bits donde se representa ese componente. Si se establecen todos los bits de una máscara de bits determinada, todos los componentes del conjunto correspondiente están activos. Para cada conjunto de componentes que esté totalmente activo, el controlador llama a WdfIoQueueStart para iniciar la cola de E/S secundaria correspondiente.
Por ejemplo, considere el dispositivo hipotético anterior. Supongamos que el componente 0 está activo, mientras que los componentes 1 y 2 están inactivos. Cuando el componente 2 se activa, PoFx llama a la rutina ComponentActiveConditionCallback de ese componente. Los tipos de solicitud A y C usan el componente 2, por lo que el controlador manipula las máscaras de bits para estos dos tipos de solicitud. Dado que ahora se establecen todos los bits de la máscara de bits para el tipo de solicitud A, el controlador inicia la cola para el tipo de solicitud A. Sin embargo, no todos los bits se establecen para el tipo de solicitud C (el componente 1 sigue inactivo). El controlador no inicia la cola para el tipo de solicitud C.
Cuando se inicia una cola de E/S secundaria, el marco comienza a entregar las solicitudes almacenadas en la cola. En el controlador de solicitudes de la cola de E/S secundaria, el controlador puede procesar de forma segura las solicitudes porque el componente está activo y se ha tomado una referencia de energía en el componente para cada una de las solicitudes.
Cuando el controlador finaliza el procesamiento de una solicitud, llama a PoFxIdleComponent para cada componente que la solicitud estaba usando y, a continuación, completa la solicitud. Cuando no hay más solicitudes mediante un componente, power Framework llama a la rutina ComponentIdleConditionCallback del controlador.
En esta devolución de llamada, el controlador borra el bit correspondiente al componente especificado, en cada máscara de bits donde se representa ese componente. Si una máscara de bits determinada indica que el componente es el primero del conjunto correspondiente para realizar la transición a la condición de inactividad, el controlador llama a WdfIoQueueStop para detener la cola de E/S secundaria correspondiente. Al hacerlo, el controlador garantiza que la cola no envía solicitudes a menos que todos los componentes del conjunto correspondiente estén activos.
Considere de nuevo el ejemplo anterior. Supongamos que todos los componentes están activos y, por tanto, se inician todas las colas. Cuando el componente 1 deja de estar inactivo, PoFx llama a la rutina ComponentIdleConditionCallback para el componente 1. En esta devolución de llamada, el controlador manipula las máscaras de bits para los tipos de solicitud B y C porque usan el componente 1. Dado que el componente 1 es el primer componente que se va a quedar inactivo para estos tipos de solicitud, el controlador detiene las colas para los tipos de solicitud B y C.
Supongamos que, en este momento, el componente 0 se vuelve inactivo. En ComponentIdleConditionCallback para el componente 0, el controlador manipula las máscaras de bits para los tipos de solicitud A y C. Dado que el componente 0 es el primer componente en estar inactivo para el tipo de solicitud A (el componente 2 sigue activo), el controlador detiene la cola para el tipo de solicitud A. Sin embargo, para el tipo de solicitud C, el componente 0 no es el primer componente para quedar inactivo. El controlador no detiene la cola para el tipo de solicitud C (lo hizo anteriormente).
Para usar la técnica descrita en este ejemplo, el controlador también debe registrar una función de devolución de llamada EvtIoCanceledOnQueue para cada una de sus colas secundarias. Si se cancelara una solicitud mientras se encontraba en la cola secundaria, el controlador podría usar esta devolución de llamada para llamar a PoFxIdleComponent para cada componente correspondiente. Al hacerlo, libera la referencia de energía que tomó el controlador de solicitudes cuando llamó a PoFxActivateComponent antes de reenviar la solicitud a la cola secundaria.