diff options
-rw-r--r-- | extras/mini-os/events.c | 17 | ||||
-rw-r--r-- | extras/mini-os/include/events.h | 1 | ||||
-rw-r--r-- | extras/mini-os/include/pcifront.h | 17 | ||||
-rw-r--r-- | extras/mini-os/pcifront.c | 88 |
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; +} |