mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
minios: PIRQ and MSI/MSI-X support
Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
This commit is contained in:
1 parent
9194f26eba
commit
38cfc3b8d0
4 files changed
+121
-2
No files matched your search
@@ -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];
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
}
|
||||