diff options
author | Bin Meng | 2018-10-15 04:21:17 -0500 |
---|---|---|
committer | Simon Glass | 2018-11-14 11:16:28 -0600 |
commit | 4135e10732a0eb3c66b34d2fde32eb54d6323fc6 (patch) | |
tree | 39480ae5ccc2769bbc6f76d42921e4ebf5f03cce /drivers | |
parent | 3bf9a8e8460f69022c85f30860911067e4aebca3 (diff) | |
download | u-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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/virtio/Kconfig | 8 | ||||
-rw-r--r-- | drivers/virtio/Makefile | 1 | ||||
-rw-r--r-- | drivers/virtio/virtio_pci.c | 421 | ||||
-rw-r--r-- | drivers/virtio/virtio_pci.h | 173 |
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 | ||
32 | config 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 | |||
32 | config VIRTIO_NET | 40 | config 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 | ||
6 | obj-y += virtio-uclass.o virtio_ring.o | 6 | obj-y += virtio-uclass.o virtio_ring.o |
7 | obj-$(CONFIG_VIRTIO_MMIO) += virtio_mmio.o | 7 | obj-$(CONFIG_VIRTIO_MMIO) += virtio_mmio.o |
8 | obj-$(CONFIG_VIRTIO_PCI) += virtio_pci.o | ||
8 | obj-$(CONFIG_VIRTIO_NET) += virtio_net.o | 9 | obj-$(CONFIG_VIRTIO_NET) += virtio_net.o |
9 | obj-$(CONFIG_VIRTIO_BLK) += virtio_blk.o | 10 | obj-$(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 | */ | ||
94 | struct virtio_pci_priv { | ||
95 | void __iomem *ioaddr; | ||
96 | }; | ||
97 | |||
98 | static 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 | |||
112 | static 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 | |||
126 | static 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 | |||
135 | static 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 | |||
147 | static 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 | |||
163 | static 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 | |||
176 | static 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 | |||
190 | static 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 | |||
221 | error_available: | ||
222 | return ERR_PTR(err); | ||
223 | } | ||
224 | |||
225 | static 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 | |||
238 | static 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 | |||
249 | static 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 | |||
265 | static 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 | |||
278 | static 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 | |||
290 | static 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 | |||
331 | static 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 | |||
344 | U_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 | |||
353 | static 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 | |||
421 | U_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: */ | ||
92 | struct 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 | |||
103 | struct 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: */ | ||
109 | struct 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: */ | ||
135 | struct 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 */ | ||