Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
[Aplica-se apenas ao KMDF]
Um driver KMDF para um dispositivo de vários componentes só deve enviar solicitações para componentes que estão em um estado ativo. Normalmente, o driver atribui filas de E/S a componentes ou conjuntos de componentes.
Considere primeiro uma fila atribuída a um único componente. O driver inicia a fila quando o componente se torna ativo e para a fila quando o componente fica ocioso. Como tal, quando o KMDF chama um gestor de pedidos para a fila, o dispositivo está no seu estado totalmente ativado (D0) e o componente necessário está ativo. O manipulador de solicitações pode acessar com segurança o hardware do componente.
O mesmo conceito se aplica a uma fila atribuída a um conjunto de componentes. Nesse caso, o driver inicia a fila quando todos os componentes do conjunto estão ativos. O controlador pára a fila quando qualquer um dos componentes fica ocioso.
Este tópico descreve como um driver KMDF para um dispositivo de vários componentes pode implementar esse suporte em uma situação que envolve vários tipos de solicitação que exigem diferentes combinações de componentes.
Exemplo
Para cada tipo de solicitação suportado pelo driver, identifique os componentes necessários. Por exemplo, considere um dispositivo que tenha três componentes: 0, 1 e 2, para o qual o driver recebe três tipos de solicitações: A, B e C. Os requisitos de componentes das solicitações são os seguintes:
| Tipo de pedido | Componentes necessários |
|---|---|
| A | 0,2 |
| B | 1 |
| C | 0,1,2 |
Neste exemplo, há três conjuntos distintos de componentes, um para cada tipo de solicitação. O driver fornece uma fila de E/S padrão gerenciada por energia para o dispositivo, bem como uma fila adicional de energia gerenciada correspondente a cada conjunto de componentes. No exemplo acima, o driver cria uma fila primária e três filas secundárias, uma correspondente a cada conjunto de componentes. Essa configuração de fila é mostrada no diagrama a seguir:
O driver mantém uma máscara de bits para cada conjunto de componentes. Cada bit na máscara de bits representa o estado ativo/ocioso de um dos componentes. Se o bit estiver definido, o componente estará ativo. Se o bit for desativado, o componente ficará ocioso.
Quando uma solicitação chega, um manipulador de solicitações para a fila de nível superior determina quais componentes a solicitação precisa e chama PoFxActivateComponent para cada um. Em seguida, o manipulador de solicitações encaminha a solicitação para a fila de E/S secundária correspondente ao conjunto desse componente.
Quando um componente se torna ativo, a estrutura de gestão de energia (PoFx) chama a rotina ComponentActiveConditionCallbackdo driver. Neste callback, o driver define o bit correspondente ao componente especificado em cada máscara onde esse componente é representado. Se todos os bits em uma determinada máscara de bits estiverem definidos, todos os componentes no conjunto correspondente estarão ativos. Para cada conjunto de componentes totalmente ativo, o driver chama WdfIoQueueStart para iniciar a fila de E/S secundária correspondente.
Por exemplo, considere o dispositivo hipotético acima. Suponha que o componente 0 esteja ativo, enquanto os componentes 1 e 2 estejam ociosos. Quando o componente 2 se torna ativo, o PoFx invoca a rotina ComponentActiveConditionCallback desse componente. Os tipos de solicitação A e C usam o componente 2, portanto, o driver manipula as máscaras de bits para esses dois tipos de solicitação. Como todos os bits na máscara de bits para o tipo de solicitação A agora estão definidos, o driver inicia a fila para o tipo de solicitação A. No entanto, nem todos os bits estão definidos para o tipo de solicitação C (o componente 1 ainda está ocioso). O controlador não inicia a fila para o tipo de pedido C.
Quando uma fila de E/S secundária é iniciada, a estrutura começa a entregar as solicitações armazenadas na fila. No gestor de pedidos para a fila de E/S secundária, o driver pode processar os pedidos com segurança porque o componente está ativo e foi estabelecida uma referência de potência no componente para cada um dos pedidos.
Quando o driver termina de processar uma solicitação, ele chama PoFxIdleComponent para cada componente que a solicitação estava usando e, em seguida, conclui a solicitação. Quando não há mais solicitações usando um componente, a estrutura de energia chama a rotina ComponentIdleConditionCallbackdo driver.
Nesta função de retorno, o driver limpa o bit correspondente ao componente especificado, em cada máscara de bits onde esse componente é representado. Se uma determinada máscara de bits indicar que o componente é o primeiro no conjunto correspondente a realizar a transição para o estado de inatividade, o driver chamará WdfIoQueueStop para interromper a fila secundária de entrada/saída correspondente. Ao fazer isso, o driver garante que a fila de espera não processe solicitações, a menos que todos os componentes no conjunto correspondente estejam ativos.
Considere novamente o exemplo acima. Suponha que todos os componentes estejam ativos e que, portanto, todas as filas sejam iniciadas. Quando o componente 1 se torna ocioso, o PoFx chama a rotina ComponentIdleConditionCallback para o componente 1. Neste retorno de chamada, o condutor manipula as máscaras de bits para os tipos de pedido B e C, já que ambos utilizam o componente 1. Como o componente 1 é o primeiro componente a ficar ocioso para ambos os tipos de solicitação, o driver interrompe as filas para os tipos de solicitação B e C.
Suponha que, neste ponto, o componente 0 fique ocioso. NoComponentIdleConditionCallback para o componente 0, o driver manipula as máscaras de bits para os tipos de solicitação A e C. Como o componente 0 é o primeiro componente a ficar ocioso para o tipo de solicitação A (o componente 2 ainda está ativo), o driver interrompe a fila para o tipo de solicitação A. No entanto, para o tipo de solicitação C, o componente 0 não é o primeiro componente a ficar ocioso. O condutor não para a fila para requisição tipo C (já o fez anteriormente).
Para usar a técnica descrita neste exemplo, o driver deve também registar uma função de retorno de chamada EvtIoCanceledOnQueue para cada uma das suas filas secundárias. Se uma solicitação fosse cancelada enquanto estava na fila secundária, o driver poderia usar este retorno de chamada para chamar PoFxIdleComponent para cada componente correspondente. Isso libera a referência de energia que o manipulador de solicitações tomou ao chamar PoFxActivateComponent antes de encaminhar a solicitação para a fila secundária.