+u64 vp_get_features(struct vp_device *vp)
+{
+ u32 f0, f1;
+
+ if (vp->use_modern) {
+ vp_write(&vp->common, virtio_pci_common_cfg, device_feature_select, 0);
+ f0 = vp_read(&vp->common, virtio_pci_common_cfg, device_feature);
+ vp_write(&vp->common, virtio_pci_common_cfg, device_feature_select, 1);
+ f1 = vp_read(&vp->common, virtio_pci_common_cfg, device_feature);
+ } else {
+ f0 = vp_read(&vp->legacy, virtio_pci_legacy, host_features);
+ f1 = 0;
+ }
+ return ((u64)f1 << 32) | f0;
+}
+
+void vp_set_features(struct vp_device *vp, u64 features)
+{
+ u32 f0, f1;
+
+ f0 = features;
+ f1 = features >> 32;
+
+ if (vp->use_modern) {
+ vp_write(&vp->common, virtio_pci_common_cfg, guest_feature_select, 0);
+ vp_write(&vp->common, virtio_pci_common_cfg, guest_feature, f0);
+ vp_write(&vp->common, virtio_pci_common_cfg, guest_feature_select, 1);
+ vp_write(&vp->common, virtio_pci_common_cfg, guest_feature, f1);
+ } else {
+ vp_write(&vp->legacy, virtio_pci_legacy, guest_features, f0);
+ }
+}
+
+u8 vp_get_status(struct vp_device *vp)
+{
+ if (vp->use_modern) {
+ return vp_read(&vp->common, virtio_pci_common_cfg, device_status);
+ } else {
+ return vp_read(&vp->legacy, virtio_pci_legacy, status);
+ }
+}
+
+void vp_set_status(struct vp_device *vp, u8 status)
+{
+ if (status == 0) /* reset */
+ return;
+ if (vp->use_modern) {
+ vp_write(&vp->common, virtio_pci_common_cfg, device_status, status);
+ } else {
+ vp_write(&vp->legacy, virtio_pci_legacy, status, status);
+ }
+}
+
+u8 vp_get_isr(struct vp_device *vp)
+{
+ if (vp->use_modern) {
+ return vp_read(&vp->isr, virtio_pci_isr, isr);
+ } else {
+ return vp_read(&vp->legacy, virtio_pci_legacy, isr);
+ }
+}
+
+void vp_reset(struct vp_device *vp)
+{
+ if (vp->use_modern) {
+ vp_write(&vp->common, virtio_pci_common_cfg, device_status, 0);
+ vp_read(&vp->isr, virtio_pci_isr, isr);
+ } else {
+ vp_write(&vp->legacy, virtio_pci_legacy, status, 0);
+ vp_read(&vp->legacy, virtio_pci_legacy, isr);
+ }
+}
+
+void vp_notify(struct vp_device *vp, struct vring_virtqueue *vq)
+{
+ if (vp->use_modern) {
+ u32 addr = vp->notify.addr +
+ vq->queue_notify_off *
+ vp->notify_off_multiplier;
+ if (vp->notify.is_io) {
+ outw(vq->queue_index, addr);
+ } else {
+ writew((void*)addr, vq->queue_index);
+ }
+ dprintf(9, "vp notify %x (%d) -- 0x%x\n",
+ addr, 2, vq->queue_index);
+ } else {
+ vp_write(&vp->legacy, virtio_pci_legacy, queue_notify, vq->queue_index);
+ }
+}
+
+int vp_find_vq(struct vp_device *vp, int queue_index,