\section{GPIO Device}\label{sec:Device Types / GPIO Device}

The Virtio GPIO device is a virtual General Purpose Input/Output device that
supports a variable number of named I/O lines, which can be configured in input
mode or in output mode with logical level low (0) or high (1).

\subsection{Device ID}\label{sec:Device Types / GPIO Device / Device ID}
41

\subsection{Virtqueues}\label{sec:Device Types / GPIO Device / Virtqueues}

\begin{description}
\item[0] requestq
\item[1] eventq
\end{description}

The \field{eventq} virtqueue is available only if the \field{VIRTIO_GPIO_F_IRQ}
feature has been negotiated.

\subsection{Feature bits}\label{sec:Device Types / GPIO Device / Feature bits}

\begin{description}
\item[VIRTIO_GPIO_F_IRQ (0)] The device supports interrupts on GPIO lines.
\end{description}

\subsection{Device configuration layout}\label{sec:Device Types / GPIO Device / Device configuration layout}

GPIO device uses the following configuration structure layout:

\begin{lstlisting}
struct virtio_gpio_config {
    le16 ngpio;
    u8 padding[2];
    le32 gpio_names_size;
};
\end{lstlisting}

\begin{description}
\item[\field{ngpio}] is the total number of GPIO lines supported by the device.

\item[\field{padding}] has no meaning and is reserved for future use. This is
    set to zero by the device.

\item[\field{gpio_names_size}] is the size of the gpio-names memory block in
    bytes, which can be fetched by the driver using the
    \field{VIRTIO_GPIO_MSG_GET_LINE_NAMES} message. The device sets this to
    0 if it doesn't support names for the GPIO lines.
\end{description}


\subsection{Device Initialization}\label{sec:Device Types / GPIO Device / Device Initialization}

\begin{itemize}
\item The driver configures and initializes the \field{requestq} virtqueue.

\item The driver configures and initializes the \field{eventq} virtqueue, if the
    \field{VIRTIO_GPIO_F_IRQ} feature has been negotiated.
\end{itemize}

\subsection{Device Operation: requestq}\label{sec:Device Types / GPIO Device / requestq Operation}

The driver uses the \field{requestq} virtqueue to send messages to the device.
The driver sends a pair of buffers, request (filled by driver) and response (to
be filled by device later), to the device. The device in turn fills the response
buffer and sends it back to the driver.

\begin{lstlisting}
struct virtio_gpio_request {
    le16 type;
    le16 gpio;
    le32 value;
};
\end{lstlisting}

All the fields of this structure are set by the driver and read by the device.

\begin{description}
\item[\field{type}] is the GPIO message type, i.e. one of
    \field{VIRTIO_GPIO_MSG_*} values.

\item[\field{gpio}] is the GPIO line number, i.e. 0 <= \field{gpio} <
    \field{ngpio}.

\item[\field{value}] is a message specific value.
\end{description}

\begin{lstlisting}
struct virtio_gpio_response {
    u8 status;
    u8 value;
};

/* Possible values of the status field */
#define VIRTIO_GPIO_STATUS_OK                   0x0
#define VIRTIO_GPIO_STATUS_ERR                  0x1
\end{lstlisting}

All the fields of this structure are set by the device and read by the driver.

\begin{description}
\item[\field{status}] of the GPIO message,
    \field{VIRTIO_GPIO_STATUS_OK} on success and \field{VIRTIO_GPIO_STATUS_ERR}
    on failure.

\item[\field{value}] is a message specific value.
\end{description}

Following is the list of messages supported by the virtio gpio specification.

\begin{lstlisting}
/* GPIO message types */
#define VIRTIO_GPIO_MSG_GET_LINE_NAMES          0x0001
#define VIRTIO_GPIO_MSG_GET_DIRECTION           0x0002
#define VIRTIO_GPIO_MSG_SET_DIRECTION           0x0003
#define VIRTIO_GPIO_MSG_GET_VALUE               0x0004
#define VIRTIO_GPIO_MSG_SET_VALUE               0x0005
#define VIRTIO_GPIO_MSG_SET_IRQ_TYPE            0x0006

