Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
A chamada do gestor de E/S para a rotina de despacho de um driver é o primeiro estágio para satisfazer uma solicitação de E/S de dispositivo. A rotina StartIo é a segunda etapa. É provável que cada driver de dispositivo com uma rotina StartIo chame IoStartPacket de suas rotinas DispatchRead e DispatchWrite e, geralmente, para um subconjunto dos códigos de controle de E/S que ele suporta em sua rotina DispatchDeviceControl . A rotina IoStartPacket adiciona o IRP à fila de dispositivos fornecidos pelo sistema do dispositivo ou, se a fila estiver vazia, chama imediatamente a rotina StartIo do driver para processar o IRP.
Você pode supor que quando a rotina StartIo de um motorista é chamada, o dispositivo de destino não está ocupado. Isso ocorre porque o gestor de E/S chama StartIo em duas circunstâncias, ou uma das rotinas de despacho do driver acabou de chamar IoStartPacket e a fila do dispositivo estava vazia, ou a rotina DpcForIsr do driver está concluindo outra solicitação e acabou de chamar IoStartNextPacket para retirar o próximo IRP da fila.
Antes que a rotina StartIo num driver de dispositivo de nível mais alto seja invocada, a rotina de despacho desse driver deve ter inspecionado e bloqueado o buffer do utilizador, se necessário, para configurar endereços válidos de buffer mapeados no IRP enfileirado para a sua rotina StartIo. Se um driver de dispositivo de nível mais alto configurar seus objetos de dispositivo para E/S direta (ou para E/S nem em buffer nem direta), o driver não poderá adiar o bloqueio de um buffer de usuário para sua rotina StartIo ; cada rotina StartIo é chamada em um contexto de thread arbitrário em IRQL = DISPATCH_LEVEL.
Observação
Qualquer memória de buffer a ser acedida pela rotina StartIo de um driver deve ser bloqueada ou alocada a partir de memória residente em espaço do sistema e deve ser acessível num contexto de thread arbitrário.
Em geral, a rotina StartIo de qualquer driver de dispositivo de nível inferior é responsável por chamar IoGetCurrentIrpStackLocation com o IRP de entrada e, em seguida, fazer qualquer processamento específico de solicitação necessário para iniciar a operação de E/S em seu dispositivo. O processamento específico da solicitação pode incluir o seguinte:
Configurando ou atualizando qualquer informação de estado sobre a solicitação atual que o driver mantém. As informações de estado podem ser armazenadas na extensão do dispositivo do objeto de dispositivo de destino ou em outro lugar no pool não paginado alocado pelo driver.
Por exemplo, se um driver de dispositivo mantém um Boolean InterruptExpected para a operação de transferência atual, sua rotina StartIo pode definir essa variável como TRUE. Se o driver mantiver um contador de tempo limite para a operação atual, sua rotina StartIo poderá configurar esse valor ou a rotina StartIo poderá enfileirar a rotina CustomTimerDpc do driver.
Se a rotina StartIo partilhar o acesso a informações de estado ou recursos de hardware com outras rotinas de driver, as informações de estado ou os recursos devem ser protegidos por um spin lock. (Consulte Spin Locks.)
Se a rotina StartIo compartilhar acesso a informações de estado ou recursos com a rotina InterruptService do driver, StartIo deve usar KeSynchronizeExecution para chamar uma rotina SynchCritSection que acessa as informações de estado ou recurso. (Consulte O uso de seções críticas.)
Atribuir um número de sequência ao IRP no caso de o driver precisar registrar um erro de E/S do dispositivo durante o processamento do IRP.
Consulte Erros de log para obter mais informações.
Se necessário, traduzir os parâmetros da localização da pilha de E/S do driver em valores específicos para o dispositivo.
Por exemplo, um driver de disco pode precisar calcular o setor inicial ou o deslocamento de bytes para o endereço do disco físico para uma operação de transferência e se o comprimento solicitado da transferência cruzará um limite de setor específico ou excederá a capacidade de transferência de seu dispositivo físico.
Se o driver controlar um dispositivo de mídia removível, verifique se há alterações de mídia antes de programar o dispositivo para E/S e notificar seu sistema de arquivos sobrejacente se a mídia tiver sido alterada.
Para obter mais informações, consulte Suporte de suportes amovíveis.
Se o dispositivo usa DMA, verificar se o comprimento solicitado (número de bytes a serem transferidos, encontrado no local da pilha de E/S do driver do IRP) deve ser dividido em operações de transferência parcial, conforme explicado em Técnicas de entrada/saída, assumindo que um driver de nível superior intimamente acoplado não pré-divide grandes transferências para o driver de dispositivo.
A rotina StartIo de tal driver de dispositivo também pode ser responsável por chamar KeFlushIoBuffers e, se o driver usa DMA baseado em pacote, por chamar AllocateAdapterChannel com a rotina AdapterControl do driver.
Consulte Objetos do Adaptador e DMA e Mantendo a Coerência do Cache para mais detalhes.
Se o dispositivo usa PIO, mapeando o endereço virtual base do buffer, descrito no IRP em Irp-MdlAddress>, para um endereço de espaço do sistema com MmGetSystemAddressForMdlSafe.
Para solicitações de leitura, a rotina StartIo do driver de dispositivo pode ser responsável por chamar KeFlushIoBuffers antes do início das operações PIO. Consulte Mantendo a coerência do cache para obter mais informações.
Se um driver não-WDM utiliza um objeto de controlador, chamando IoAllocateController para registar a sua rotina ControllerControl.
Se o driver lida com IRPs canceláveis, verifique se o IRP de entrada já foi cancelado.
Se um IRP de entrada puder ser cancelado antes de ser processado até à conclusão, a rotina StartIo deverá chamar IoSetCancelRoutine com o IRP e o ponto de entrada da rotina Cancel do driver. A rotina StartIo deve adquirir o bloqueio de rotação cancel para sua chamada para IoSetCancelRoutine. Como alternativa, um driver pode usar IoSetStartIoAttributes para definir o atributo NonCancelable para a rotina StartIo como TRUE. Isso impede que o sistema tente cancelar um IRP que foi passado para StartIo por uma chamada para IoStartPacket.
Como regra geral, um driver que usa E/S em buffer tem uma rotina StartIo mais simples do que um que usa E/S direta. Os drivers que utilizam E/S em buffer transferem pequenas quantidades de dados para cada solicitação de transferência, enquanto aqueles que utilizam E/S direta (seja DMA ou PIO) transferem grandes quantidades de dados de ou para buffers bloqueados em memória, que podem atravessar limites de páginas físicas na memória do sistema.
Drivers de nível mais alto em camadas superiores aos drivers de dispositivos físicos geralmente configuram os seus objetos de dispositivo para corresponder aos dos respetivos drivers de dispositivo. No entanto, um driver de nível mais alto, particularmente um driver de sistema de arquivos, pode configurar objetos de dispositivo para nem E/S direta nem em buffer.
Os drivers que configuram os seus objetos de dispositivo para E/S em buffer podem confiar no gestor de E/S para passar buffers válidos em todos os IRPs enviados ao driver. Os drivers de nível inferior que configuram objetos de dispositivo para E/S direta podem contar com o driver de nível mais alto em sua cadeia para passar buffers válidos em todos os IRPs enviados através de quaisquer drivers intermediários para o driver de dispositivo de nível inferior subjacente.
Usando E/S em buffer em rotinas StartIo
Se a rotina DispatchRead, DispatchWrite ou DispatchDeviceControl de um driver determinar que uma solicitação é válida e chamar IoStartPacket, o gerenciador de E/S chamará a rotina StartIo do driver para processar o IRP imediatamente se a fila de dispositivos estiver vazia. Se a fila não estiver vazia, IoStartPacket enfileirará o IRP. Eventualmente, uma chamada para IoStartNextPacket da rotina DpcForIsr ou CustomDpc do driver faz com que o gerenciador de E/S remova a fila do IRP e chame a rotina StartIo do driver.
A rotina StartIo chama IoGetCurrentIrpStackLocation e determina qual operação deve ser executada para satisfazer a solicitação. Ele pré-processa o IRP de qualquer forma necessária antes de programar o dispositivo físico para realizar a solicitação de E/S.
Se o acesso ao dispositivo físico (ou à extensão do dispositivo) deve ser sincronizado com uma rotina InterruptService , a rotina StartIo deve chamar uma rotina SynchCritSection para executar a programação de dispositivo necessária. Para obter mais informações, consulte Usando Seções Críticas.
Um driver de dispositivo físico que usa E/S em buffer transfere dados de ou para um buffer de espaço do sistema, alocado pelo gerenciador de E/S, que o driver encontra em cada IRP em Irp-AssociatedIrp.SystemBuffer>.
Usando E/S Direta em Rotinas StartIo
Se a rotina DispatchRead, DispatchWrite ou DispatchDeviceControl de um driver determinar que uma solicitação é válida e chamar IoStartPacket, o gerenciador de E/S chamará a rotina StartIo do driver para processar o IRP imediatamente se a fila de dispositivos estiver vazia. Se a fila não estiver vazia, IoStartPacket enfileirará o IRP. Eventualmente, uma chamada para IoStartNextPacket da rotina DpcForIsr ou CustomDpc do driver faz com que o gestor de E/S retire o IRP da fila e chame a rotina StartIo do driver.
A rotina StartIo chama IoGetCurrentIrpStackLocation e determina qual operação deve ser executada para satisfazer a solicitação. Ele pré-processa o IRP de qualquer forma necessária, como dividir uma grande solicitação de transferência DMA em intervalos de transferência parcial e salvar o estado sobre o comprimento de uma solicitação de transferência de entrada que deve ser dividida. Em seguida, ele programa o dispositivo físico para realizar a solicitação de E/S.
Se o acesso ao dispositivo físico (ou à extensão do dispositivo) deve ser sincronizado com o ISR do driver, a rotina StartIo deve usar uma rotina SynchCritSection fornecida pelo driver para executar a programação necessária. Para obter mais informações, consulte Usando Seções Críticas.
Qualquer driver que usa E/S direta lê ou grava dados de um buffer bloqueado, descrito por uma lista de descritores de memória (MDL), que o driver encontra no IRP em Irp-MdlAddress>. Esse driver geralmente usa E/S em buffer para solicitações de controle de dispositivo. Para obter mais informações, consulte Manipulando solicitações de controle de E/S em rotinas StartIo.
O tipo MDL é um tipo opaco que os drivers não acessam diretamente. Em vez disso, os drivers que usam PIO remapeiam buffers de espaço do usuário chamando MmGetSystemAddressForMdlSafe com Irp-MdlAddress> como parâmetro. Os drivers que usam DMA também passam Irp-MdlAddress> nas rotinas de suporte durante as suas operações de transferência, de modo a que os endereços de memória intermédia sejam remapeados para intervalos lógicos para os seus dispositivos.
A menos que um driver de nível superior estreitamente acoplado divida grandes solicitações de transferência DMA para o driver de dispositivo subjacente, a rotina StartIo de um driver de dispositivo de nível mais baixo deve dividir cada solicitação de transferência maior do que o seu dispositivo pode controlar em uma única operação de transferência. Os drivers que usam o DMA do sistema são obrigados a dividir as solicitações de transferência que são muito grandes para o controlador DMA do sistema ou para seus dispositivos lidarem em uma única operação de transferência.
Se o dispositivo for um dispositivo DMA subordinado, seu driver deve sincronizar as transferências através de um controlador DMA do sistema com um objeto adaptador alocado pelo driver, representando o canal DMA, e uma rotina AdapterControl fornecida pelo driver. O driver de um dispositivo DMA bus-master também deve usar um objeto de adaptador alocado por driver para sincronizar as suas transferências e deve fornecer uma rotina AdapterControl se usar o suporte DMA baseado em pacotes do sistema ou uma rotina AdapterListControl se usar o suporte de dispersão e recolha do sistema.
Dependendo do design do driver, ele pode sincronizar as operações de transferência e controle de dispositivo em um dispositivo físico com um objeto controlador e fornecer uma rotina ControllerControl .
Consulte Objetos do adaptador e DMA e objetos do controlador para obter mais informações.
Manipulando solicitações de controle de E/S em rotinas StartIo
Em geral, apenas um subconjunto de solicitações de controle de E/S do dispositivo é passada da rotina DispatchDeviceControl ou DispatchInternalDeviceControl de um driver para processamento posterior pela rotina StartIo do driver. A rotina StartIo do driver só precisa lidar com solicitações válidas de controle de dispositivo que exijam alterações no estado do dispositivo ou retornem informações voláteis sobre o estado atual do dispositivo.
Cada novo driver deve suportar o mesmo conjunto de códigos de controle de E/S públicas que todos os outros drivers para o mesmo tipo de dispositivo. O sistema define códigos de controle de E/S públicos específicos do tipo de dispositivo para solicitações IRP_MJ_DEVICE_CONTROL como solicitações em buffer.
Consequentemente, os drivers de dispositivo físico fazem transferências de dados de ou para um buffer de espaço do sistema que cada driver encontra no IRP em Irp-AssociatedIrp.SystemBuffer> para solicitações de controle de dispositivo. Mesmo os drivers que configuram seus objetos de dispositivo para E/S direta usam E/S em buffer para satisfazer solicitações de controle de dispositivo com códigos de controle de E/S públicos.
A definição de cada código de controle de E/S determina se os dados transferidos para essa solicitação são armazenados em buffer. Qualquer código de controle de E/S definido de forma privada para solicitações de IRP_MJ_INTERNAL_DEVICE_CONTROL específicas do driver entre drivers emparelhados pode definir um código com método em buffer, método direto ou método nenhum. Como regra geral, qualquer código de controle de E/S definido privadamente não deve ser especificado com um método, caso um driver de nível superior intimamente acoplado precise alocar um buffer para essa solicitação.
Programando o dispositivo para operações de E/S
Normalmente, a rotina StartIo em um driver de dispositivo de nível mais baixo deve sincronizar o acesso a qualquer memória ou registro de dispositivo que compartilha com o ISR do driver usando KeSynchronizeExecution para chamar uma rotina SynchCritSection fornecida pelo driver. A rotina StartIo do motorista usa a rotina SynchCritSection para realmente programar o dispositivo físico para E/S no DIRQL. Para obter mais informações, consulte Usando Seções Críticas.
Antes de chamar KeSynchronizeExecution, a rotina StartIo deve fazer qualquer pré-processamento necessário para a solicitação. O pré-processamento pode incluir o cálculo de um intervalo de transferência parcial inicial e o salvamento de qualquer informação de estado sobre a solicitação original para outras rotinas de driver.
Se um driver de dispositivo usa DMA, sua rotina StartIo geralmente chama AllocateAdapterChannel com uma rotina AdapterControl fornecida pelo driver. Nessas circunstâncias, a rotina StartIo adia a responsabilidade de programar o dispositivo físico para a rotina AdapterControl . Ele, por sua vez, pode chamar KeSynchronizeExecution para que uma rotina SynchCritSection fornecida pelo driver programe o dispositivo para uma transferência DMA.