Iniciando um dispositivo em um driver de função

Um driver de função define uma rotina IoCompletion , passa uma solicitação IRP_MN_START_DEVICE para baixo na pilha do dispositivo e adia suas operações de início até que todos os drivers inferiores tenham terminado com o IRP. Consulte Adiando o processamento de PnP IRP até que drivers inferiores sejam concluídos para obter informações detalhadas sobre como usar um evento de kernel e uma rotina IoCompletion para adiar o processamento de IRP.

Quando sua rotina DispatchPnP recupera o controle depois que todos os drivers inferiores terminarem com o IRP, o driver de função executará suas tarefas para iniciar o dispositivo. Um driver de função inicia o dispositivo com um procedimento semelhante ao seguinte:

  1. Se um driver inferior falhou no IRP (IoCallDriver retornou um erro), não continue processando o IRP. Faça qualquer limpeza necessária e retorne da rotina DispatchPnP (vá para a última etapa nesta lista).

  2. Se drivers inferiores processarem o IRP com êxito, inicie o dispositivo.

    As etapas exatas para iniciar um dispositivo variam de dispositivo para dispositivo. Essas etapas podem incluir mapeamento de espaço de E/S, inicialização de registros de hardware, definição do dispositivo no estado de energia D0 e conexão da interrupção com IoConnectInterrupt. Se o driver estiver reiniciando um dispositivo após uma solicitação de IRP_MN_STOP_DEVICE , o driver poderá ter o estado do dispositivo para restaurar.

    O dispositivo deve ser ligado antes que qualquer driver possa acessá-lo. Consulte Ligar um dispositivo para obter mais informações.

    Se o dispositivo deve ser habilitado para ativação, seu proprietário da política de energia (geralmente o driver de função) deve enviar um IRP de espera/ativação depois de ligar o dispositivo e antes de concluir a solicitação de IRP_MN_START_DEVICE . Para obter detalhes, consulte Enviando um IRP de espera/ativação.

  3. Inicie OS IRPs na fila de retenção de IRP.

    Limpe o sinalizador de HOLD_NEW_REQUESTS definido pelo driver e inicie os IRPs na fila de retenção de IRP. Os drivers devem fazer isso ao iniciar um dispositivo pela primeira vez e ao reiniciar um dispositivo após uma parada de consulta ou parar o IRP. Consulte Mantendo IRPs de entrada quando um dispositivo está em pausa para obter mais informações.

  4. [Opcional] Habilite interfaces para o dispositivo chamando IoSetDeviceInterfaceState.

    Habilite as interfaces, se houver, que o driver registrou anteriormente em sua rotina AddDevice (ou em um INF ou por outro componente, como um co-instalador).

    No Windows 2000 e versões posteriores do Windows, o gerenciador PnP não envia notificação de chegadas da interface do dispositivo até que o IRP_MN_START_DEVICE IRP seja concluído, indicando que todos os drivers do dispositivo concluíram suas operações de início. O gerenciador PnP também falha em todas as solicitações de criação que chegam antes que todos os drivers do dispositivo concluam o IRP inicial.

  5. Conclua o IRP.

    A rotina IoCompletion do driver de função retornou STATUS_MORE_PROCESSING_REQUIRED, conforme descrito em Adiando o processamento de IRP PnP até que os drivers inferiores terminem, de modo que a rotina DispatchPnP do driver de função deve chamar IoCompleteRequest para retomar o processamento de conclusão de E/S.

    Se as operações de início do driver de função tiverem sido bem-sucedidas, o driver definirá Irp-IoStatus.Status> como STATUS_SUCCESS, chamará IoCompleteRequest com um aumento de prioridade de IO_NO_INCREMENT e retornará STATUS_SUCCESS de sua rotina DispatchPnP.

    Se o driver de função encontrar um erro durante suas operações de início, o driver definirá um erro status no IRP, chamará IoCompleteRequest com IO_NO_INCREMENT e retornará o erro de sua rotina DispatchPnP.

    Se um driver inferior falhou no IRP (IoCallDriver retornou um erro), o driver de função chamará IoCompleteRequest com IO_NO_INCREMENT e retornará o erro IoCallDriver de sua rotina DispatchPnP . O driver de função não define Irp-IoStatus.Status> nesse caso porque o status já foi definido pelo driver inferior que falhou com o IRP.

Quando um driver de função recebe uma solicitação IRP_MN_START_DEVICE, ele deve examinar as estruturas em IrpSp-Parameters.StartDevice.AllocatedResources> e IrpSp-Parameters.StartDevice.AllocatedResourcesTranslated>, que descrevem os recursos brutos e traduzidos, respectivamente, que o gerenciador PnP atribuiu ao dispositivo. Os drivers devem salvar uma cópia de cada lista de recursos na extensão do dispositivo como um auxílio de depuração.

As listas de recursos são emparelhadas CM_RESOURCE_LIST estruturas, nas quais cada elemento da lista bruta corresponde ao mesmo elemento da lista traduzida. Por exemplo, se AllocatedResources.List[0] descrever um intervalo de portas de E/S bruto, AllocatedResourcesTranslated.List[0] descreverá o mesmo intervalo após a tradução. Cada recurso traduzido inclui um endereço físico e o tipo do recurso.

Se um driver receber um recurso de memória traduzida (CmResourceTypeMemory), ele deverá chamar MmMapIoSpace para mapear o endereço físico em um endereço virtual por meio do qual ele pode acessar registros de dispositivo. Para que um driver opere de maneira independente da plataforma, ele deve marcar cada recurso retornado, traduzido e mapeá-lo, se necessário.

Um driver de função deve fazer o seguinte em resposta a um IRP_MN_START_DEVICE para garantir o acesso a todos os recursos do dispositivo:

  1. Copie IrpSp-Parameters.StartDevice.AllocatedResources> para a extensão do dispositivo.

  2. Copie IrpSp-Parameters.StartDevice.AllocatedResourcesTranslated> para a extensão do dispositivo.

  3. Em um loop, inspecione cada elemento descritor em AllocatedResourcesTranslated. Se o tipo de recurso do descritor for CmResourceTypeMemory, chame MmMapIoSpace, passando o endereço físico e o comprimento do recurso traduzido.

Quando o driver recebe uma solicitação de IRP_MN_STOP_DEVICE, IRP_MN_REMOVE_DEVICE ou IRP_MN_SURPRISE_REMOVAL , ele deve liberar os mapeamentos chamando MmUnmapIoSpace em um loop semelhante. O driver também deverá chamar MmUnmapIoSpace se ele precisar falhar na solicitação de IRP_MN_START_DEVICE .

Consulte Mapeamento Bus-Relative endereços para endereços virtuais para obter mais informações.