/* GPIO Direction types */
#define VIRTIO_GPIO_DIRECTION_NONE              0x00
#define VIRTIO_GPIO_DIRECTION_OUT               0x01
#define VIRTIO_GPIO_DIRECTION_IN                0x02

/* GPIO interrupt types */
#define VIRTIO_GPIO_IRQ_TYPE_NONE               0x00
#define VIRTIO_GPIO_IRQ_TYPE_EDGE_RISING        0x01
#define VIRTIO_GPIO_IRQ_TYPE_EDGE_FALLING       0x02
#define VIRTIO_GPIO_IRQ_TYPE_EDGE_BOTH          0x03
#define VIRTIO_GPIO_IRQ_TYPE_LEVEL_HIGH         0x04
#define VIRTIO_GPIO_IRQ_TYPE_LEVEL_LOW          0x08
\end{lstlisting}

\subsubsection{requestq Operation: Get Line Names}\label{sec:Device Types / GPIO Device / requestq Operation / Get Line Names}

The driver sends this message to receive a stream of zero-terminated strings,
where each string represents the name of a GPIO line, present in increasing
order of the GPIO line numbers. The names of the GPIO lines are optional and may
be present only for a subset of GPIO lines. If missing, then a zero-byte must be
present for the GPIO line. If present, the name string must be zero-terminated
and the name must be unique within a GPIO Device. The names of the GPIO lines
are encoded in 7-bit ASCII.

These names of the GPIO lines should be most meaningful producer names for the
system, such as name indicating the usage. For example "MMC-CD", "Red LED Vdd"
and "ethernet reset" are reasonable line names as they describe what the line is
used for, while "GPIO0" is not a good name to give to a GPIO line.

Here is an example of how the gpio names memory block may look like for a GPIO
device with 10 GPIO lines, where line names are provided only for lines 0
("MMC-CD"), 5 ("Red LED Vdd") and 7 ("ethernet reset").

\begin{lstlisting}
u8 gpio_names[] = {
    'M', 'M', 'C', '-', 'C', 'D', 0,
    0,
    0,
    0,
    0,
    'R', 'e', 'd', ' ', 'L', 'E', 'D', ' ', 'V', 'd', 'd', 0,
    0,
    'E', 't', 'h', 'e', 'r', 'n', 'e', 't', ' ', 'r', 'e', 's', 'e', 't', 0,
    0,
    0
};
\end{lstlisting}

The device sets the \field{gpio_names_size} to a non-zero value if this message
is supported by the device, else it must be set to zero.

This message type uses different layout for the response structure, as the
device needs to return the \field{gpio_names} array.

\begin{lstlisting}
struct virtio_gpio_response_N {
    u8 status;
    u8 value[N];
};
\end{lstlisting}

The driver must allocate the \field{value[N]} buffer in the \field{struct
virtio_gpio_response_N} for N bytes, where N = \field{gpio_names_size}.

\begin{tabularx}{\textwidth}{ |l||X|X|X| }
\hline
\textbf{Request} & \field{type} & \field{gpio} & \field{value} \\
\hline
& \field{VIRTIO_GPIO_MSG_GET_LINE_NAMES} & 0 & 0 \\
\hline
\end{tabularx}

\begin{tabularx}{\textwidth}{ |l||X|X|X| }
\hline
\textbf{Response} & \field{status} & \field{value[N]} & \field{Where N is} \\
\hline
& \field{VIRTIO_GPIO_STATUS_*} & gpio-names & \field{gpio_names_size} \\
\hline
\end{tabularx}

\subsubsection{requestq Operation: Get Direction}\label{sec:Device Types / GPIO Device / requestq Operation / Get Direction}

The driver sends this message to request the device to return a line's
configured direction.

\begin{tabularx}{\textwidth}{ |l||X|X|X| }
\hline
\textbf{Request} & \field{type} & \field{gpio} & \field{value} \\
\hline
& \field{VIRTIO_GPIO_MSG_GET_DIRECTION} & line number & 0 \\
\hline
\end{tabularx}

