minios: PIRQ and MSI/MSI-X support
authorKeir Fraser <keir.fraser@citrix.com>
Wed, 2 Jul 2008 16:26:42 +0000 (17:26 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Wed, 2 Jul 2008 16:26:42 +0000 (17:26 +0100)
Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
extras/mini-os/events.c
extras/mini-os/include/events.h
extras/mini-os/include/pcifront.h
extras/mini-os/pcifront.c

index 87f54ef5ebe47fb1672a0171f45de142d364f549..e89d7478fa52d29a15669913135eecb031127f70 100644 (file)
@@ -136,6 +136,23 @@ evtchn_port_t bind_virq(uint32_t virq, evtchn_handler_t handler, void *data)
        return op.port;
 }
 
+evtchn_port_t bind_pirq(uint32_t pirq, int will_share, evtchn_handler_t handler, void *data)
+{
+       evtchn_bind_pirq_t op;
+
+       /* Try to bind the pirq to a port */
+       op.pirq = pirq;
+       op.flags = will_share ? BIND_PIRQ__WILL_SHARE : 0;
+
+       if ( HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &op) != 0 )
+       {
+               printk("Failed to bind physical IRQ %d\n", pirq);
+               return -1;
+       }
+       bind_evtchn(op.port, handler, data);
+       return op.port;
+}
+
 #if defined(__x86_64__)
 char irqstack[2 * STACK_SIZE];
 
index 9ffb35d320c5ef224153127e12915a9998879010..fd708eb5d31d9e723be1132891b51f526cd88d9a 100644 (file)
@@ -27,6 +27,7 @@ typedef void (*evtchn_handler_t)(evtchn_port_t, struct pt_regs *, void *);
 /* prototypes */
 int do_event(evtchn_port_t port, struct pt_regs *regs);
 evtchn_port_t bind_virq(uint32_t virq, evtchn_handler_t handler, void *data);
+evtchn_port_t bind_pirq(uint32_t pirq, int will_share, evtchn_handler_t handler, void *data);
 evtchn_port_t bind_evtchn(evtchn_port_t port, evtchn_handler_t handler,
                                                  void *data);
 void unbind_evtchn(evtchn_port_t port);
index 71d4faa13d3085fe6af0473031a7fcaadeaabd0a..f09769808d7891e0248296c032bc4933a52070e6 100644 (file)
@@ -2,9 +2,8 @@
 #include <xen/io/pciif.h>
 struct pcifront_dev;
 struct pcifront_dev *init_pcifront(char *nodename);
-void pcifront_scan(struct pcifront_dev *dev, void (*fun)(unsigned int domain, unsigned int bus, unsigned slot, unsigned int fun));
 void pcifront_op(struct pcifront_dev *dev, struct xen_pci_op *op);
-void shutdown_pcifront(struct pcifront_dev *dev);
+void pcifront_scan(struct pcifront_dev *dev, void (*fun)(unsigned int domain, unsigned int bus, unsigned slot, unsigned int fun));
 int pcifront_conf_read(struct pcifront_dev *dev,
                        unsigned int dom,
                        unsigned int bus, unsigned int slot, unsigned long fun,
@@ -13,3 +12,17 @@ int pcifront_conf_write(struct pcifront_dev *dev,
                         unsigned int dom,
                         unsigned int bus, unsigned int slot, unsigned long fun,
                         unsigned int off, unsigned int size, unsigned int val);
+int pcifront_enable_msi(struct pcifront_dev *dev,
+                        unsigned int dom,
+                        unsigned int bus, unsigned int slot, unsigned long fun);
+int pcifront_disable_msi(struct pcifront_dev *dev,
+                         unsigned int dom,
+                         unsigned int bus, unsigned int slot, unsigned long fun);
+int pcifront_enable_msix(struct pcifront_dev *dev,
+                         unsigned int dom,
+                         unsigned int bus, unsigned int slot, unsigned long fun,
+                         struct xen_msix_entry *entries, int n);
+int pcifront_disable_msix(struct pcifront_dev *dev,
+                          unsigned int dom,
+                          unsigned int bus, unsigned int slot, unsigned long fun);
+void shutdown_pcifront(struct pcifront_dev *dev);
index d5f3511e27316ed1b0d0973f64906844b02c86ba..bd8be0b9f03dd7e90d2db33ff0c36b66bb676701 100644 (file)
@@ -276,3 +276,91 @@ int pcifront_conf_write(struct pcifront_dev *dev,
 
     return op.err;
 }
+
+int pcifront_enable_msi(struct pcifront_dev *dev,
+                        unsigned int dom,
+                        unsigned int bus, unsigned int slot, unsigned long fun)
+{
+    struct xen_pci_op op;
+
+    memset(&op, 0, sizeof(op));
+
+    op.cmd = XEN_PCI_OP_enable_msi;
+    op.domain = dom;
+    op.bus = bus;
+    op.devfn = PCI_DEVFN(slot, fun);
+
+    pcifront_op(dev, &op);
+    
+    if (op.err)
+        return op.err;
+    else
+        return op.value;
+}
+
+int pcifront_disable_msi(struct pcifront_dev *dev,
+                         unsigned int dom,
+                         unsigned int bus, unsigned int slot, unsigned long fun)
+{
+    struct xen_pci_op op;
+
+    memset(&op, 0, sizeof(op));
+
+    op.cmd = XEN_PCI_OP_disable_msi;
+    op.domain = dom;
+    op.bus = bus;
+    op.devfn = PCI_DEVFN(slot, fun);
+
+    pcifront_op(dev, &op);
+    
+    return op.err;
+}
+
+int pcifront_enable_msix(struct pcifront_dev *dev,
+                         unsigned int dom,
+                         unsigned int bus, unsigned int slot, unsigned long fun,
+                         struct xen_msix_entry *entries, int n)
+{
+    struct xen_pci_op op;
+
+    if (n > SH_INFO_MAX_VEC)
+        return XEN_PCI_ERR_op_failed;
+
+    memset(&op, 0, sizeof(op));
+
+    op.cmd = XEN_PCI_OP_enable_msix;
+    op.domain = dom;
+    op.bus = bus;
+    op.devfn = PCI_DEVFN(slot, fun);
+    op.value = n;
+
+    memcpy(op.msix_entries, entries, n * sizeof(*entries));
+
+    pcifront_op(dev, &op);
+    
+    if (op.err)
+        return op.err;
+
+    memcpy(entries, op.msix_entries, n * sizeof(*entries));
+
+    return 0;
+}
+
+
+int pcifront_disable_msix(struct pcifront_dev *dev,
+                          unsigned int dom,
+                          unsigned int bus, unsigned int slot, unsigned long fun)
+{
+    struct xen_pci_op op;
+
+    memset(&op, 0, sizeof(op));
+
+    op.cmd = XEN_PCI_OP_disable_msix;
+    op.domain = dom;
+    op.bus = bus;
+    op.devfn = PCI_DEVFN(slot, fun);
+
+    pcifront_op(dev, &op);
+    
+    return op.err;
+}