Sequências de transferência de E/S
A extensão de estrutura do SPB (SpbCx) dá suporte a sequências de transferência de E/S. Uma sequência de transferência de E/S é um conjunto ordenado de transferências de ônibus (operações de leitura e gravação) que é executado como uma única operação de barramento atômico. Todas as transferências em uma sequência de transferência de E/S acessam o mesmo dispositivo de destino no barramento. Enquanto uma sequência está sendo executada, nenhum outro dispositivo no barramento pode ser acessado, mesmo que o driver do controlador SPB possa receber solicitações de E/S para outros dispositivos antes que a sequência de transferência de E/S seja concluída.
Um exemplo de uma sequência de transferência de E/S é uma operação de leitura de gravação, que é uma operação de gravação de barramento seguida por uma operação de leitura de barramento. Um driver de dispositivo periférico cliente pode usar esse tipo de sequência para gravar em um registro de seleção de função em um dispositivo periférico conectado a SPB e, em seguida, ler o valor da função de dispositivo selecionada. Essas duas transferências podem ter comprimentos diferentes. Por exemplo, a operação de gravação pode transferir um byte de dados e a operação de leitura pode transferir muitos bytes de dados.
Tipos de sequências de transferência de E/S
Um cliente pode iniciar uma sequência de transferência de E/S de uma destas maneiras:
O cliente pode especificar toda a sequência em uma solicitação de controle de E/ S IOCTL_SPB_EXECUTE_SEQUENCE . Essa solicitação permite que o driver do controlador SPB use as otimizações de desempenho específicas do hardware disponíveis para executar a sequência de transferência. Para obter mais informações, consulte Sequências de solicitação única.
O cliente pode enviar uma solicitação de controle de E/ S IOCTL_SPB_LOCK_CONTROLLER para bloquear o controlador no início de uma sequência e enviar um IOCTL_SPB_UNLOCK_CONTROLLER quando a sequência for concluída. Enquanto o controlador está bloqueado, o cliente envia uma solicitação de E/S separada (IRP_MJ_READ ou IRP_MJ_WRITE) para cada operação de leitura ou gravação na sequência. Para obter mais informações, consulte Sequências implementadas pelo cliente.
Sempre que possível, um cliente deve usar a solicitação IOCTL_SPB_EXECUTE_SEQUENCE , que é mais rápida, é menos propensa a erros e diminui significativamente o tempo durante o qual outros clientes são bloqueados fora do ônibus. No entanto, um cliente poderá usar as solicitações IOCTL_SPB_LOCK_CONTROLLER e IOCTL_SPB_UNLOCK_CONTROLLER se precisar examinar o valor lido durante uma das transferências na sequência antes de iniciar uma transferência posterior na sequência. Nesse caso, é necessário um design cuidadoso para evitar bloquear outros clientes do ônibus por mais tempo do que o necessário, e um driver periférico mal projetado pode prejudicar o desempenho geral do sistema.
Sequências de Single-Request
Para melhorar o desempenho, o driver do controlador SPB deve implementar uma função de retorno de chamada EvtSpbControllerIoSequence para lidar com solicitações de IOCTL_SPB_EXECUTE_SEQUENCE . Essa abordagem adiciona alguma complexidade ao driver do controlador SPB, mas evita exigir que o cliente execute uma sequência de transferência de E/S como uma série de operações individuais de leitura e gravação enquanto outros clientes são bloqueados fora do barramento.
Observação
A implementação de uma função EvtSpbControllerIoSequence é altamente recomendada e pode se tornar um requisito para Windows 8.
A implementação de uma sequência de transferência é semelhante à de uma operação simples de leitura ou gravação, mas também requer atualizações para o estado armazenado da operação de sequência entre as transferências individuais na sequência. Após a conclusão da primeira transferência, o driver do controlador SPB atualiza o estado da sequência para selecionar a próxima transferência na sequência. O estado da sequência é armazenado no contexto do dispositivo e inclui o identificador SPBREQUEST que é passado para o retorno de chamada EvtSpbControllerIoSequence . O driver do controlador SPB usa esse identificador para obter os parâmetros buffer, comprimento, direção e posição para as transferências individuais na sequência. Para obter mais informações sobre como obter esses parâmetros, consulte SpbRequestGetTransferParameters.
Se o driver do controlador SPB não puder executar a operação de IOCTL_SPB_EXECUTE_SEQUENCE solicitada, ele concluirá a solicitação com um código de falha. Se essa falha ocorrer, o cliente poderá, como opção, bloquear o barramento, executar explicitamente a sequência de transferência de E/S como uma série de solicitações simples de E/S e desbloquear o barramento. Para obter mais informações, consulte Sequências implementadas pelo cliente.
O SpbCx faz verificação de parâmetros em solicitações IOCTL_SPB_XXX que recebe de drivers de dispositivo periféricos. Para solicitações de IOCTL_SPB_EXECUTE_SEQUENCE , o SpbCx rejeita sequências vazias e sequências que contêm ponteiros de buffer NULL ou buffers de comprimento zero.
O driver do controlador SPB deve verificar se o comprimento de cada transferência em uma sequência não excede o limite especificado pelo driver. Por exemplo, o driver de exemplo SkeletonI2C no WDK (Kit de Driver do Windows) falha em uma solicitação IOCTL_SPB_EXECUTE_SEQUENCE que especifica uma transferência que excede bytes de 4K e define o código de status dessa solicitação como STATUS_INVALID_PARAMETER. Antes de iniciar uma operação de sequência para uma solicitação de IOCTL_SPB_EXECUTE_SEQUENCE , o driver deve validar os parâmetros de todas as transferências na sequência para verificar se a operação pode ser concluída com êxito.
O SpbCx nunca precede um retorno de chamada EvtSpbControllerIoSequence com um retorno de chamada EvtSpbControllerLock e nunca segue um retorno de chamada EvtSpbControllerIoSequence com um retorno de chamada EvtSpbControllerUnlock .
Sequências de Client-Implemented
Um cliente de um driver de controlador SPB pode executar explicitamente uma sequência de transferência de E/S como uma série de leituras e gravações simples. O cliente pode ser um driver no modo kernel ou um driver de modo de usuário que controla um dispositivo periférico anexado ao barramento. Antes da primeira transferência na sequência, o cliente envia uma solicitação IOCTL_SPB_LOCK_CONTROLLER para o dispositivo de destino para impedir que outros acessos de barramento não relacionados ocorram entre as transferências na sequência. Em seguida, o cliente envia solicitações IRP_MJ_READ e IRP_MJ_WRITE para executar as transferências na sequência. Por fim, o cliente envia uma solicitação IOCTL_SPB_UNLOCK_CONTROLLER para liberar o bloqueio.
Um cliente pode precisar implementar esse tipo de sequência de transferência de E/S se uma transferência posterior na sequência tiver uma dependência de uma transferência anterior. Por exemplo, a primeira leitura pode indicar quantos bytes mais ler ou gravar posteriormente. No entanto, se essa dependência não existir, o cliente deverá enviar uma solicitação IOCTL_SPB_EXECUTE_SEQUENCE para o driver do controlador SPB, que pode executar a sequência com mais eficiência.
Entre a solicitação de IOCTL_SPB_LOCK_CONTROLLER que inicia uma sequência implementada pelo cliente e a solicitação IOCTL_SPB_UNLOCK_CONTROLLER que encerra a sequência, as únicas solicitações de E/S que o cliente pode enviar para o dispositivo de destino são IRP_MJ_READ e IRP_MJ_WRITE solicitações. Qualquer violação dessa regra é um erro.
Os bloqueios SPB são usados apenas para garantir que uma sequência de leituras e gravações seja executada como uma operação de barramento atômico e deve ser usada exclusivamente para essa finalidade.
Para obter mais informações, consulte Manipulando sequências de Client-Implemented.