Compartir a través de


Operaciones de bus atómico

Para usar determinadas funcionalidades de hardware de un dispositivo periférico conectado a SPB, es posible que un cliente del controlador SPB (es decir, un controlador periférico) tenga que realizar una secuencia de transferencias de datos hacia y desde el dispositivo como una operación atómica de bus. La secuencia de transferencia es atómica porque ningún otro cliente puede transferir datos hacia o desde un dispositivo en el bus hasta que finalice la secuencia.

La manera típica de que un cliente realice una secuencia de transferencia como una operación de bus atómico es enviar una solicitud de IOCTL_SPB_EXECUTE_SEQUENCE al dispositivo de destino. En esta solicitud, el cliente especifica la secuencia como una lista de transferencias sencillas de lectura y escritura. La lista puede tener una longitud arbitraria. Las lecturas y escrituras se realizan en el orden en que se enumeran, y cada lectura o escritura puede transferir un número arbitrario de bytes. La mayoría de los controladores SPB admiten solicitudes de IOCTL_SPB_EXECUTE_SEQUENCE .

Bloqueos del controlador SPB

Una forma menos común de realizar una secuencia de transferencia atómica es usar un bloqueo de controlador SPB. Un cliente envía una solicitud de IOCTL_SPB_LOCK_CONTROLLER para adquirir el bloqueo y una solicitud de IOCTL_SPB_UNLOCK_CONTROLLER para liberar el bloqueo. Cuando un cliente contiene el bloqueo del controlador, cualquier secuencia de solicitudes sencillas de lectura y escritura (IRP_MJ_READ y IRP_MJ_WRITE) que el cliente envía al dispositivo se realiza como una operación atómica en el bus.

La mayoría de los dispositivos periféricos conectados a SPB no requieren bloqueos de controlador y la mayoría de los controladores de controlador SPB no implementan compatibilidad con estos bloqueos. Sin embargo, es posible que algunos clientes necesiten usar bloqueos de controlador para acceder a los dispositivos que tienen características inusuales.

Por ejemplo, un dispositivo podría implementar funciones de dispositivo a las que solo se puede acceder a través de operaciones de lectura-modificación-escritura que son atómicas en el bus. Para realizar esta operación, el cliente envía las cuatro solicitudes de E/S siguientes (en el orden que se muestra):

  1. IOCTL_SPB_LOCK_CONTROLLER : adquiera el bloqueo del controlador.
  2. IRP_MJ_READ : lee un bloque de datos de un dispositivo de destino.
  3. IRP_MJ_WRITE : vuelva a escribir los datos modificados en el dispositivo.
  4. IOCTL_SPB_UNLOCK_CONTROLLER : libere el bloqueo del controlador.

Después de la operación de lectura de la lista anterior, el cliente interpreta los datos leídos del dispositivo y modifica los datos antes de volver a escribirlos en el dispositivo.

Sin embargo, algunos dispositivos conectados a SPB tienen características que requieren bloqueos de controlador. Para la mayoría de los dispositivos que requieren operaciones atómicas de bus, IOCTL_SPB_EXECUTE_SEQUENCE solicitudes son suficientes.

No confunda los bloqueos del controlador SPB con bloqueos de conexión SPB. En el caso atípico en el que dos clientes comparten acceso al mismo dispositivo periférico conectado a SPB, cualquiera de los clientes puede usar un bloqueo de conexión para obtener temporalmente acceso exclusivo al dispositivo. Para obtener más información, consulte Bloqueos de conexión de SPB.

Señales de bus de hardware

Para controlar una solicitud de IOCTL_SPB_EXECUTE_SEQUENCE , un controlador de controlador SPB configura el hardware del controlador para generar las señales adecuadas en el bus durante la secuencia de transferencia. Los dispositivos periféricos conectados al bus pueden depender de estas señales para detectar cuándo está en curso una operación de bus atómico. El conjunto de señales de hardware que un controlador SPB usa para realizar una secuencia de transferencia como una operación atómica de bus depende del tipo de bus.

Para un bus I2C, el controlador inicia una secuencia transmitiendo un bit de inicio en el bus y finaliza una secuencia transmitiendo un bit de parada. Entre los bits de inicio y detención, la secuencia de transferencias de datos hacia y desde el dispositivo se realiza como una única operación de bus atómico. Excepto para la transferencia final en la secuencia, cada transferencia va seguida de una operación de reinicio de I2C (un bit de inicio repetido que no va precedido de un bit de detención).