\begin{tabularx}{\textwidth}{ |l||X|X| }
\hline
\textbf{Response} & \field{status} & \field{value} \\
\hline
& \field{VIRTIO_GPIO_STATUS_*} & 0 = none, 1 = output, 2 = input \\
\hline
\end{tabularx}

\subsubsection{requestq Operation: Set Direction}\label{sec:Device Types / GPIO Device / requestq Operation / Set Direction}

The driver sends this message to request the device to configure a line's
direction. The driver can either set the direction to
\field{VIRTIO_GPIO_DIRECTION_IN} or \field{VIRTIO_GPIO_DIRECTION_OUT}, which
also activates the line, or to \field{VIRTIO_GPIO_DIRECTION_NONE}, which
deactivates the line.

The driver should set the value of the GPIO line, using the
\field{VIRTIO_GPIO_MSG_SET_VALUE} message, before setting the direction of the
line to output to avoid any undesired behavior.

\begin{tabularx}{\textwidth}{ |l||X|X|X| }
\hline
\textbf{Request} & \field{type} & \field{gpio} & \field{value} \\
\hline
& \field{VIRTIO_GPIO_MSG_SET_DIRECTION} & line number & 0 = none, 1 = output, 2 = input \\
\hline
\end{tabularx}

\begin{tabularx}{\textwidth}{ |l||X|X| }
\hline
\textbf{Response} & \field{status} & \field{value} \\
\hline
& \field{VIRTIO_GPIO_STATUS_*} & 0 \\
\hline
\end{tabularx}

\subsubsection{requestq Operation: Get Value}\label{sec:Device Types / GPIO Device / requestq Operation / Get Value}

The driver sends this message to request the device to return current value
sensed on a line.

\begin{tabularx}{\textwidth}{ |l||X|X|X| }
\hline
\textbf{Request} & \field{type} & \field{gpio} & \field{value} \\
\hline
& \field{VIRTIO_GPIO_MSG_GET_VALUE} & line number & 0 \\
\hline
\end{tabularx}

\begin{tabularx}{\textwidth}{ |l||X|X| }
\hline
\textbf{Response} & \field{status} & \field{value} \\
\hline
& \field{VIRTIO_GPIO_STATUS_*} & 0 = low, 1 = high \\
\hline
\end{tabularx}

\subsubsection{requestq Operation: Set Value}\label{sec:Device Types / GPIO Device / requestq Operation / Set Value}

The driver sends this message to request the device to set the value of a line.
The line may already be configured for output or may get configured to output
later, at which point this output value must be used by the device for the line.

\begin{tabularx}{\textwidth}{ |l||X|X|X| }
\hline
\textbf{Request} & \field{type} & \field{gpio} & \field{value} \\
\hline
& \field{VIRTIO_GPIO_MSG_SET_VALUE} & line number & 0 = low, 1 = high \\
\hline
\end{tabularx}

\begin{tabularx}{\textwidth}{ |l||X|X| }
\hline
\textbf{Response} & \field{status} & \field{value} \\
\hline
& \field{VIRTIO_GPIO_STATUS_*} & 0 \\
\hline
\end{tabularx}

\subsubsection{requestq Operation: Set IRQ Type}\label{sec:Device Types / GPIO Device / requestq Operation / Set IRQ Type}

This request is allowed only if the \field{VIRTIO_GPIO_F_IRQ} feature has been
negotiated.

The interrupt configuration is divided into two steps, enabling or disabling of
the interrupt at the device and masking or unmasking of the interrupt for
delivery at the driver. This request only pertains to enabling or disabling of
the interrupt at the device, the masking and unmasking of the interrupt is
handled by a separate request that takes place over the \field{eventq}
virtqueue.

The driver sends the \field{VIRTIO_GPIO_MSG_SET_IRQ_TYPE} message over the
\field{requestq} virtqueue to enable or disable interrupt for a GPIO line at
the device.

