@@ -591,6 +591,78 @@ static struct virtio_config_ops virtio_pci_config_ops = {
.finalize_features = vp_finalize_features,
};
+static struct virtmem *setup_mem(struct virtio_device *vdev, unsigned index)
+{
+ struct virtio_pci_device *vp_dev = to_vp_device(vdev);
+ struct virtmem *vmem;
+ u32 size;
+ u32 pfn;
+
+ /* Select the memory region we're interested in */
+ printk(KERN_INFO "selecting mem region %d\n", index);
+ iowrite32(index, vp_dev->ioaddr + VIRTIO_PCI_MEM_SEL);
+
+ /* Read memory region size */
+ size = ioread32(vp_dev->ioaddr + VIRTIO_PCI_MEM_SIZE);
+ if (!size) return ERR_PTR(-ENOENT);
+
+ pfn = ioread32(vp_dev->ioaddr + VIRTIO_PCI_MEM_PFN);
+ printk(KERN_INFO "pfn is %#x\n", pfn);
+
+ /* allocate and fill out our structure the represents an active
+ * mem_region */
+ vmem = kmalloc(sizeof(struct virtmem), GFP_KERNEL);
+ if (!vmem)
+ return ERR_PTR(-ENOMEM);
+
+ vmem->size = size;
+ vmem->phys_addr = pfn << 12;
+
+ return vmem;
+
+}
+
+/* support for VirtIO shared memory */
+static int vp_map_region(struct virtio_device *vdev, unsigned nmem,
+ struct virtmem ** vmem)
+{
+ int i;
+
+ for (i = 0; i < nmem; ++i) {
+ vmem[i] = setup_mem(vdev, i);
+ printk(KERN_INFO "virtio_pci: vp_map_region (%lu, %lu)\n",
+ vmem[i]->phys_addr, vmem[i]->size);
+
+ /* let's map it here and assign the address to 'map_addr' */
+ vmem[i]->map_addr = ioremap_cache(vmem[i]->phys_addr, vmem[i]->size);
+
+ if (vmem[i]->map_addr == NULL) {
+ printk(KERN_INFO "virtio_pci: vp_map_region (%lu, %lu) failed \n",
+ vmem[i]->phys_addr, vmem[i]->size);
+ return -ENODEV;
+ }
+ }
+
+ /* TODO: compare length to size? */
+
+ return 0;
+}
+
+static void vp_unmap_region(struct virtio_device *vdev, struct virtmem *vmem)
+{
+
+ vmem->map_addr = 0;
+ vmem->size = 0;
+ iounmap(vmem->phys_addr);
+
+ return;
+}
+
+static struct virtio_device_ops virtio_pci_device_ops = {
+ .map_region = vp_map_region,
+ .unmap_region = vp_unmap_region,
+};
+
static void virtio_pci_release_dev(struct device *_d)
{
struct virtio_device *dev = container_of(_d, struct virtio_device, dev);
@@ -630,6 +702,7 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev,
vp_dev->vdev.dev.parent = virtio_pci_root;
vp_dev->vdev.dev.release = virtio_pci_release_dev;
vp_dev->vdev.config = &virtio_pci_config_ops;
+ vp_dev->vdev.device = &virtio_pci_device_ops;
vp_dev->pci_dev = pci_dev;
INIT_LIST_HEAD(&vp_dev->virtqueues);
spin_lock_init(&vp_dev->lock);
@@ -26,6 +26,14 @@ struct virtqueue {
void *priv;
};
+struct virtmem {
+ struct virtio_device *vdev;
+ u32 size;
+ u64 phys_addr;
+ unsigned char * map_addr;
+ void * priv;
+};
+
/**
* virtqueue_ops - operations for virtqueue abstraction layer
* @add_buf: expose buffer to other end
@@ -88,6 +96,7 @@ struct virtio_device {
struct device dev;
struct virtio_device_id id;
struct virtio_config_ops *config;
+ struct virtio_device_ops *device;
struct list_head vqs;
/* Note that this is a Linux set_bit-style bitmap. */
unsigned long features[1];
@@ -96,6 +96,13 @@ struct virtio_config_ops {
void (*finalize_features)(struct virtio_device *vdev);
};
+struct virtio_device_ops {
+ int (*map_region) (struct virtio_device *vdev,
+ unsigned nmem, struct virtmem ** vmem);
+ void (*unmap_region)(struct virtio_device *vdev, struct virtmem *vmem);
+ /* we might need query region and other stuff */
+};
+
/* If driver didn't advertise the feature, it will never appear. */
void virtio_check_driver_offered_feature(const struct virtio_device *vdev,
unsigned int fbit);
@@ -49,15 +49,21 @@
/* MSI-X registers: only enabled if MSI-X is enabled. */
/* A 16-bit vector for configuration changes. */
-#define VIRTIO_MSI_CONFIG_VECTOR 20
+#define VIRTIO_MSI_CONFIG_VECTOR 32
/* A 16-bit vector for selected queue notifications. */
-#define VIRTIO_MSI_QUEUE_VECTOR 22
+#define VIRTIO_MSI_QUEUE_VECTOR 34
/* Vector value used to disable MSI for queue */
#define VIRTIO_MSI_NO_VECTOR 0xffff
/* The remaining space is defined by each driver as the per-driver
* configuration space */
-#define VIRTIO_PCI_CONFIG(dev) ((dev)->msix_enabled ? 24 : 20)
+#define VIRTIO_PCI_CONFIG(dev) ((dev)->msix_enabled ? 36 : 32)
+
+#define VIRTIO_PCI_MEM_SEL 20
+
+#define VIRTIO_PCI_MEM_SIZE 24
+
+#define VIRTIO_PCI_MEM_PFN 28
/* Virtio ABI version, this must match exactly */
#define VIRTIO_PCI_ABI_VERSION 0