Compartilhar via


Operações de barramento atômico

Para usar determinadas funcionalidades de hardware de um dispositivo periférico conectado a SPB, um cliente do controlador SPB (ou seja, um driver periférico) pode precisar executar uma sequência de transferências de dados de e para o dispositivo como uma operação de barramento atômico. A sequência de transferência é atômica porque nenhum outro cliente pode transferir dados de ou para um dispositivo no barramento até que a sequência seja concluída.

A maneira típica de um cliente executar uma sequência de transferência como uma operação de barramento atômico é enviar uma solicitação de IOCTL_SPB_EXECUTE_SEQUENCE para o dispositivo de destino. Nessa solicitação, o cliente especifica a sequência como uma lista de transferências simples de leitura e gravação. A lista pode ter comprimento arbitrário. As leituras e gravações são executadas na ordem em que estão listadas e cada leitura ou gravação pode transferir um número arbitrário de bytes. A maioria dos controladores SPB dá suporte a solicitações de IOCTL_SPB_EXECUTE_SEQUENCE .

Bloqueios do controlador SPB

Uma maneira menos comum de executar uma sequência de transferência atômica é usar um bloqueio de controlador SPB. Um cliente envia uma solicitação de IOCTL_SPB_LOCK_CONTROLLER para adquirir o bloqueio e uma solicitação IOCTL_SPB_UNLOCK_CONTROLLER para liberar o bloqueio. Quando um cliente mantém o bloqueio do controlador, qualquer sequência de solicitações simples de leitura e gravação (IRP_MJ_READ e IRP_MJ_WRITE) que o cliente envia para o dispositivo é executada como uma operação atômica no barramento.

A maioria dos dispositivos periféricos conectados ao SPB não exige bloqueios de controlador e a maioria dos drivers de controlador SPB não implementa suporte para esses bloqueios. No entanto, alguns clientes podem precisar usar bloqueios de controlador para acessar dispositivos que têm recursos incomuns.

Por exemplo, um dispositivo pode implementar funções de dispositivo que só podem ser acessadas por meio de operações de leitura-modificação-gravação atômicas no barramento. Para executar essa operação, o cliente envia as quatro solicitações de E/S a seguir (na ordem mostrada):

  1. IOCTL_SPB_LOCK_CONTROLLER – adquira o bloqueio do controlador.
  2. IRP_MJ_READ – ler um bloco de dados de um dispositivo de destino.
  3. IRP_MJ_WRITE – gravar os dados modificados de volta no dispositivo.
  4. IOCTL_SPB_UNLOCK_CONTROLLER – libere o bloqueio do controlador.

Após a operação de leitura na lista anterior, o cliente interpreta os dados que foram lidos do dispositivo e modifica os dados antes de escrevê-los no dispositivo.

No entanto, poucos dispositivos conectados ao SPB têm recursos que exigem bloqueios do controlador. Para a maioria dos dispositivos que exigem operações de barramento atômico, IOCTL_SPB_EXECUTE_SEQUENCE solicitações são suficientes.

Não confunda bloqueios de controlador SPB com bloqueios de conexão SPB. No caso atípico em que dois clientes compartilham acesso ao mesmo dispositivo periférico conectado a SPB, qualquer cliente pode usar um bloqueio de conexão para obter temporariamente acesso exclusivo ao dispositivo. Para obter mais informações, consulte Bloqueios de conexão do SPB.

Sinais de barramento de hardware

Para lidar com uma solicitação de IOCTL_SPB_EXECUTE_SEQUENCE , um driver de controlador SPB configura o hardware do controlador para gerar os sinais apropriados no barramento durante a sequência de transferência. Dispositivos periféricos anexados ao barramento podem depender desses sinais para detectar quando uma operação de barramento atômico está em andamento. O conjunto de sinais de hardware que um controlador SPB usa para executar uma sequência de transferência como uma operação de barramento atômico depende do tipo de barramento.

Para um barramento I2C, o controlador inicia uma sequência transmitindo um bit inicial no barramento e encerra uma sequência transmitindo um bit de parada. Entre os bits de início e parada, a sequência de transferências de dados de e para o dispositivo é executada como uma única operação de barramento atômico. Exceto pela transferência final na sequência, cada transferência é seguida por uma operação de reinicialização de I2C (um bit inicial repetido que não é precedido por um bit de parada).

