forked from oasis-tcs/virtio-spec
-
Notifications
You must be signed in to change notification settings - Fork 0
/
virtio-gpio.tex
590 lines (460 loc) · 22.8 KB
/
virtio-gpio.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
\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 is offered by the device.
\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}