Para un bus SPI, el controlador inicia una secuencia mediante la aserción de la línea de selección de chip en el dispositivo de destino y finaliza la secuencia mediante la deserción de la línea de selección de chip. Al mantener la línea de selección de chip constantemente asercida durante una secuencia de transferencias de datos a través del bus, las transferencias se realizan como una única operación de bus atómico.

Un dispositivo I2C de ejemplo

Un dispositivo periférico típico en un bus I2C podría implementar varias funciones internas del dispositivo. Para acceder a algunas de estas funciones, un cliente puede usar IOCTL_SPB_EXECUTE_SEQUENCE solicitudes.

Por ejemplo, un dispositivo periférico I2C podría contener los dos registros internos siguientes:

  • Registro de dirección de función en el que el cliente escribe la dirección interna de la función del dispositivo para acceder.
  • Registro de datos a través del cual el cliente lee datos de o escribe datos en la dirección de función especificada.

En este ejemplo, el dispositivo periférico I2C interpreta el primer byte escrito en el dispositivo después de un bit de inicio para que sea una dirección de función que se carga en el registro de la dirección de función. Los bytes adicionales transferidos al dispositivo o desde él antes de que finalice la secuencia (como se indica en el bit de detención) se tratan mediante el dispositivo como datos que se van a transferir a través del registro de datos.

Para realizar una operación de escritura, el cliente envía una solicitud de escritura (IRP_MJ_WRITE) en la que el primer byte del búfer de escritura es la dirección de la función y los bytes restantes del búfer son datos que se escribirán en la dirección de la función.

La lectura desde el dispositivo es más complicada. Supongamos que el dispositivo I2C de este ejemplo admite una característica de "lectura rápida" que restablece automáticamente el registro de direcciones de función a su valor predeterminado, 0, cuando se detecta un bit de detención en el bus. Con esta característica, el cliente puede leer los datos de la dirección de función 0 sin tener que escribir primero en el registro de direcciones de función. Esta característica puede mejorar la velocidad de las operaciones de lectura del dispositivo, especialmente si la mayoría de las lecturas proceden de la dirección de función 0 y son relativamente cortas.

Sin embargo, para leer un bloque de datos de una dirección de función distinta de cero, el cliente todavía debe escribir un byte en el registro de direcciones de función antes de leer el bloque de datos del registro de datos. El cliente debe realizar estas transferencias de escritura y lectura como una operación de bus atómico para evitar que el controlador de bus transmita un bit de detención después de la escritura en el registro de direcciones de función y antes de la lectura del registro de datos. De lo contrario, el bit de detención hará que los datos se lean desde la dirección de función 0 en lugar de desde la dirección de función distinta de cero.

En la lista siguiente se describe la serie de solicitudes de E/S que un cliente envía al dispositivo I2C en este ejemplo para realizar una operación de lectura-modificación-escritura en los datos ubicados en una dirección de función distinta de cero en el dispositivo:

  1. IOCTL_SPB_EXECUTE_SEQUENCE : realice una secuencia de transferencia de E/S para leer datos del dispositivo. La primera transferencia de esta secuencia es una escritura de bytes en el registro de direcciones de función. La segunda transferencia de la secuencia es una lectura de algún número de bytes de la dirección de función seleccionada. Estas dos transferencias se realizan atómicamente en el autobús.
  2. IRP_MJ_WRITE : escriba datos en el dispositivo. El primer byte del búfer de escritura de esta solicitud es el valor que se va a escribir en el registro de direcciones de función. Los bytes restantes del búfer son datos para escribir en la dirección de función seleccionada.

En su lugar, se pueden usar otros patrones de solicitudes para realizar esta operación de lectura-modificación-escritura. Por ejemplo, la solicitud de IRP_MJ_WRITE del paso 2 se puede reemplazar por una solicitud de IOCTL_SPB_EXECUTE_SEQUENCE que especifica dos transferencias de datos, las cuales son escrituras. La primera transferencia de la secuencia carga un byte en el registro de direcciones de función. La segunda transferencia escribe los bytes de datos en la dirección de función seleccionada. Esta solicitud, a diferencia de la solicitud de IRP_MJ_WRITE del paso 2, no requiere que el cliente combine los bytes de datos y bytes de datos de la dirección de función en el mismo búfer de escritura.

Para realizar una lectura-modificación-escritura en la dirección de función 0 de este dispositivo, la solicitud de IOCTL_SPB_EXECUTE_SEQUENCE del paso 1 de la lista anterior se puede reemplazar por una solicitud simple de lectura (IRP_MJ_READ).