Para um barramento SPI, o controlador inicia uma sequência afirmando a linha chip-select para o dispositivo de destino e encerra a sequência desativando a linha chip-select. Mantendo a linha chip-select continuamente afirmada durante uma sequência de transferências de dados sobre o ônibus, as transferências são executadas como uma única operação de barramento atômico.

Um dispositivo I2 C deexemplo

Um dispositivo periférico típico em um barramento I2C pode implementar várias funções de dispositivo internas. Para acessar algumas dessas funções, um cliente pode usar IOCTL_SPB_EXECUTE_SEQUENCE solicitações.

Por exemplo, um dispositivo periférico I2C pode conter os dois registros internos a seguir:

  • Um registro de endereço de função no qual o cliente grava o endereço interno da função de dispositivo a ser acessada.
  • Um registro de dados por meio do qual o cliente lê dados ou grava dados no endereço de função especificado.

O dispositivo periférico I2C neste exemplo interpreta o primeiro byte gravado no dispositivo após um bit inicial para ser um endereço de função a ser carregado no registro de endereço de função. Todos os bytes adicionais transferidos de ou para o dispositivo antes do término da sequência (conforme indicado pelo bit de parada) são tratados pelo dispositivo como dados a serem transferidos por meio do registro de dados.

Para executar uma operação de gravação, o cliente envia uma solicitação de gravação (IRP_MJ_WRITE) na qual o primeiro byte no buffer de gravação é o endereço da função e os bytes restantes no buffer são dados a serem gravados no endereço da função.

A leitura do dispositivo é mais complicada. Suponha que o dispositivo I2C neste exemplo dê suporte a um recurso de "leitura rápida" que redefine automaticamente o registro de endereço de função para seu valor padrão, 0, quando um bit de parada é detectado no barramento. Com esse recurso, o cliente pode ler os dados do endereço da função 0 sem primeiro precisar gravar no registro de endereço de função. Esse recurso pode melhorar a velocidade das operações de leitura do dispositivo, especialmente se a maioria das leituras for do endereço de função 0 e for relativamente curta.

No entanto, para ler um bloco de dados de um endereço de função diferente de zero, o cliente ainda deve gravar um byte no registro de endereço de função antes de ler o bloco de dados do registro de dados. O cliente deve executar essas transferências de gravação e leitura como uma operação de barramento atômico para impedir que o controlador de barramento transmite um bit de parada após a gravação para o registro de endereço de função e antes da leitura do registro de dados. Caso contrário, o bit de parada fará com que os dados sejam lidos do endereço de função 0 em vez do endereço da função diferente de zero.

A lista a seguir descreve a série de solicitações de E/S que um cliente envia para o dispositivo I2C neste exemplo para executar uma operação de leitura-modificação-gravação em dados localizados em um endereço de função diferente de zero no dispositivo:

  1. IOCTL_SPB_EXECUTE_SEQUENCE – execute uma sequência de transferência de E/S para ler dados do dispositivo. A primeira transferência nessa sequência é uma gravação de byte no registro de endereço de função. A segunda transferência na sequência é uma leitura de alguns números de bytes do endereço de função selecionado. Essas duas transferências são executadas atomicamente no ônibus.
  2. IRP_MJ_WRITE - Gravar dados no dispositivo. O primeiro byte no buffer de gravação para essa solicitação é o valor a ser gravado no registro de endereço de função. Os bytes restantes no buffer são dados a serem gravados no endereço de função selecionado.

Outros padrões de solicitações podem ser usados para executar essa operação de leitura-modificação-gravação. Por exemplo, a solicitação IRP_MJ_WRITE na etapa 2 pode ser substituída por uma solicitação de IOCTL_SPB_EXECUTE_SEQUENCE que especifica duas transferências de dados, ambas gravações. A primeira transferência na sequência carrega um byte no registro de endereço de função. A segunda transferência grava os bytes de dados no endereço da função selecionada. Essa solicitação, ao contrário da solicitação IRP_MJ_WRITE na etapa 2, não exige que o cliente combine o byte de endereço de função e os bytes de dados no mesmo buffer de gravação.

Para executar uma leitura-modificação-gravação no endereço da função 0 neste dispositivo, a solicitação IOCTL_SPB_EXECUTE_SEQUENCE na etapa 1 da lista anterior pode ser substituída por uma solicitação simples de leitura (IRP_MJ_READ).