aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extras/mini-os/events.c17
-rw-r--r--extras/mini-os/include/events.h1
-rw-r--r--extras/mini-os/include/pcifront.h17
-rw-r--r--extras/mini-os/pcifront.c88
4 files changed, 121 insertions, 2 deletions
diff --git a/extras/mini-os/events.c b/extras/mini-os/events.c
index 87f54ef5eb..e89d7478fa 100644
--- a/extras/mini-os/events.c
+++ b/extras/mini-os/events.c
@@ -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];
diff --git a/extras/mini-os/include/events.h b/extras/mini-os/include/events.h
index 9ffb35d320..fd708eb5d3 100644
--- a/extras/mini-os/include/events.h
+++ b/extras/mini-os/include/events.h
@@ -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);
diff --git a/extras/mini-os/include/pcifront.h b/extras/mini-os/include/pcifront.h
index 71d4faa13d..f09769808d 100644
--- a/extras/mini-os/include/pcifront.h
+++ b/extras/mini-os/include/pcifront.h
@@ -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);
diff --git a/extras/mini-os/pcifront.c b/extras/mini-os/pcifront.c
index d5f3511e27..bd8be0b9f0 100644
--- a/extras/mini-os/pcifront.c
+++ b/extras/mini-os/pcifront.c
@@ -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;
+}