aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBin Meng2018-10-15 04:21:17 -0500
committerSimon Glass2018-11-14 11:16:28 -0600
commit4135e10732a0eb3c66b34d2fde32eb54d6323fc6 (patch)
tree39480ae5ccc2769bbc6f76d42921e4ebf5f03cce
parent3bf9a8e8460f69022c85f30860911067e4aebca3 (diff)
downloadu-boot-4135e10732a0eb3c66b34d2fde32eb54d6323fc6.tar.gz
u-boot-4135e10732a0eb3c66b34d2fde32eb54d6323fc6.tar.xz
u-boot-4135e10732a0eb3c66b34d2fde32eb54d6323fc6.zip
virtio: Add virtio over pci transport driver
This adds a transport driver that implements UCLASS_VIRTIO for virtio over pci, which is commonly used on x86. It only supports the legacy interface of the pci transport, which is the default device that QEMU emulates. Signed-off-by: Bin Meng <bmeng.cn@gmail.com> Reviewed-by: Simon Glass <sjg@chromium.org>
-rw-r--r--drivers/virtio/Kconfig8
-rw-r--r--drivers/virtio/Makefile1
-rw-r--r--drivers/virtio/virtio_pci.c421
-rw-r--r--drivers/virtio/virtio_pci.h173
4 files changed, 603 insertions, 0 deletions
diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
index b72477ae28..753912f0f9 100644
--- a/drivers/virtio/Kconfig
+++ b/drivers/virtio/Kconfig
@@ -29,6 +29,14 @@ config VIRTIO_MMIO
29 This driver provides support for memory mapped virtio 29 This driver provides support for memory mapped virtio
30 platform device driver. 30 platform device driver.
31 31
32config VIRTIO_PCI
33 bool "PCI driver for virtio devices"
34 depends on DM_PCI
35 select VIRTIO
36 help
37 This driver provides support for virtio based paravirtual device
38 drivers over PCI.
39
32config VIRTIO_NET 40config VIRTIO_NET
33 bool "virtio net driver" 41 bool "virtio net driver"
34 depends on VIRTIO 42 depends on VIRTIO
diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile
index 5fe742815b..5ee6183e60 100644
--- a/drivers/virtio/Makefile
+++ b/drivers/virtio/Makefile
@@ -5,5 +5,6 @@
5 5
6obj-y += virtio-uclass.o virtio_ring.o 6obj-y += virtio-uclass.o virtio_ring.o
7obj-$(CONFIG_VIRTIO_MMIO) += virtio_mmio.o 7obj-$(CONFIG_VIRTIO_MMIO) += virtio_mmio.o
8obj-$(CONFIG_VIRTIO_PCI) += virtio_pci.o
8obj-$(CONFIG_VIRTIO_NET) += virtio_net.o 9obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
9obj-$(CONFIG_VIRTIO_BLK) += virtio_blk.o 10obj-$(CONFIG_VIRTIO_BLK) += virtio_blk.o
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
new file mode 100644
index 0000000000..a3f1083153
--- /dev/null
+++ b/drivers/virtio/virtio_pci.c
@@ -0,0 +1,421 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
4 *
5 * VirtIO PCI bus transport driver
6 * Ported from Linux drivers/virtio/virtio_pci*.c
7 */
8
9#include <common.h>
10#include <dm.h>
11#include <virtio_types.h>
12#include <virtio.h>
13#include <virtio_ring.h>
14#include <dm/device.h>
15#include <linux/compat.h>
16#include <linux/io.h>
17#include "virtio_pci.h"
18
19#define VIRTIO_PCI_DRV_NAME "virtio-pci"
20
21/* PCI device ID in the range 0x1000 to 0x103f */
22#define VIRTIO_PCI_VENDOR_ID 0x1af4
23#define VIRTIO_PCI_DEVICE_ID00 0x1000
24#define VIRTIO_PCI_DEVICE_ID01 0x1001
25#define VIRTIO_PCI_DEVICE_ID02 0x1002
26#define VIRTIO_PCI_DEVICE_ID03 0x1003
27#define VIRTIO_PCI_DEVICE_ID04 0x1004
28#define VIRTIO_PCI_DEVICE_ID05 0x1005
29#define VIRTIO_PCI_DEVICE_ID06 0x1006
30#define VIRTIO_PCI_DEVICE_ID07 0x1007
31#define VIRTIO_PCI_DEVICE_ID08 0x1008
32#define VIRTIO_PCI_DEVICE_ID09 0x1009
33#define VIRTIO_PCI_DEVICE_ID0A 0x100a
34#define VIRTIO_PCI_DEVICE_ID0B 0x100b
35#define VIRTIO_PCI_DEVICE_ID0C 0x100c
36#define VIRTIO_PCI_DEVICE_ID0D 0x100d
37#define VIRTIO_PCI_DEVICE_ID0E 0x100e
38#define VIRTIO_PCI_DEVICE_ID0F 0x100f
39#define VIRTIO_PCI_DEVICE_ID10 0x1010
40#define VIRTIO_PCI_DEVICE_ID11 0x1011
41#define VIRTIO_PCI_DEVICE_ID12 0x1012
42#define VIRTIO_PCI_DEVICE_ID13 0x1013
43#define VIRTIO_PCI_DEVICE_ID14 0x1014
44#define VIRTIO_PCI_DEVICE_ID15 0x1015
45#define VIRTIO_PCI_DEVICE_ID16 0x1016
46#define VIRTIO_PCI_DEVICE_ID17 0x1017
47#define VIRTIO_PCI_DEVICE_ID18 0x1018
48#define VIRTIO_PCI_DEVICE_ID19 0x1019
49#define VIRTIO_PCI_DEVICE_ID1A 0x101a
50#define VIRTIO_PCI_DEVICE_ID1B 0x101b
51#define VIRTIO_PCI_DEVICE_ID1C 0x101c
52#define VIRTIO_PCI_DEVICE_ID1D 0x101d
53#define VIRTIO_PCI_DEVICE_ID1E 0x101e
54#define VIRTIO_PCI_DEVICE_ID1F 0x101f
55#define VIRTIO_PCI_DEVICE_ID20 0x1020
56#define VIRTIO_PCI_DEVICE_ID21 0x1021
57#define VIRTIO_PCI_DEVICE_ID22 0x1022
58#define VIRTIO_PCI_DEVICE_ID23 0x1023
59#define VIRTIO_PCI_DEVICE_ID24 0x1024
60#define VIRTIO_PCI_DEVICE_ID25 0x1025
61#define VIRTIO_PCI_DEVICE_ID26 0x1026
62#define VIRTIO_PCI_DEVICE_ID27 0x1027
63#define VIRTIO_PCI_DEVICE_ID28 0x1028
64#define VIRTIO_PCI_DEVICE_ID29 0x1029
65#define VIRTIO_PCI_DEVICE_ID2A 0x102a
66#define VIRTIO_PCI_DEVICE_ID2B 0x102b
67#define VIRTIO_PCI_DEVICE_ID2C 0x102c
68#define VIRTIO_PCI_DEVICE_ID2D 0x102d
69#define VIRTIO_PCI_DEVICE_ID2E 0x102e
70#define VIRTIO_PCI_DEVICE_ID2F 0x102f
71#define VIRTIO_PCI_DEVICE_ID30 0x1030
72#define VIRTIO_PCI_DEVICE_ID31 0x1031
73#define VIRTIO_PCI_DEVICE_ID32 0x1032
74#define VIRTIO_PCI_DEVICE_ID33 0x1033
75#define VIRTIO_PCI_DEVICE_ID34 0x1034
76#define VIRTIO_PCI_DEVICE_ID35 0x1035
77#define VIRTIO_PCI_DEVICE_ID36 0x1036
78#define VIRTIO_PCI_DEVICE_ID37 0x1037
79#define VIRTIO_PCI_DEVICE_ID38 0x1038
80#define VIRTIO_PCI_DEVICE_ID39 0x1039
81#define VIRTIO_PCI_DEVICE_ID3A 0x103a
82#define VIRTIO_PCI_DEVICE_ID3B 0x103b
83#define VIRTIO_PCI_DEVICE_ID3C 0x103c
84#define VIRTIO_PCI_DEVICE_ID3D 0x103d
85#define VIRTIO_PCI_DEVICE_ID3E 0x103e
86#define VIRTIO_PCI_DEVICE_ID3F 0x103f
87
88/**
89 * virtio pci transport driver private data
90 *
91 * @ioaddr: pci transport device register base
92 * @version: pci transport device version
93 */
94struct virtio_pci_priv {
95 void __iomem *ioaddr;
96};
97
98static int virtio_pci_get_config(struct udevice *udev, unsigned int offset,
99 void *buf, unsigned int len)
100{
101 struct virtio_pci_priv *priv = dev_get_priv(udev);
102 void __iomem *ioaddr = priv->ioaddr + VIRTIO_PCI_CONFIG_OFF(false);
103 u8 *ptr = buf;
104 int i;
105
106 for (i = 0; i < len; i++)
107 ptr[i] = ioread8(ioaddr + i);
108
109 return 0;
110}
111
112static int virtio_pci_set_config(struct udevice *udev, unsigned int offset,
113 const void *buf, unsigned int len)
114{
115 struct virtio_pci_priv *priv = dev_get_priv(udev);
116 void __iomem *ioaddr = priv->ioaddr + VIRTIO_PCI_CONFIG_OFF(false);
117 const u8 *ptr = buf;
118 int i;
119
120 for (i = 0; i < len; i++)
121 iowrite8(ptr[i], ioaddr + i);
122
123 return 0;
124}
125
126static int virtio_pci_get_status(struct udevice *udev, u8 *status)
127{
128 struct virtio_pci_priv *priv = dev_get_priv(udev);
129
130 *status = ioread8(priv->ioaddr + VIRTIO_PCI_STATUS);
131
132 return 0;
133}
134
135static int virtio_pci_set_status(struct udevice *udev, u8 status)
136{
137 struct virtio_pci_priv *priv = dev_get_priv(udev);
138
139 /* We should never be setting status to 0 */
140 WARN_ON(status == 0);
141
142 iowrite8(status, priv->ioaddr + VIRTIO_PCI_STATUS);
143
144 return 0;
145}
146
147static int virtio_pci_reset(struct udevice *udev)
148{
149 struct virtio_pci_priv *priv = dev_get_priv(udev);
150
151 /* 0 status means a reset */
152 iowrite8(0, priv->ioaddr + VIRTIO_PCI_STATUS);
153
154 /*
155 * Flush out the status write, and flush in device writes,
156 * including MSI-X interrupts, if any.
157 */
158 ioread8(priv->ioaddr + VIRTIO_PCI_STATUS);
159
160 return 0;
161}
162
163static int virtio_pci_get_features(struct udevice *udev, u64 *features)
164{
165 struct virtio_pci_priv *priv = dev_get_priv(udev);
166
167 /*
168 * When someone needs more than 32 feature bits, we'll need to
169 * steal a bit to indicate that the rest are somewhere else.
170 */
171 *features = ioread32(priv->ioaddr + VIRTIO_PCI_HOST_FEATURES);
172
173 return 0;
174}
175
176static int virtio_pci_set_features(struct udevice *udev)
177{
178 struct virtio_pci_priv *priv = dev_get_priv(udev);
179 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
180
181 /* Make sure we don't have any features > 32 bits! */
182 WARN_ON((u32)uc_priv->features != uc_priv->features);
183
184 /* We only support 32 feature bits */
185 iowrite32(uc_priv->features, priv->ioaddr + VIRTIO_PCI_GUEST_FEATURES);
186
187 return 0;
188}
189
190static struct virtqueue *virtio_pci_setup_vq(struct udevice *udev,
191 unsigned int index)
192{
193 struct virtio_pci_priv *priv = dev_get_priv(udev);
194 struct virtqueue *vq;
195 unsigned int num;
196 int err;
197
198 /* Select the queue we're interested in */
199 iowrite16(index, priv->ioaddr + VIRTIO_PCI_QUEUE_SEL);
200
201 /* Check if queue is either not available or already active */
202 num = ioread16(priv->ioaddr + VIRTIO_PCI_QUEUE_NUM);
203 if (!num || ioread32(priv->ioaddr + VIRTIO_PCI_QUEUE_PFN)) {
204 err = -ENOENT;
205 goto error_available;
206 }
207
208 /* Create the vring */
209 vq = vring_create_virtqueue(index, num, VIRTIO_PCI_VRING_ALIGN, udev);
210 if (!vq) {
211 err = -ENOMEM;
212 goto error_available;
213 }
214
215 /* Activate the queue */
216 iowrite32(virtqueue_get_desc_addr(vq) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT,
217 priv->ioaddr + VIRTIO_PCI_QUEUE_PFN);
218
219 return vq;
220
221error_available:
222 return ERR_PTR(err);
223}
224
225static void virtio_pci_del_vq(struct virtqueue *vq)
226{
227 struct virtio_pci_priv *priv = dev_get_priv(vq->vdev);
228 unsigned int index = vq->index;
229
230 iowrite16(index, priv->ioaddr + VIRTIO_PCI_QUEUE_SEL);
231
232 /* Select and deactivate the queue */
233 iowrite32(0, priv->ioaddr + VIRTIO_PCI_QUEUE_PFN);
234
235 vring_del_virtqueue(vq);
236}
237
238static int virtio_pci_del_vqs(struct udevice *udev)
239{
240 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
241 struct virtqueue *vq, *n;
242
243 list_for_each_entry_safe(vq, n, &uc_priv->vqs, list)
244 virtio_pci_del_vq(vq);
245
246 return 0;
247}
248
249static int virtio_pci_find_vqs(struct udevice *udev, unsigned int nvqs,
250 struct virtqueue *vqs[])
251{
252 int i;
253
254 for (i = 0; i < nvqs; ++i) {
255 vqs[i] = virtio_pci_setup_vq(udev, i);
256 if (IS_ERR(vqs[i])) {
257 virtio_pci_del_vqs(udev);
258 return PTR_ERR(vqs[i]);
259 }
260 }
261
262 return 0;
263}
264
265static int virtio_pci_notify(struct udevice *udev, struct virtqueue *vq)
266{
267 struct virtio_pci_priv *priv = dev_get_priv(udev);
268
269 /*
270 * We write the queue's selector into the notification register
271 * to signal the other end
272 */
273 iowrite16(vq->index, priv->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY);
274
275 return 0;
276}
277
278static int virtio_pci_bind(struct udevice *udev)
279{
280 static int num_devs;
281 char name[20];
282
283 /* Create a unique device name for PCI type devices */
284 sprintf(name, "%s#%u", VIRTIO_PCI_DRV_NAME, num_devs++);
285 device_set_name(udev, name);
286
287 return 0;
288}
289
290static int virtio_pci_probe(struct udevice *udev)
291{
292 struct pci_child_platdata *pplat = dev_get_parent_platdata(udev);
293 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
294 struct virtio_pci_priv *priv = dev_get_priv(udev);
295 u16 subvendor, subdevice;
296 u8 revision;
297
298 /* We only own devices >= 0x1000 and <= 0x103f: leave the rest. */
299 if (pplat->device < 0x1000 || pplat->device > 0x103f)
300 return -ENODEV;
301
302 /* Transitional devices must have a PCI revision ID of 0 */
303 dm_pci_read_config8(udev, PCI_REVISION_ID, &revision);
304 if (revision != VIRTIO_PCI_ABI_VERSION) {
305 printf("(%s): virtio_pci expected ABI version %d, got %d\n",
306 udev->name, VIRTIO_PCI_ABI_VERSION, revision);
307 return -ENODEV;
308 }
309
310 /*
311 * Transitional devices must have the PCI subsystem device ID matching
312 * the virtio device ID
313 */
314 dm_pci_read_config16(udev, PCI_SUBSYSTEM_ID, &subdevice);
315 dm_pci_read_config16(udev, PCI_SUBSYSTEM_VENDOR_ID, &subvendor);
316 uc_priv->device = subdevice;
317 uc_priv->vendor = subvendor;
318
319 priv->ioaddr = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0, PCI_REGION_IO);
320 if (!priv->ioaddr)
321 return -ENXIO;
322 debug("(%s): virtio legacy device reg base %04lx\n",
323 udev->name, (ulong)priv->ioaddr);
324
325 debug("(%s): device (%d) vendor (%08x) version (%d)\n", udev->name,
326 uc_priv->device, uc_priv->vendor, revision);
327
328 return 0;
329}
330
331static const struct dm_virtio_ops virtio_pci_ops = {
332 .get_config = virtio_pci_get_config,
333 .set_config = virtio_pci_set_config,
334 .get_status = virtio_pci_get_status,
335 .set_status = virtio_pci_set_status,
336 .reset = virtio_pci_reset,
337 .get_features = virtio_pci_get_features,
338 .set_features = virtio_pci_set_features,
339 .find_vqs = virtio_pci_find_vqs,
340 .del_vqs = virtio_pci_del_vqs,
341 .notify = virtio_pci_notify,
342};
343
344U_BOOT_DRIVER(virtio_pci) = {
345 .name = VIRTIO_PCI_DRV_NAME,
346 .id = UCLASS_VIRTIO,
347 .ops = &virtio_pci_ops,
348 .bind = virtio_pci_bind,
349 .probe = virtio_pci_probe,
350 .priv_auto_alloc_size = sizeof(struct virtio_pci_priv),
351};
352
353static struct pci_device_id virtio_pci_supported[] = {
354 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID00) },
355 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID01) },
356 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID02) },
357 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID03) },
358 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID04) },
359 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID05) },
360 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID06) },
361 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID07) },
362 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID08) },
363 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID09) },
364 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID0A) },
365 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID0B) },
366 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID0C) },
367 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID0D) },
368 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID0E) },
369 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID0F) },
370 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID10) },
371 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID11) },
372 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID12) },
373 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID13) },
374 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID14) },
375 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID15) },
376 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID16) },
377 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID17) },
378 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID18) },
379 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID19) },
380 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID1A) },
381 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID1B) },
382 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID1C) },
383 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID1D) },
384 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID1E) },
385 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID1F) },
386 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID20) },
387 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID21) },
388 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID22) },
389 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID23) },
390 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID24) },
391 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID25) },
392 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID26) },
393 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID27) },
394 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID28) },
395 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID29) },
396 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID2A) },
397 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID2B) },
398 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID2C) },
399 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID2D) },
400 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID2E) },
401 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID2F) },
402 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID30) },
403 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID31) },
404 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID32) },
405 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID33) },
406 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID34) },
407 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID35) },
408 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID36) },
409 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID37) },
410 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID38) },
411 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID39) },
412 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID3A) },
413 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID3B) },
414 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID3C) },
415 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID3D) },
416 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID3E) },
417 { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID3F) },
418 {},
419};
420
421U_BOOT_PCI_DEVICE(virtio_pci, virtio_pci_supported);
diff --git a/drivers/virtio/virtio_pci.h b/drivers/virtio/virtio_pci.h
new file mode 100644
index 0000000000..cc753ed7b3
--- /dev/null
+++ b/drivers/virtio/virtio_pci.h
@@ -0,0 +1,173 @@
1/* SPDX-License-Identifier: BSD-3-Clause */
2/*
3 * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
4 *
5 * From Linux kernel include/uapi/linux/virtio_pci.h
6 */
7
8#ifndef _LINUX_VIRTIO_PCI_H
9#define _LINUX_VIRTIO_PCI_H
10
11#ifndef VIRTIO_PCI_NO_LEGACY
12
13/* A 32-bit r/o bitmask of the features supported by the host */
14#define VIRTIO_PCI_HOST_FEATURES 0
15
16/* A 32-bit r/w bitmask of features activated by the guest */
17#define VIRTIO_PCI_GUEST_FEATURES 4
18
19/* A 32-bit r/w PFN for the currently selected queue */
20#define VIRTIO_PCI_QUEUE_PFN 8
21
22/* A 16-bit r/o queue size for the currently selected queue */
23#define VIRTIO_PCI_QUEUE_NUM 12
24
25/* A 16-bit r/w queue selector */
26#define VIRTIO_PCI_QUEUE_SEL 14
27
28/* A 16-bit r/w queue notifier */
29#define VIRTIO_PCI_QUEUE_NOTIFY 16
30
31/* An 8-bit device status register */
32#define VIRTIO_PCI_STATUS 18
33
34/*
35 * An 8-bit r/o interrupt status register. Reading the value will return the
36 * current contents of the ISR and will also clear it. This is effectively
37 * a read-and-acknowledge.
38 */
39#define VIRTIO_PCI_ISR 19
40
41/* MSI-X registers: only enabled if MSI-X is enabled */
42
43/* A 16-bit vector for configuration changes */
44#define VIRTIO_MSI_CONFIG_VECTOR 20
45/* A 16-bit vector for selected queue notifications */
46#define VIRTIO_MSI_QUEUE_VECTOR 22
47
48/*
49 * The remaining space is defined by each driver as the per-driver
50 * configuration space
51 */
52#define VIRTIO_PCI_CONFIG_OFF(msix) ((msix) ? 24 : 20)
53
54/* Virtio ABI version, this must match exactly */
55#define VIRTIO_PCI_ABI_VERSION 0
56
57/*
58 * How many bits to shift physical queue address written to QUEUE_PFN.
59 * 12 is historical, and due to x86 page size.
60 */
61#define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12
62
63/*
64 * The alignment to use between consumer and producer parts of vring.
65 * x86 pagesize again.
66 */
67#define VIRTIO_PCI_VRING_ALIGN 4096
68
69#endif /* VIRTIO_PCI_NO_LEGACY */
70
71/* The bit of the ISR which indicates a device configuration change */
72#define VIRTIO_PCI_ISR_CONFIG 0x2
73/* Vector value used to disable MSI for queue */
74#define VIRTIO_MSI_NO_VECTOR 0xffff
75
76#ifndef VIRTIO_PCI_NO_MODERN
77
78/* IDs for different capabilities. Must all exist. */
79
80/* Common configuration */
81#define VIRTIO_PCI_CAP_COMMON_CFG 1
82/* Notifications */
83#define VIRTIO_PCI_CAP_NOTIFY_CFG 2
84/* ISR access */
85#define VIRTIO_PCI_CAP_ISR_CFG 3
86/* Device specific configuration */
87#define VIRTIO_PCI_CAP_DEVICE_CFG 4
88/* PCI configuration access */
89#define VIRTIO_PCI_CAP_PCI_CFG 5
90
91/* This is the PCI capability header: */
92struct virtio_pci_cap {
93 __u8 cap_vndr; /* Generic PCI field: PCI_CAP_ID_VNDR */
94 __u8 cap_next; /* Generic PCI field: next ptr */
95 __u8 cap_len; /* Generic PCI field: capability length */
96 __u8 cfg_type; /* Identifies the structure */
97 __u8 bar; /* Where to find it */
98 __u8 padding[3]; /* Pad to full dword */
99 __le32 offset; /* Offset within bar */
100 __le32 length; /* Length of the structure, in bytes */
101};
102
103struct virtio_pci_notify_cap {
104 struct virtio_pci_cap cap;
105 __le32 notify_off_multiplier; /* Multiplier for queue_notify_off */
106};
107
108/* Fields in VIRTIO_PCI_CAP_COMMON_CFG: */
109struct virtio_pci_common_cfg {
110 /* About the whole device */
111 __le32 device_feature_select; /* read-write */
112 __le32 device_feature; /* read-only */
113 __le32 guest_feature_select; /* read-write */
114 __le32 guest_feature; /* read-write */
115 __le16 msix_config; /* read-write */
116 __le16 num_queues; /* read-only */
117 __u8 device_status; /* read-write */
118 __u8 config_generation; /* read-only */
119
120 /* About a specific virtqueue */
121 __le16 queue_select; /* read-write */
122 __le16 queue_size; /* read-write, power of 2 */
123 __le16 queue_msix_vector; /* read-write */
124 __le16 queue_enable; /* read-write */
125 __le16 queue_notify_off; /* read-only */
126 __le32 queue_desc_lo; /* read-write */
127 __le32 queue_desc_hi; /* read-write */
128 __le32 queue_avail_lo; /* read-write */
129 __le32 queue_avail_hi; /* read-write */
130 __le32 queue_used_lo; /* read-write */
131 __le32 queue_used_hi; /* read-write */
132};
133
134/* Fields in VIRTIO_PCI_CAP_PCI_CFG: */
135struct virtio_pci_cfg_cap {
136 struct virtio_pci_cap cap;
137 __u8 pci_cfg_data[4]; /* Data for BAR access */
138};
139
140/* Macro versions of offsets for the Old Timers! */
141#define VIRTIO_PCI_CAP_VNDR 0
142#define VIRTIO_PCI_CAP_NEXT 1
143#define VIRTIO_PCI_CAP_LEN 2
144#define VIRTIO_PCI_CAP_CFG_TYPE 3
145#define VIRTIO_PCI_CAP_BAR 4
146#define VIRTIO_PCI_CAP_OFFSET 8
147#define VIRTIO_PCI_CAP_LENGTH 12
148
149#define VIRTIO_PCI_NOTIFY_CAP_MULT 16
150
151#define VIRTIO_PCI_COMMON_DFSELECT 0
152#define VIRTIO_PCI_COMMON_DF 4
153#define VIRTIO_PCI_COMMON_GFSELECT 8
154#define VIRTIO_PCI_COMMON_GF 12
155#define VIRTIO_PCI_COMMON_MSIX 16
156#define VIRTIO_PCI_COMMON_NUMQ 18
157#define VIRTIO_PCI_COMMON_STATUS 20
158#define VIRTIO_PCI_COMMON_CFGGENERATION 21
159#define VIRTIO_PCI_COMMON_Q_SELECT 22
160#define VIRTIO_PCI_COMMON_Q_SIZE 24
161#define VIRTIO_PCI_COMMON_Q_MSIX 26
162#define VIRTIO_PCI_COMMON_Q_ENABLE 28
163#define VIRTIO_PCI_COMMON_Q_NOFF 30
164#define VIRTIO_PCI_COMMON_Q_DESCLO 32
165#define VIRTIO_PCI_COMMON_Q_DESCHI 36
166#define VIRTIO_PCI_COMMON_Q_AVAILLO 40
167#define VIRTIO_PCI_COMMON_Q_AVAILHI 44
168#define VIRTIO_PCI_COMMON_Q_USEDLO 48
169#define VIRTIO_PCI_COMMON_Q_USEDHI 52
170
171#endif /* VIRTIO_PCI_NO_MODERN */
172
173#endif /* _LINUX_VIRTIO_PCI_H */