The driver sends this message with trigger type set to any valid value other
than \field{VIRTIO_GPIO_IRQ_TYPE_NONE}, to enable the interrupt for a GPIO line,
this doesn't unmask the interrupt for delivery at the driver though. For edge
trigger type, the device should latch the interrupt events from this point
onward and notify it to the driver once the interrupt is unmasked. For level
trigger type, the device should notify the driver once the interrupt signal on a
line is sensed and the interrupt is unmasked for the line.

The driver sends this message with trigger type set to
\field{VIRTIO_GPIO_IRQ_TYPE_NONE}, to disable the interrupt for a GPIO line. The
device should discard any latched interrupt event associated with it. In order
to change the trigger type of an already enabled interrupt, the driver should
first disable the interrupt and then re-enable it with appropriate trigger type.

The interrupts are masked at initialization and the driver unmasks them by
queuing a pair of buffers, of type \field{virtio_gpio_irq_request} and
\field{virtio_gpio_irq_response}, over the \field{eventq} virtqueue for a GPIO
line. A separate pair of buffers must be queued for each GPIO line, the driver
wants to configure for interrupts. Once an already enabled interrupt is unmasked
by the driver, the device can notify the driver of an active interrupt signal on
the GPIO line. This is done by updating the \field{struct
virtio_gpio_irq_response} buffer's \field{status} with
\field{VIRTIO_GPIO_IRQ_STATUS_VALID} and returning the updated buffers to the
driver. The interrupt is masked automatically at this point until the buffers
are available again at the device.

The interrupt for a GPIO line should not be unmasked before being enabled by the
driver.

If the interrupt is disabled by the driver, by setting the trigger type to
\field{VIRTIO_GPIO_IRQ_TYPE_NONE}, or the interrupt is unmasked without being
enabled first, the device should return any unused pair of buffers for the GPIO
line, over the \field{eventq} virtqueue, after setting the \field{status} field
to \field{VIRTIO_GPIO_IRQ_STATUS_INVALID}. This also masks the interrupt.

\begin{tabularx}{\textwidth}{ |l||X|X|X| }
\hline
\textbf{Request} & \field{type} & \field{gpio} & \field{value} \\
\hline
& \field{VIRTIO_GPIO_MSG_SET_IRQ_TYPE} & line number & one of \field{VIRTIO_GPIO_IRQ_TYPE_*} \\
\hline
\end{tabularx}

\begin{tabularx}{\textwidth}{ |l||X|X| }
\hline
\textbf{Response} & \field{status} & \field{value} \\
\hline
& \field{VIRTIO_GPIO_STATUS_*} & 0 \\
\hline
\end{tabularx}

\subsubsection{requestq Operation: Message Flow}\label{sec:Device Types / GPIO Device / requestq Operation / Message Flow}

\begin{itemize}
\item The driver queues \field{struct virtio_gpio_request} and
    \field{virtio_gpio_response} buffers to the \field{requestq} virtqueue,
    after filling all fields of the \field{struct virtio_gpio_request} buffer as
    defined by the specific message type.

\item The driver notifies the device of the presence of buffers on the
    \field{requestq} virtqueue.

\item The device, after receiving the message from the driver, processes it and
    fills all the fields of the \field{struct virtio_gpio_response} buffer
    (received from the driver). The \field{status} must be set to
    \field{VIRTIO_GPIO_STATUS_OK} on success and \field{VIRTIO_GPIO_STATUS_ERR}
    on failure.

\item The device puts the buffers back on the \field{requestq} virtqueue and
    notifies the driver of the same.

\item The driver fetches the buffers and processes the response received in the
    \field{virtio_gpio_response} buffer.

\item The driver can send multiple messages in parallel for same or different
    GPIO line.
\end{itemize}

\drivernormative{\subsubsection}{requestq Operation}{Device Types / GPIO Device / requestq Operation}

\begin{itemize}
\item The driver MUST send messages on the \field{requestq} virtqueue.

\item The driver MUST queue both \field{struct virtio_gpio_request} and
    \field{virtio_gpio_response} for every message sent to the device.

\item The \field{struct virtio_gpio_request} buffer MUST be filled by the driver
    and MUST be read-only for the device.

\item The \field{struct virtio_gpio_response} buffer MUST be filled by the
    device and MUST be writable by the device.

