static uint64_t virtio_pci_common_read(void *opaque, hwaddr addr,

                                       unsigned size)

{

    VirtIOPCIProxy *proxy = opaque;

    VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);

    uint32_t val = 0;

    int i;



    switch (addr) {

    case VIRTIO_PCI_COMMON_DFSELECT:

        val = proxy->dfselect;

        break;

    case VIRTIO_PCI_COMMON_DF:

        if (proxy->dfselect <= 1) {

            val = vdev->host_features >> (32 * proxy->dfselect);

        }

        break;

    case VIRTIO_PCI_COMMON_GFSELECT:

        val = proxy->gfselect;

        break;

    case VIRTIO_PCI_COMMON_GF:

        if (proxy->gfselect < ARRAY_SIZE(proxy->guest_features)) {

            val = proxy->guest_features[proxy->gfselect];

        }

        break;

    case VIRTIO_PCI_COMMON_MSIX:

        val = vdev->config_vector;

        break;

    case VIRTIO_PCI_COMMON_NUMQ:

        for (i = 0; i < VIRTIO_QUEUE_MAX; ++i) {

            if (virtio_queue_get_num(vdev, i)) {

                val = i + 1;

            }

        }

        break;

    case VIRTIO_PCI_COMMON_STATUS:

        val = vdev->status;

        break;

    case VIRTIO_PCI_COMMON_CFGGENERATION:

        val = vdev->generation;

        break;

    case VIRTIO_PCI_COMMON_Q_SELECT:

        val = vdev->queue_sel;

        break;

    case VIRTIO_PCI_COMMON_Q_SIZE:

        val = virtio_queue_get_num(vdev, vdev->queue_sel);

        break;

    case VIRTIO_PCI_COMMON_Q_MSIX:

        val = virtio_queue_vector(vdev, vdev->queue_sel);

        break;

    case VIRTIO_PCI_COMMON_Q_ENABLE:

        val = proxy->vqs[vdev->queue_sel].enabled;

        break;

    case VIRTIO_PCI_COMMON_Q_NOFF:

        /* Simply map queues in order */

        val = vdev->queue_sel;

        break;

    case VIRTIO_PCI_COMMON_Q_DESCLO:

        val = proxy->vqs[vdev->queue_sel].desc[0];

        break;

    case VIRTIO_PCI_COMMON_Q_DESCHI:

        val = proxy->vqs[vdev->queue_sel].desc[1];

        break;

    case VIRTIO_PCI_COMMON_Q_AVAILLO:

        val = proxy->vqs[vdev->queue_sel].avail[0];

        break;

    case VIRTIO_PCI_COMMON_Q_AVAILHI:

        val = proxy->vqs[vdev->queue_sel].avail[1];

        break;

    case VIRTIO_PCI_COMMON_Q_USEDLO:

        val = proxy->vqs[vdev->queue_sel].used[0];

        break;

    case VIRTIO_PCI_COMMON_Q_USEDHI:

        val = proxy->vqs[vdev->queue_sel].used[1];

        break;

    default:

        val = 0;

    }



    return val;

}
