uboot/drivers/virtio/virtio_pci_modern.c
<<
>>
Prefs
   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.m"
  20
  21/* PCI device ID in the range 0x1040 to 0x107f */
  22#define VIRTIO_PCI_VENDOR_ID    0x1af4
  23#define VIRTIO_PCI_DEVICE_ID00  0x1040
  24#define VIRTIO_PCI_DEVICE_ID01  0x1041
  25#define VIRTIO_PCI_DEVICE_ID02  0x1042
  26#define VIRTIO_PCI_DEVICE_ID03  0x1043
  27#define VIRTIO_PCI_DEVICE_ID04  0x1044
  28#define VIRTIO_PCI_DEVICE_ID05  0x1045
  29#define VIRTIO_PCI_DEVICE_ID06  0x1046
  30#define VIRTIO_PCI_DEVICE_ID07  0x1047
  31#define VIRTIO_PCI_DEVICE_ID08  0x1048
  32#define VIRTIO_PCI_DEVICE_ID09  0x1049
  33#define VIRTIO_PCI_DEVICE_ID0A  0x104a
  34#define VIRTIO_PCI_DEVICE_ID0B  0x104b
  35#define VIRTIO_PCI_DEVICE_ID0C  0x104c
  36#define VIRTIO_PCI_DEVICE_ID0D  0x104d
  37#define VIRTIO_PCI_DEVICE_ID0E  0x104e
  38#define VIRTIO_PCI_DEVICE_ID0F  0x104f
  39#define VIRTIO_PCI_DEVICE_ID10  0x1050
  40#define VIRTIO_PCI_DEVICE_ID11  0x1051
  41#define VIRTIO_PCI_DEVICE_ID12  0x1052
  42#define VIRTIO_PCI_DEVICE_ID13  0x1053
  43#define VIRTIO_PCI_DEVICE_ID14  0x1054
  44#define VIRTIO_PCI_DEVICE_ID15  0x1055
  45#define VIRTIO_PCI_DEVICE_ID16  0x1056
  46#define VIRTIO_PCI_DEVICE_ID17  0x1057
  47#define VIRTIO_PCI_DEVICE_ID18  0x1058
  48#define VIRTIO_PCI_DEVICE_ID19  0x1059
  49#define VIRTIO_PCI_DEVICE_ID1A  0x105a
  50#define VIRTIO_PCI_DEVICE_ID1B  0x105b
  51#define VIRTIO_PCI_DEVICE_ID1C  0x105c
  52#define VIRTIO_PCI_DEVICE_ID1D  0x105d
  53#define VIRTIO_PCI_DEVICE_ID1E  0x105e
  54#define VIRTIO_PCI_DEVICE_ID1F  0x105f
  55#define VIRTIO_PCI_DEVICE_ID20  0x1060
  56#define VIRTIO_PCI_DEVICE_ID21  0x1061
  57#define VIRTIO_PCI_DEVICE_ID22  0x1062
  58#define VIRTIO_PCI_DEVICE_ID23  0x1063
  59#define VIRTIO_PCI_DEVICE_ID24  0x1064
  60#define VIRTIO_PCI_DEVICE_ID25  0x1065
  61#define VIRTIO_PCI_DEVICE_ID26  0x1066
  62#define VIRTIO_PCI_DEVICE_ID27  0x1067
  63#define VIRTIO_PCI_DEVICE_ID28  0x1068
  64#define VIRTIO_PCI_DEVICE_ID29  0x1069
  65#define VIRTIO_PCI_DEVICE_ID2A  0x106a
  66#define VIRTIO_PCI_DEVICE_ID2B  0x106b
  67#define VIRTIO_PCI_DEVICE_ID2C  0x106c
  68#define VIRTIO_PCI_DEVICE_ID2D  0x106d
  69#define VIRTIO_PCI_DEVICE_ID2E  0x106e
  70#define VIRTIO_PCI_DEVICE_ID2F  0x106f
  71#define VIRTIO_PCI_DEVICE_ID30  0x1070
  72#define VIRTIO_PCI_DEVICE_ID31  0x1071
  73#define VIRTIO_PCI_DEVICE_ID32  0x1072
  74#define VIRTIO_PCI_DEVICE_ID33  0x1073
  75#define VIRTIO_PCI_DEVICE_ID34  0x1074
  76#define VIRTIO_PCI_DEVICE_ID35  0x1075
  77#define VIRTIO_PCI_DEVICE_ID36  0x1076
  78#define VIRTIO_PCI_DEVICE_ID37  0x1077
  79#define VIRTIO_PCI_DEVICE_ID38  0x1078
  80#define VIRTIO_PCI_DEVICE_ID39  0x1079
  81#define VIRTIO_PCI_DEVICE_ID3A  0x107a
  82#define VIRTIO_PCI_DEVICE_ID3B  0x107b
  83#define VIRTIO_PCI_DEVICE_ID3C  0x107c
  84#define VIRTIO_PCI_DEVICE_ID3D  0x107d
  85#define VIRTIO_PCI_DEVICE_ID3E  0x107e
  86#define VIRTIO_PCI_DEVICE_ID3F  0x107f
  87
  88/**
  89 * virtio pci transport driver private data
  90 *
  91 * @common: pci transport device common register block base
  92 * @notify_base: pci transport device notify register block base
  93 * @device: pci transport device device-specific register block base
  94 * @device_len: pci transport device device-specific register block length
  95 * @notify_offset_multiplier: multiply queue_notify_off by this value
  96 */
  97struct virtio_pci_priv {
  98        struct virtio_pci_common_cfg __iomem *common;
  99        void __iomem *notify_base;
 100        void __iomem *device;
 101        u32 device_len;
 102        u32 notify_offset_multiplier;
 103};
 104
 105static int virtio_pci_get_config(struct udevice *udev, unsigned int offset,
 106                                 void *buf, unsigned int len)
 107{
 108        struct virtio_pci_priv *priv = dev_get_priv(udev);
 109        u8 b;
 110        __le16 w;
 111        __le32 l;
 112
 113        WARN_ON(offset + len > priv->device_len);
 114
 115        switch (len) {
 116        case 1:
 117                b = ioread8(priv->device + offset);
 118                memcpy(buf, &b, sizeof(b));
 119                break;
 120        case 2:
 121                w = cpu_to_le16(ioread16(priv->device + offset));
 122                memcpy(buf, &w, sizeof(w));
 123                break;
 124        case 4:
 125                l = cpu_to_le32(ioread32(priv->device + offset));
 126                memcpy(buf, &l, sizeof(l));
 127                break;
 128        case 8:
 129                l = cpu_to_le32(ioread32(priv->device + offset));
 130                memcpy(buf, &l, sizeof(l));
 131                l = cpu_to_le32(ioread32(priv->device + offset + sizeof(l)));
 132                memcpy(buf + sizeof(l), &l, sizeof(l));
 133                break;
 134        default:
 135                WARN_ON(true);
 136        }
 137
 138        return 0;
 139}
 140
 141static int virtio_pci_set_config(struct udevice *udev, unsigned int offset,
 142                                 const void *buf, unsigned int len)
 143{
 144        struct virtio_pci_priv *priv = dev_get_priv(udev);
 145        u8 b;
 146        __le16 w;
 147        __le32 l;
 148
 149        WARN_ON(offset + len > priv->device_len);
 150
 151        switch (len) {
 152        case 1:
 153                memcpy(&b, buf, sizeof(b));
 154                iowrite8(b, priv->device + offset);
 155                break;
 156        case 2:
 157                memcpy(&w, buf, sizeof(w));
 158                iowrite16(le16_to_cpu(w), priv->device + offset);
 159                break;
 160        case 4:
 161                memcpy(&l, buf, sizeof(l));
 162                iowrite32(le32_to_cpu(l), priv->device + offset);
 163                break;
 164        case 8:
 165                memcpy(&l, buf, sizeof(l));
 166                iowrite32(le32_to_cpu(l), priv->device + offset);
 167                memcpy(&l, buf + sizeof(l), sizeof(l));
 168                iowrite32(le32_to_cpu(l), priv->device + offset + sizeof(l));
 169                break;
 170        default:
 171                WARN_ON(true);
 172        }
 173
 174        return 0;
 175}
 176
 177static int virtio_pci_generation(struct udevice *udev, u32 *counter)
 178{
 179        struct virtio_pci_priv *priv = dev_get_priv(udev);
 180
 181        *counter = ioread8(&priv->common->config_generation);
 182
 183        return 0;
 184}
 185
 186static int virtio_pci_get_status(struct udevice *udev, u8 *status)
 187{
 188        struct virtio_pci_priv *priv = dev_get_priv(udev);
 189
 190        *status = ioread8(&priv->common->device_status);
 191
 192        return 0;
 193}
 194
 195static int virtio_pci_set_status(struct udevice *udev, u8 status)
 196{
 197        struct virtio_pci_priv *priv = dev_get_priv(udev);
 198
 199        /* We should never be setting status to 0 */
 200        WARN_ON(status == 0);
 201
 202        iowrite8(status, &priv->common->device_status);
 203
 204        return 0;
 205}
 206
 207static int virtio_pci_reset(struct udevice *udev)
 208{
 209        struct virtio_pci_priv *priv = dev_get_priv(udev);
 210
 211        /* 0 status means a reset */
 212        iowrite8(0, &priv->common->device_status);
 213
 214        /*
 215         * After writing 0 to device_status, the driver MUST wait for a read
 216         * of device_status to return 0 before reinitializing the device.
 217         * This will flush out the status write, and flush in device writes,
 218         * including MSI-X interrupts, if any.
 219         */
 220        while (ioread8(&priv->common->device_status))
 221                udelay(1000);
 222
 223        return 0;
 224}
 225
 226static int virtio_pci_get_features(struct udevice *udev, u64 *features)
 227{
 228        struct virtio_pci_priv *priv = dev_get_priv(udev);
 229
 230        iowrite32(0, &priv->common->device_feature_select);
 231        *features = ioread32(&priv->common->device_feature);
 232        iowrite32(1, &priv->common->device_feature_select);
 233        *features |= ((u64)ioread32(&priv->common->device_feature) << 32);
 234
 235        return 0;
 236}
 237
 238static int virtio_pci_set_features(struct udevice *udev)
 239{
 240        struct virtio_pci_priv *priv = dev_get_priv(udev);
 241        struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
 242
 243        if (!__virtio_test_bit(udev, VIRTIO_F_VERSION_1)) {
 244                debug("virtio: device uses modern interface but does not have VIRTIO_F_VERSION_1\n");
 245                return -EINVAL;
 246        }
 247
 248        iowrite32(0, &priv->common->guest_feature_select);
 249        iowrite32((u32)uc_priv->features, &priv->common->guest_feature);
 250        iowrite32(1, &priv->common->guest_feature_select);
 251        iowrite32(uc_priv->features >> 32, &priv->common->guest_feature);
 252
 253        return 0;
 254}
 255
 256static struct virtqueue *virtio_pci_setup_vq(struct udevice *udev,
 257                                             unsigned int index)
 258{
 259        struct virtio_pci_priv *priv = dev_get_priv(udev);
 260        struct virtio_pci_common_cfg __iomem *cfg = priv->common;
 261        struct virtqueue *vq;
 262        u16 num;
 263        u64 addr;
 264        int err;
 265
 266        if (index >= ioread16(&cfg->num_queues))
 267                return ERR_PTR(-ENOENT);
 268
 269        /* Select the queue we're interested in */
 270        iowrite16(index, &cfg->queue_select);
 271
 272        /* Check if queue is either not available or already active */
 273        num = ioread16(&cfg->queue_size);
 274        if (!num || ioread16(&cfg->queue_enable))
 275                return ERR_PTR(-ENOENT);
 276
 277        if (num & (num - 1)) {
 278                printf("(%s): bad queue size %u", udev->name, num);
 279                return ERR_PTR(-EINVAL);
 280        }
 281
 282        /* Create the vring */
 283        vq = vring_create_virtqueue(index, num, VIRTIO_PCI_VRING_ALIGN, udev);
 284        if (!vq) {
 285                err = -ENOMEM;
 286                goto error_available;
 287        }
 288
 289        /* Activate the queue */
 290        iowrite16(virtqueue_get_vring_size(vq), &cfg->queue_size);
 291
 292        addr = virtqueue_get_desc_addr(vq);
 293        iowrite32((u32)addr, &cfg->queue_desc_lo);
 294        iowrite32(addr >> 32, &cfg->queue_desc_hi);
 295
 296        addr = virtqueue_get_avail_addr(vq);
 297        iowrite32((u32)addr, &cfg->queue_avail_lo);
 298        iowrite32(addr >> 32, &cfg->queue_avail_hi);
 299
 300        addr = virtqueue_get_used_addr(vq);
 301        iowrite32((u32)addr, &cfg->queue_used_lo);
 302        iowrite32(addr >> 32, &cfg->queue_used_hi);
 303
 304        iowrite16(1, &cfg->queue_enable);
 305
 306        return vq;
 307
 308error_available:
 309        return ERR_PTR(err);
 310}
 311
 312static void virtio_pci_del_vq(struct virtqueue *vq)
 313{
 314        struct virtio_pci_priv *priv = dev_get_priv(vq->vdev);
 315        unsigned int index = vq->index;
 316
 317        iowrite16(index, &priv->common->queue_select);
 318
 319        /* Select and deactivate the queue */
 320        iowrite16(0, &priv->common->queue_enable);
 321
 322        vring_del_virtqueue(vq);
 323}
 324
 325static int virtio_pci_del_vqs(struct udevice *udev)
 326{
 327        struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
 328        struct virtqueue *vq, *n;
 329
 330        list_for_each_entry_safe(vq, n, &uc_priv->vqs, list)
 331                virtio_pci_del_vq(vq);
 332
 333        return 0;
 334}
 335
 336static int virtio_pci_find_vqs(struct udevice *udev, unsigned int nvqs,
 337                               struct virtqueue *vqs[])
 338{
 339        int i;
 340
 341        for (i = 0; i < nvqs; ++i) {
 342                vqs[i] = virtio_pci_setup_vq(udev, i);
 343                if (IS_ERR(vqs[i])) {
 344                        virtio_pci_del_vqs(udev);
 345                        return PTR_ERR(vqs[i]);
 346                }
 347        }
 348
 349        return 0;
 350}
 351
 352static int virtio_pci_notify(struct udevice *udev, struct virtqueue *vq)
 353{
 354        struct virtio_pci_priv *priv = dev_get_priv(udev);
 355        u16 off;
 356
 357        /* Select the queue we're interested in */
 358        iowrite16(vq->index, &priv->common->queue_select);
 359
 360        /* get offset of notification word for this vq */
 361        off = ioread16(&priv->common->queue_notify_off);
 362
 363        /*
 364         * We write the queue's selector into the notification register
 365         * to signal the other end
 366         */
 367        iowrite16(vq->index,
 368                  priv->notify_base + off * priv->notify_offset_multiplier);
 369
 370        return 0;
 371}
 372
 373/**
 374 * virtio_pci_find_capability - walk capabilities to find device info
 375 *
 376 * @udev:       the transport device
 377 * @cfg_type:   the VIRTIO_PCI_CAP_* value we seek
 378 *
 379 * @return offset of the configuration structure
 380 */
 381static int virtio_pci_find_capability(struct udevice *udev, u8 cfg_type)
 382{
 383        int pos;
 384        int offset;
 385        u8 type, bar;
 386
 387        for (pos = dm_pci_find_capability(udev, PCI_CAP_ID_VNDR);
 388             pos > 0;
 389             pos = dm_pci_find_next_capability(udev, pos, PCI_CAP_ID_VNDR)) {
 390                offset = pos + offsetof(struct virtio_pci_cap, cfg_type);
 391                dm_pci_read_config8(udev, offset, &type);
 392                offset = pos + offsetof(struct virtio_pci_cap, bar);
 393                dm_pci_read_config8(udev, offset, &bar);
 394
 395                /* Ignore structures with reserved BAR values */
 396                if (bar > 0x5)
 397                        continue;
 398
 399                if (type == cfg_type)
 400                        return pos;
 401        }
 402
 403        return 0;
 404}
 405
 406/**
 407 * virtio_pci_map_capability - map base address of the capability
 408 *
 409 * @udev:       the transport device
 410 * @off:        offset of the configuration structure
 411 *
 412 * @return base address of the capability
 413 */
 414static void __iomem *virtio_pci_map_capability(struct udevice *udev, int off)
 415{
 416        u8 bar;
 417        u32 offset;
 418        ulong base;
 419        void __iomem *p;
 420
 421        if (!off)
 422                return NULL;
 423
 424        offset = off + offsetof(struct virtio_pci_cap, bar);
 425        dm_pci_read_config8(udev, offset, &bar);
 426        offset = off + offsetof(struct virtio_pci_cap, offset);
 427        dm_pci_read_config32(udev, offset, &offset);
 428
 429        /*
 430         * TODO: adding 64-bit BAR support
 431         *
 432         * Per spec, the BAR is permitted to be either 32-bit or 64-bit.
 433         * For simplicity, only read the BAR address as 32-bit.
 434         */
 435        base = dm_pci_read_bar32(udev, bar);
 436        p = (void __iomem *)base + offset;
 437
 438        return p;
 439}
 440
 441static int virtio_pci_bind(struct udevice *udev)
 442{
 443        static int num_devs;
 444        char name[20];
 445
 446        /* Create a unique device name  */
 447        sprintf(name, "%s#%u", VIRTIO_PCI_DRV_NAME, num_devs++);
 448        device_set_name(udev, name);
 449
 450        return 0;
 451}
 452
 453static int virtio_pci_probe(struct udevice *udev)
 454{
 455        struct pci_child_platdata *pplat = dev_get_parent_platdata(udev);
 456        struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
 457        struct virtio_pci_priv *priv = dev_get_priv(udev);
 458        u16 subvendor;
 459        u8 revision;
 460        int common, notify, device;
 461        int offset;
 462
 463        /* We only own devices >= 0x1040 and <= 0x107f: leave the rest. */
 464        if (pplat->device < 0x1040 || pplat->device > 0x107f)
 465                return -ENODEV;
 466
 467        /* Transitional devices must not have a PCI revision ID of 0 */
 468        dm_pci_read_config8(udev, PCI_REVISION_ID, &revision);
 469
 470        /* Modern devices: simply use PCI device id, but start from 0x1040. */
 471        uc_priv->device = pplat->device - 0x1040;
 472        dm_pci_read_config16(udev, PCI_SUBSYSTEM_VENDOR_ID, &subvendor);
 473        uc_priv->vendor = subvendor;
 474
 475        /* Check for a common config: if not, use legacy mode (bar 0) */
 476        common = virtio_pci_find_capability(udev, VIRTIO_PCI_CAP_COMMON_CFG);
 477        if (!common) {
 478                printf("(%s): leaving for legacy driver\n", udev->name);
 479                return -ENODEV;
 480        }
 481
 482        /* If common is there, notify should be too */
 483        notify = virtio_pci_find_capability(udev, VIRTIO_PCI_CAP_NOTIFY_CFG);
 484        if (!notify) {
 485                printf("(%s): missing capabilities %i/%i\n", udev->name,
 486                       common, notify);
 487                return -EINVAL;
 488        }
 489
 490        /*
 491         * Device capability is only mandatory for devices that have
 492         * device-specific configuration.
 493         */
 494        device = virtio_pci_find_capability(udev, VIRTIO_PCI_CAP_DEVICE_CFG);
 495        if (device) {
 496                offset = notify + offsetof(struct virtio_pci_cap, length);
 497                dm_pci_read_config32(udev, offset, &priv->device_len);
 498        }
 499
 500        /* Map configuration structures */
 501        priv->common = virtio_pci_map_capability(udev, common);
 502        priv->notify_base = virtio_pci_map_capability(udev, notify);
 503        priv->device = virtio_pci_map_capability(udev, device);
 504        debug("(%p): common @ %p, notify base @ %p, device @ %p\n",
 505              udev, priv->common, priv->notify_base, priv->device);
 506
 507        /* Read notify_off_multiplier from config space */
 508        offset = notify + offsetof(struct virtio_pci_notify_cap,
 509                                   notify_off_multiplier);
 510        dm_pci_read_config32(udev, offset, &priv->notify_offset_multiplier);
 511
 512        debug("(%s): device (%d) vendor (%08x) version (%d)\n", udev->name,
 513              uc_priv->device, uc_priv->vendor, revision);
 514
 515        return 0;
 516}
 517
 518static const struct dm_virtio_ops virtio_pci_ops = {
 519        .get_config     = virtio_pci_get_config,
 520        .set_config     = virtio_pci_set_config,
 521        .generation     = virtio_pci_generation,
 522        .get_status     = virtio_pci_get_status,
 523        .set_status     = virtio_pci_set_status,
 524        .reset          = virtio_pci_reset,
 525        .get_features   = virtio_pci_get_features,
 526        .set_features   = virtio_pci_set_features,
 527        .find_vqs       = virtio_pci_find_vqs,
 528        .del_vqs        = virtio_pci_del_vqs,
 529        .notify         = virtio_pci_notify,
 530};
 531
 532U_BOOT_DRIVER(virtio_pci_modern) = {
 533        .name   = VIRTIO_PCI_DRV_NAME,
 534        .id     = UCLASS_VIRTIO,
 535        .ops    = &virtio_pci_ops,
 536        .bind   = virtio_pci_bind,
 537        .probe  = virtio_pci_probe,
 538        .priv_auto_alloc_size = sizeof(struct virtio_pci_priv),
 539};
 540
 541static struct pci_device_id virtio_pci_supported[] = {
 542        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID00) },
 543        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID01) },
 544        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID02) },
 545        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID03) },
 546        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID04) },
 547        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID05) },
 548        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID06) },
 549        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID07) },
 550        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID08) },
 551        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID09) },
 552        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID0A) },
 553        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID0B) },
 554        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID0C) },
 555        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID0D) },
 556        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID0E) },
 557        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID0F) },
 558        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID10) },
 559        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID11) },
 560        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID12) },
 561        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID13) },
 562        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID14) },
 563        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID15) },
 564        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID16) },
 565        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID17) },
 566        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID18) },
 567        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID19) },
 568        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID1A) },
 569        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID1B) },
 570        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID1C) },
 571        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID1D) },
 572        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID1E) },
 573        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID1F) },
 574        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID20) },
 575        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID21) },
 576        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID22) },
 577        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID23) },
 578        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID24) },
 579        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID25) },
 580        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID26) },
 581        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID27) },
 582        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID28) },
 583        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID29) },
 584        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID2A) },
 585        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID2B) },
 586        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID2C) },
 587        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID2D) },
 588        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID2E) },
 589        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID2F) },
 590        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID30) },
 591        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID31) },
 592        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID32) },
 593        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID33) },
 594        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID34) },
 595        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID35) },
 596        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID36) },
 597        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID37) },
 598        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID38) },
 599        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID39) },
 600        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID3A) },
 601        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID3B) },
 602        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID3C) },
 603        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID3D) },
 604        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID3E) },
 605        { PCI_DEVICE(VIRTIO_PCI_VENDOR_ID, VIRTIO_PCI_DEVICE_ID3F) },
 606        {},
 607};
 608
 609U_BOOT_PCI_DEVICE(virtio_pci_modern, virtio_pci_supported);
 610