\item The driver MAY send multiple messages for same or different GPIO lines in
    parallel.

\item The driver MUST NOT send IRQ messages if the \field{VIRTIO_GPIO_F_IRQ}
    feature has not been negotiated.

\item The driver MUST NOT send IRQ messages for a GPIO line configured for
    output.

\item The driver MUST set the IRQ trigger type to
    \field{VIRTIO_GPIO_IRQ_TYPE_NONE} once it is done using the GPIO line
    configured for interrupts.

\item In order to change the trigger type of an already enabled interrupt, the
    driver MUST first disable the interrupt and then re-enable it with
    appropriate trigger type.
\end{itemize}

\devicenormative{\subsubsection}{requestq Operation}{Device Types / GPIO Device / requestq Operation}

\begin{itemize}
\item The device MUST set all the fields of the \field{struct
    virtio_gpio_response} before sending it back to the driver.

\item The device MUST set all the fields of the \field{struct
    virtio_gpio_config} on receiving a configuration request from the driver.

\item The device MUST set the \field{gpio_names_size} field as zero in the
    \field{struct virtio_gpio_config}, if it doesn't implement names for
    individual GPIO lines.

\item The device MUST set the \field{gpio_names_size} field, in the
    \field{struct virtio_gpio_config}, with the size of gpio-names memory block
    in bytes, if the device implements names for individual GPIO lines. The
    strings MUST be zero-terminated and an unique (if available) within the GPIO
    device.

\item The device MUST process multiple messages, for the same GPIO line,
    sequentially and respond to them in the order they were received on the
    virtqueue.

\item The device MAY process messages, for different GPIO lines, out of order
    and in parallel, and MAY send message's response to the driver out of order.

\item The device MUST discard all state information corresponding to a GPIO
    line, once the driver has requested to set its direction to
    \field{VIRTIO_GPIO_DIRECTION_NONE}.

\item The device MUST latch an edge interrupt if the interrupt is enabled but
    still masked.

\item The device MUST NOT latch an level interrupt if the interrupt is enabled
    but still masked.

\item The device MUST discard any latched interrupt for a GPIO line, once
    interrupt is disabled for the same.
\end{itemize}

\subsection{Device Operation: eventq}\label{sec:Device Types / GPIO Device / eventq Operation}

The \field{eventq} virtqueue is used by the driver to unmask the interrupts and
used by the device to notify the driver of newly sensed interrupts. In order to
unmask interrupt on a GPIO line, the driver queues a pair of buffers,
\field{struct virtio_gpio_irq_request} (filled by driver) and \field{struct
virtio_gpio_irq_response} (to be filled by device later), to the \field{eventq}
virtqueue. A separate pair of buffers must be queued for each GPIO line, the
driver wants to configure for interrupts. The device, on sensing an interrupt,
returns the pair of buffers for the respective GPIO line, which also masks the
interrupts. The driver can queue the buffers again to unmask the interrupt.

\begin{lstlisting}
struct virtio_gpio_irq_request {
    le16 gpio;
};
\end{lstlisting}

This structure is filled by the driver and read by the device.

\begin{description}
\item[\field{gpio}] is the GPIO line number, i.e. 0 <= \field{gpio} <
    \field{ngpio}.
\end{description}

\begin{lstlisting}
struct virtio_gpio_irq_response {
    u8 status;
};

/* Possible values of the interrupt status field */
#define VIRTIO_GPIO_IRQ_STATUS_INVALID          0x0
#define VIRTIO_GPIO_IRQ_STATUS_VALID            0x1
\end{lstlisting}

This structure is filled by the device and read by the driver.

\begin{description}
\item[\field{status}] of the interrupt event,
    \field{VIRTIO_GPIO_IRQ_STATUS_VALID} on interrupt and
    \field{VIRTIO_GPIO_IRQ_STATUS_INVALID} to return the buffers back to the
    driver after interrupt is disabled.
\end{description}

\subsubsection{eventq Operation: Message Flow}\label{sec:Device Types / GPIO Device / eventq Operation / Message Flow}

