Escrevendo rotinas de DPC

As principais responsabilidades das rotinas DpcForIsr e CustomDpc são garantir que a próxima operação de E/S do dispositivo seja iniciada imediatamente e concluir o IRP atual.

O trabalho adicional feito por qualquer rotina DpcForIsr ou CustomDpc depende do design do driver e da natureza do dispositivo. Por exemplo, uma rotina DpcForIsr ou CustomDpc também pode fazer o seguinte:

  • Repita uma operação que atingiu o tempo limite ou falhou.

  • Chame IoAllocateErrorLogEntry, configure um pacote de log de erros para relatar um erro de E/S do dispositivo e chame IoWriteErrorLogEntry.

    Para obter mais informações sobre como lidar com erros de E/S, consulte Erros de log.

  • Se o driver usar E/S em buffer ou se o IRP especificar uma operação de controle de dispositivo, transfira os dados lidos do dispositivo para o buffer do sistema em Irp-AssociatedIrp.SystemBuffer> antes de concluir o IRP.

  • Se o driver usar E /S direta e precisar dividir grandes transferências em partes menores, salve o estado sobre cada operação de transferência parcial concluída, calcule o próximo intervalo de transferência parcial e use uma rotina SynchCritSection fornecida pelo driver para programar o dispositivo para a próxima operação de transferência parcial.

    Até mesmo um driver que usa E/S em buffer pode ter que dividir uma solicitação de transferência se o dispositivo tiver recursos de transferência limitados.

  • Se o driver usar DMA baseado em pacotes, chame FlushAdapterBuffers após cada operação de transferência de dispositivo e chame FreeAdapterChannel ou FreeMapRegisters quando uma sequência de transferências parciais for feita e a solicitação de transferência completa for atendida.

    Se uma transferência solicitada for apenas parcialmente atendida por uma única operação de DMA, a rotina DpcForIsr ou CustomDpc geralmente será responsável por configurar uma ou mais operações de DMA até que o número especificado de bytes do IRP seja totalmente transferido.

    Para obter mais informações sobre como usar o AMD, consulte DMA e Objetos do Adaptador.

  • Se o driver usar PIO (E/S) programada, chame KeFlushIoBuffers no final de cada operação de transferência se o IRP atual solicitar uma leitura.

    Se uma transferência solicitada for apenas parcialmente atendida por uma única operação de PIO, a rotina DpcForIsr ou CustomDpc geralmente será responsável por configurar uma ou mais operações de transferência até que o número especificado de bytes do IRP seja totalmente transferido.

    Para obter mais informações sobre como usar o PIO, consulte Usando E/S direta.

  • Se um driver não WDM tiver uma rotina ControllerControl , chame IoFreeController quando uma operação solicitada for concluída.

Observe que uma rotina DpcForIsr ou CustomDpc geralmente faz a maior parte do processamento de E/S do dispositivo do driver para atender aos IRPs. Essas rotinas também compartilham parte da responsabilidade de enfileirar IRPs no dispositivo com as rotinas de expedição do driver.

Considere as diretrizes de design gerais a seguir.

  • Qualquer rotina DpcForIsr ou CustomDpc deve chamar IoStartNextPacket assim que puder fazer essa chamada com segurança: ou seja, sem possivelmente causar um conflito de recursos ou uma condição de corrida com a rotina StartIo do piloto ou com qualquer outra rotina que a rotina StartIo faça a execução.

  • Se um driver gerenciar seu próprio enfileiramento de IRPs, sua rotina DpcForIsr ou CustomDpc deverá notificar o driver assim que for seguro remover a fila do próximo IRP e configurar o dispositivo para a próxima solicitação.

Uma rotina DpcForIsr ou CustomDpc deve chamar IoStartNextPacket ou notificar a rotina de driver apropriada quando o processamento de E/S do dispositivo para a próxima solicitação puder ser iniciado. Dependendo do driver e do dispositivo, isso pode ocorrer bem antes que a rotina DpcForIsr ou CustomDpc conclua o IRP atual com IoCompleteRequest ou pode ocorrer imediatamente antes que essa rotina conclua o IRP atual e retorne o controle.