\begin{itemize}
\item The virtio-gpio driver is requested by a client driver to enable interrupt
    for a GPIO line and configure it to a particular trigger type.

\item The driver sends the \field{VIRTIO_GPIO_MSG_SET_IRQ_TYPE} message, over
    the \field{requestq} virtqueue, and the device configures the GPIO line for
    the requested trigger type and enables the interrupt. The interrupt is still
    masked for delivery though. The device shall latch the interrupt from now
    onward for edge trigger type.

\item The driver unmasks the interrupt by queuing a pair of buffers to the
    \field{eventq} virtqueue for the GPIO line. The driver can do this before
    enabling the interrupt as well, though the interrupt must be both unmasked
    and enabled to get delivered at the driver.

\item The driver notifies the device of the presence of new buffers on the
    \field{eventq} virtqueue. The interrupt is fully configured at this point.

\item The device, on sensing an active interrupt on the GPIO line, finds the
    matching buffers (based on GPIO line number) from the \field{eventq}
    virtqueue and update its \field{struct virtio_gpio_irq_response} buffer's
    \field{status} with \field{VIRTIO_GPIO_IRQ_STATUS_VALID} and returns the
    pair of buffers to the device. This results in masking the interrupt as
    well.

\item The device notifies the driver of the presence of returned buffers on the
    \field{eventq} virtqueue.

\item If the GPIO line is configured for level interrupts, the device ignores
    any further interrupt signals on this GPIO line, until the interrupt is
    unmasked again by the driver by making the buffers available to the device.
    Once the interrupt is unmasked again and the interrupt on the line is still
    active, the device shall notify the driver again.

\item If the GPIO line is configured for edge interrupts, the device latches
    the interrupt received for this GPIO line, until the interrupt is unmasked
    again by the driver by making the buffers available to the device. Once the
    interrupt is unmasked again and an interrupt was latched earlier, the
    device shall notify the driver again.

\item The driver on receiving the notification from the device, processes the
    interrupt. The interrupt is masked at the device until the buffers are
    queued again by the driver.

\item In a typical guest operating system kernel, the virtio-gpio driver
    notifies the client driver, that is associated with this GPIO line, to
    process the event. In the case of a level triggered interrupt, the client
    driver shall fully process and acknowledge the event at its source to return
    the line to its inactive state before the interrupt is unmasked again to
    avoid a spurious interrupt.

\item Once the interrupt is handled, the driver may queue a pair of buffers for
    the GPIO line to unmask the interrupt again.

\item The driver can also disable the interrupt by sending the
    \field{VIRTIO_GPIO_MSG_SET_IRQ_TYPE} message, with
    \field{VIRTIO_GPIO_IRQ_TYPE_NONE} trigger type. In that case, the device
    shall return the unused pair of buffers for the GPIO line after setting the
    \field{status} field with \field{VIRTIO_GPIO_IRQ_STATUS_INVALID}.
\end{itemize}

\drivernormative{\subsubsection}{eventq Operation}{Device Types / GPIO Device / eventq Operation}

\begin{itemize}
\item The driver MUST both enable and unmask the interrupt in order to get
    notified for the same.

\item The driver MUST enable the interrupt before unmasking it.

\item To unmask the interrupt, the driver MUST queue a separate pair of buffers
    to the \field{eventq} virtqueue for each GPIO line.

\item The driver MUST NOT add multiple pairs of buffers for the same GPIO line
    on the \field{eventq} virtqueue.
\end{itemize}

\devicenormative{\subsubsection}{eventq Operation}{Device Types / GPIO Device / eventq Operation}

\begin{itemize}
\item The device MUST NOT send an interrupt event to the driver for a GPIO
    line unless the interrupt has been both unmasked and enabled by the
    driver.

\item On receiving \field{VIRTIO_GPIO_MSG_SET_IRQ_TYPE} message, with
    \field{VIRTIO_GPIO_IRQ_TYPE_NONE} trigger type, the device MUST return the
    buffers, if they were received earlier, after setting the \field{status}
    field to \field{VIRTIO_GPIO_IRQ_STATUS_INVALID}.
\end{itemize}
