IRQ: added irq source capability and make the inthandler setup use it
authorLukas Humbel <lukas.humbel@inf.ethz.ch>
Thu, 31 Mar 2016 15:07:41 +0000 (17:07 +0200)
committerLukas Humbel <lukas.humbel@inf.ethz.ch>
Wed, 6 Apr 2016 08:37:36 +0000 (10:37 +0200)
Signed-off-by: Lukas Humbel <lukas.humbel@inf.ethz.ch>

21 files changed:
errors/errno.fugu
hake/Config.hs.template
if/pci.if
include/arch/x86_64/barrelfish/invocations_arch.h
include/barrelfish/sys_debug.h
include/barrelfish_kpi/capabilities.h
include/barrelfish_kpi/sys_debug.h
include/pci/pci_client_debug.h [new file with mode: 0644]
kernel/arch/x86_64/irq.c
kernel/arch/x86_64/syscall.c
kernel/include/arch/x86_64/irq.h
kernel/include/kcb.h
kernel/kcb.c
lib/barrelfish/arch/x86/sys_debug.c
lib/barrelfish/inthandler.c
lib/pci/Hakefile
lib/pci/mem.c
lib/pci/pci_client.c
usr/pci/pci.c
usr/pci/pci.h
usr/pci/pci_service.c

index 4f277d1..99bd7ea 100755 (executable)
@@ -779,6 +779,7 @@ errors driverkit DRIVERKIT_ {
 
 // errors in PCI/device handling
 errors pci PCI_ERR_ {
+    failure DEVICE_NOT_INIT     "Device not initialized",
     failure IOAPIC_INIT         "Failed in ioapic_init()",
     failure MINT_IOCAP          "Failed to mint IO cap",
     failure ROUTING_IRQ         "Failed while routing interrupt",
index 3409768..b9dd06d 100644 (file)
@@ -226,6 +226,9 @@ libacpi_debug = False
 acpi_interface_debug :: Bool
 acpi_interface_debug = False
 
+acpi_service_debug :: Bool
+acpi_service_debug = False
+
 acpi_server_debug :: Bool
 acpi_server_debug = False
 
index 0f4f947..3deca93 100644 (file)
--- a/if/pci.if
+++ b/if/pci.if
@@ -65,6 +65,9 @@ interface pci "The PCI Interface" {
 
     /* write PCI conf header */
     rpc write_conf_header(in uint32 dword, in uint32 val, out errval err);
+    
+    /* Enable (legacy) interrupt */
+    rpc irq_enable(out errval err);
 
     /* Enable MSI-X for the specified PCI device. */
     rpc msix_enable_addr(in uint8 bus, in uint8 dev, in uint8 fn,
index 8bdd0ad..26f43a9 100644 (file)
@@ -414,9 +414,16 @@ invoke_dispatcher_setup_guest(struct capref dispatcher,
                        get_cap_addr(guest_control_cap)).error;
 }
 
-static inline errval_t invoke_irq_connect(struct capref irqcap, struct capref epcap)
+static inline errval_t invoke_irqvector_connect(struct capref irqcap, struct capref epcap)
 {
-    struct sysret ret = cap_invoke2(irqcap, IRQCmd_Connect, get_cap_addr(epcap));
+    struct sysret ret = cap_invoke2(irqcap, IRQVectorCmd_Connect, get_cap_addr(epcap));
+    return ret.error;
+}
+
+static inline errval_t invoke_irqvector_get_vector(struct capref irqcap, uint32_t * out_vec)
+{
+    struct sysret ret = cap_invoke1(irqcap, IRQVectorCmd_GetVector);
+    *out_vec = ret.value;
     return ret.error;
 }
 
index 8ec884f..9d6909d 100644 (file)
@@ -16,6 +16,7 @@
 #define BARRELFISH_SYS_DEBUG_H
 
 #include <sys/cdefs.h>
+#include <barrelfish/caddr.h>
 
 __BEGIN_DECLS
 
@@ -43,6 +44,7 @@ errval_t sys_debug_hardware_timer_read(uintptr_t* ret);
 errval_t sys_debug_hardware_timer_hertz_read(uintptr_t* ret);
 errval_t sys_debug_hardware_global_timer_read(uint64_t *ret);
 errval_t sys_debug_get_apic_ticks_per_sec(uint32_t *ret);
+errval_t sys_debug_create_irq_src_cap(struct capref cap, uint16_t gsi);
 
 #ifdef ENABLE_FEIGN_FRAME_CAP
 errval_t sys_debug_feign_frame_cap(struct capref slot, lpaddr_t base,
index 542d773..e6e1a60 100644 (file)
@@ -339,12 +339,20 @@ enum irqtable_cmd {
 };
 
 /**
- * IRQ commands.
+ * IRQ Vector commands.
+ */
+
+enum irqvector_cmd {
+       IRQVectorCmd_Connect,   ///< Connect this capability to a messaging channel
+       IRQVectorCmd_GetVector ///< Return the local interrupt vector
+};
+
+/**
+ * IRQ Vector commands.
  */
 
 enum irq_cmd {
-       IRQCmd_Connect, ///< Connect this capability to a messaging channel
-       IRQCmd_GetVector ///< Return the local interrupt vector
+    IRQCmd_GetVector   ///< Return vector and controller saved in this cap.
 };
 
 
index cd1caa1..f7dc3f7 100644 (file)
@@ -33,7 +33,8 @@ enum debug_message {
     DEBUG_GET_APIC_TICKS_PER_SEC,
     DEBUG_FEIGN_FRAME_CAP,
     DEBUG_TRACE_PMEM_CTRL,
-    DEBUG_GET_APIC_ID
+    DEBUG_GET_APIC_ID,
+    DEBUG_CREATE_IRQ_SRC_CAP
 };
 
 #endif //BARRELFISH_KPI_SYS_DEBUG_H
diff --git a/include/pci/pci_client_debug.h b/include/pci/pci_client_debug.h
new file mode 100644 (file)
index 0000000..1f510b4
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef PCI_CLIENT_DEBUG_H
+#define PCI_CLIENT_DEBUG_H
+
+#if defined(PCI_CLIENT_DEBUG) || defined(GLOBAL_DEBUG)
+#define PCI_CLIENT_DEBUG(x...) printf("pci_client: " x)
+#else
+#define PCI_CLIENT_DEBUG(x...) ((void)0)
+#endif
+
+#endif
index 6f300d9..74c841a 100644 (file)
@@ -418,7 +418,8 @@ static void send_user_interrupt(int irq)
     assert(irq >= 0 && irq < NDISPATCH);
     struct kcb *k = kcb_current;
     do {
-        if (k->irq_dest_caps[irq].cap.type == ObjType_IRQVector) {
+        if (k->irq_dest_caps[irq] != NULL) {
+            assert(k->irq_dest_caps[irq]->cap.type == ObjType_IRQVector);
             break;
         }
         k = k->next;
@@ -428,7 +429,7 @@ static void send_user_interrupt(int irq)
         switch_kcb(k);
     }
     // from here: kcb_current is the kcb for which the interrupt was intended
-    struct capability *cap = &kcb_current->irq_dest_caps[irq].cap;
+    struct capability *cap = &kcb_current->irq_dest_caps[irq]->cap;
 
     // Return on null cap (unhandled interrupt)
     if(cap->type == ObjType_Null) {
@@ -496,7 +497,7 @@ errval_t irq_table_alloc(int *outvec)
         struct kcb *k = kcb_current;
         bool found_free = true;
         do {
-            if (k->irq_dest_caps[i].cap.type == ObjType_IRQVector) {
+            if (k->irq_dest_caps[i] != NULL) {
                 found_free = false;
                 break;
             }
@@ -510,12 +511,36 @@ errval_t irq_table_alloc(int *outvec)
         *outvec = -1;
         return SYS_ERR_IRQ_NO_FREE_VECTOR;
     } else {
-        //TODO Luki: Somehow we must put here a cap in the table
         *outvec = i;
         return SYS_ERR_OK;
     }
 }
 
+errval_t irq_debug_create_src_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t out_cap_addr, uint16_t gsi)
+{
+    // This method is a hack to forge a irq src cap for the given GSI targeting the ioapic
+    errval_t err;
+    struct cte out_cap;
+    memset(&out_cap, 0, sizeof(struct cte));
+
+    out_cap.cap.type = ObjType_IRQ;
+    out_cap.cap.u.irq.line = gsi;
+    const uint32_t ioapic_controller_id = 2;
+    out_cap.cap.u.irq.controller = ioapic_controller_id;
+
+    struct cte * cn;
+    err = caps_lookup_slot(&dcb_current->cspace.cap, dcn, dcn_vbits, &cn, CAPRIGHTS_WRITE);
+    if(err_is_fail(err)){
+        return err;
+    }
+    err = caps_copy_to_cnode(cn, out_cap_addr, &out_cap, 0, 0, 0);
+    if(err_is_fail(err)){
+        return err;
+    }
+
+    return SYS_ERR_OK;
+}
+
 errval_t irq_table_alloc_dest_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t out_cap_addr)
 {
     errval_t err;
@@ -526,10 +551,10 @@ errval_t irq_table_alloc_dest_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t ou
     // TODO Luki: Figure out why it was working with i=0 before
     for (i = 1; i < NDISPATCH; i++) {
         //struct kcb * k = kcb_current;
-        assert(kcb_current->irq_dest_caps[i].cap.type == ObjType_Null ||
-               kcb_current->irq_dest_caps[i].cap.type == ObjType_IRQVector);
+        assert(kcb_current->irq_dest_caps[i] == NULL ||
+               kcb_current->irq_dest_caps[i]->cap.type == ObjType_IRQVector);
         //TODO Luki: iterate over kcb
-        if (kcb_current->irq_dest_caps[i].cap.type != ObjType_IRQVector) {
+        if (kcb_current->irq_dest_caps[i] == NULL) {
             break;
         }
     }
@@ -548,10 +573,19 @@ errval_t irq_table_alloc_dest_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t ou
         if(err_is_fail(err)){
             return err;
         }
-        err = caps_copy_to_cnode(cn, out_cap_addr, &out_cap, 0, 0, 0);
+        // The following lines equal
+        // caps_copy_to_cnode(cn, out_cap_addr, &out_cap, 0, 0, 0);
+        assert(cn->cap.type == ObjType_CNode);
+        struct cte *dest_cte;
+        dest_cte = caps_locate_slot(cn->cap.u.cnode.cnode, out_cap_addr);
+        err = caps_copy_to_cte(dest_cte, &out_cap, 0, 0, 0);
         if(err_is_fail(err)){
             return err;
         }
+
+        // Link dest_cte in
+        kcb_current->irq_dest_caps[i] = dest_cte;
+
         return SYS_ERR_OK;
     }
 }
@@ -561,6 +595,8 @@ errval_t irq_connect(struct capability *dest_cap, capaddr_t endpoint_adr)
     errval_t err;
     struct cte *endpoint;
 
+    printk(LOG_ERR, "Entering irq_connect\n");
+
     // Lookup & check message endpoint cap
     err = caps_lookup_slot(&dcb_current->cspace.cap, endpoint_adr,
                            CPTR_BITS, &endpoint, CAPRIGHTS_WRITE);
@@ -646,7 +682,7 @@ errval_t irq_table_notify_domains(struct kcb *kcb)
     //TODO Luki: Check if this stuff is correct with multiple kcbs
     uintptr_t msg[] = { 1 };
     for (int i = 0; i < NDISPATCH; i++) {
-        struct capability * dest_cap = &kcb->irq_dest_caps[i].cap;
+        struct capability * dest_cap = &(kcb->irq_dest_caps[i]->cap);
         if (dest_cap->type == ObjType_IRQVector) {
             struct capability * ep_cap = dest_cap->u.irqvector.ep;
             if (ep_cap) {
@@ -664,7 +700,7 @@ errval_t irq_table_notify_domains(struct kcb *kcb)
                 }
             }
             // Remove endpoint. Domains must re-register by calling connect again.
-            kcb->irq_dest_caps[i].cap.u.irqvector.ep->type = ObjType_Null;
+            kcb->irq_dest_caps[i]->cap.u.irqvector.ep->type = ObjType_Null;
         }
     }
     return SYS_ERR_OK;
index 9067021..4e56f07 100644 (file)
@@ -799,7 +799,17 @@ static struct sysret handle_trace_setup(struct capability *cap,
     return SYSRET(SYS_ERR_OK);
 }
 
-static struct sysret handle_irq_get_vector(struct capability *to, int cmd,
+static struct sysret handle_irq_get_vector(struct capability * to, int cmd,
+        uintptr_t *args)
+{
+    struct sysret ret;
+    ret.error = SYS_ERR_OK;
+    ret.value = to->u.irq.line;
+    return ret;
+
+}
+
+static struct sysret handle_irqvector_get_vector(struct capability *to, int cmd,
                                             uintptr_t *args)
 {
     struct sysret ret;
@@ -808,7 +818,7 @@ static struct sysret handle_irq_get_vector(struct capability *to, int cmd,
     return ret;
 }
 
-static struct sysret handle_irq_connect(struct capability *to, int cmd,
+static struct sysret handle_irqvector_connect(struct capability *to, int cmd,
                                             uintptr_t *args)
 {
     return SYSRET(irq_connect(to, args[0]));
@@ -1170,9 +1180,12 @@ static invocation_handler_t invocations[ObjType_Num][CAP_MAX_CMD] = {
         [IPICmd_Send_Start] = kernel_send_start_ipi,
         [IPICmd_Send_Init] = kernel_send_init_ipi,
     },
+    [ObjType_IRQ] = {
+        [IRQCmd_GetVector] = handle_irq_get_vector
+    },
        [ObjType_IRQVector] = {
-                       [IRQCmd_Connect] = handle_irq_connect,
-                       [IRQCmd_GetVector] = handle_irq_get_vector
+                       [IRQVectorCmd_Connect] = handle_irqvector_connect,
+                       [IRQVectorCmd_GetVector] = handle_irqvector_get_vector
        },
     [ObjType_IRQTable] = {
         [IRQTableCmd_Alloc] = handle_irq_table_alloc,
@@ -1453,6 +1466,10 @@ struct sysret sys_syscall(uint64_t syscall, uint64_t arg0, uint64_t arg1,
             retval.value = apic_get_id();
             break;
 
+        case DEBUG_CREATE_IRQ_SRC_CAP:
+            retval.error = irq_debug_create_src_cap(arg1, args[0], args[1], args[2]);
+            break;
+
         default:
             printk(LOG_ERR, "invalid sys_debug msg type\n");
         }
index f30fd36..1413a2a 100644 (file)
@@ -165,5 +165,6 @@ errval_t irq_table_delete(unsigned int nidt);
 struct kcb;
 errval_t irq_table_notify_domains(struct kcb *kcb);
 errval_t irq_table_alloc_dest_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t out_cap_addr);
+errval_t irq_debug_create_src_cap(uint8_t dcn_vbits, capaddr_t dcn, capaddr_t out_cap_addr, uint16_t gsi);
 
 #endif
index bf37d98..c5ef57f 100644 (file)
@@ -66,7 +66,7 @@ struct kcb {
     //driver whose kernel_now > this kcb's kernel_off.
     int64_t kernel_off;
 
-    struct cte irq_dest_caps[NDISPATCH];
+    struct cte * irq_dest_caps[NDISPATCH];
     // TODO: maybe add a shared part which can replace struct core_data?
 };
 
index c258a6e..c0d7c62 100644 (file)
@@ -105,7 +105,7 @@ void kcb_update_core_id(struct kcb *kcb)
     }
 
     for (int i = 0; i < NDISPATCH; i++) {
-        struct capability *cap = &kcb->irq_dest_caps[i].cap;
+        struct capability *cap = &kcb->irq_dest_caps[i]->cap;
         assert(cap->type != ObjType_EndPoint); // Now we store IRQVector caps here
         if (cap->type == ObjType_IRQVector) {
             struct capability * ep = cap->u.irqvector.ep;
index bb29ef1..fc85612 100644 (file)
@@ -27,6 +27,16 @@ errval_t sys_debug_get_tsc_per_ms(uint64_t *ret)
     return sr.error;
 }
 
+errval_t sys_debug_create_irq_src_cap(struct capref cap, uint16_t gsi)
+{
+    uint8_t dcn_vbits = get_cnode_valid_bits(cap);
+    capaddr_t dcn_addr = get_cnode_addr(cap);
+
+    struct sysret sr = syscall6(SYSCALL_DEBUG, DEBUG_CREATE_IRQ_SRC_CAP, dcn_vbits, dcn_addr,
+        cap.slot, gsi);
+    return sr.error;
+}
+
 errval_t sys_debug_get_apic_id(uint8_t *ret)
 {
     struct sysret sr = syscall2(SYSCALL_DEBUG, DEBUG_GET_APIC_ID);
index c097356..ab683cd 100644 (file)
@@ -201,7 +201,7 @@ errval_t inthandler_setup_movable_cap(struct capref dest_cap, interrupt_handler_
     }
 
     // Connect dest_cap with endpoint
-    invoke_irq_connect(dest_cap, epcap);
+    invoke_irqvector_connect(dest_cap, epcap);
 
 
     return SYS_ERR_OK;
@@ -254,13 +254,13 @@ errval_t inthandler_setup_movable(interrupt_handler_fn handler, void *handler_ar
         return err_push(err, LIB_ERR_ENDPOINT_CREATE);
     }
 
-    err = invoke_irq_connect(irq_dest_cap, epcap);
+    err = invoke_irqvector_connect(irq_dest_cap, epcap);
     if (err_is_fail(err)) {
         DEBUG_ERR(err, "Could not connect irq_cap and endpoint");
         return err;
     }
 
-    err = invoke_irq_get_vector(irq_dest_cap, ret_vector);
+    err = invoke_irqvector_get_vector(irq_dest_cap, ret_vector);
     if (err_is_fail(err)) {
         DEBUG_ERR(err, "Could not lookup irq vector");
         return err;
index 4d0d258..e9f6163 100644 (file)
@@ -16,7 +16,8 @@
                   flounderBindings = [ "pci" ],
                   flounderExtraBindings = [ ("pci", ["rpcclient"]) ],
                   flounderExtraDefs = [ ("monitor_blocking",["rpcclient"]) ],
-                  architectures = [ "x86_64", "x86_32" ]
+                  architectures = [ "x86_64", "x86_32" ],
+                  addLibraries = libDeps [ "acpi_client" ]
                 },
   
   -- XXX: This library is a bit weird right now.
index b22c311..a6350f7 100644 (file)
 #include <stdio.h>
 #include <barrelfish/barrelfish.h>
 #include <pci/mem.h>
-
-#if 0
-#define PCI_DEBUG(x...) printf("pci_client: " x)
-#else
-#define PCI_DEBUG(x...) ((void)0)
-#endif
+#include <pci/pci_client_debug.h>
 
 errval_t map_device(struct device_mem *mem)
 {
@@ -25,7 +20,7 @@ errval_t map_device(struct device_mem *mem)
         return SYS_ERR_OK; // XXX
     }
 
-    PCI_DEBUG("map_device: %lu\n", mem->bytes);
+    PCI_CLIENT_DEBUG("map_device: %lu\n", mem->bytes);
 
     size_t offset = 0;
     size_t cap_size = mem->bytes / mem->nr_caps;
@@ -39,14 +34,14 @@ errval_t map_device(struct device_mem *mem)
     }
 
     for (int i = 0; i < mem->nr_caps; i++) {
-        PCI_DEBUG("mem: map in cap nr %d\n", i);
+        PCI_CLIENT_DEBUG("mem: map in cap nr %d\n", i);
         err = mem->memobj->f.fill(mem->memobj, offset, mem->frame_cap[i],
                                   cap_size);
         if (err_is_fail(err)) {
             DEBUG_ERR(err, "memobj->f.fill failed");
             return err_push(err, LIB_ERR_MEMOBJ_FILL);
         }
-        PCI_DEBUG("offset = %lu\n", offset);
+        PCI_CLIENT_DEBUG("offset = %lu\n", offset);
         err = mem->memobj->f.pagefault(mem->memobj, mem->vregion, offset, 0);
         if (err_is_fail(err)) {
             DEBUG_ERR(err, "memobj->f.pagefault failed");
index ecc96b7..d0eea5c 100644 (file)
 #include <barrelfish/dispatch.h>
 #include <barrelfish/inthandler.h>
 #include <pci/pci.h>
+#include <pci/pci_client_debug.h>
 #include <if/pci_defs.h>
 #include <if/pci_rpcclient_defs.h>
+#include <acpi_client/acpi_client.h>
 
 #define INVALID_VECTOR ((uint32_t)-1)
 
@@ -94,16 +96,25 @@ errval_t pci_register_driver_movable_irq(pci_driver_init_fn init_func, uint32_t
 
     struct capref irq_src_cap;
 
-    // Get IRQ 0. For backward compatability with function interface
+    // Get vector 0 of the device.
+    // For backward compatibility with function interface.
     err = pci_client->vtbl.get_irq_cap(pci_client, 0, &msgerr, &irq_src_cap);
     if (err_is_fail(err) || err_is_fail(msgerr)) {
         if (err_is_ok(err)) {
             err = msgerr;
         }
-        DEBUG_ERR(err, "requesting cap for IRQ %d of device", 0);
+        DEBUG_ERR(err, "requesting cap for IRQ 0 of device");
         goto out;
     }
 
+    uint32_t gsi = INVALID_VECTOR;
+    err = invoke_irq_get_vector(irq_src_cap, &gsi);
+    if (err_is_fail(err)) {
+        DEBUG_ERR(err, "Could not lookup GSI vector");
+        return err;
+    }
+    PCI_CLIENT_DEBUG("Got irq cap, gsi: %"PRIu32"\n", gsi);
+
     // Get irq_dest_cap from monitor
     struct capref irq_dest_cap;
     err = alloc_dest_irq_cap(&irq_dest_cap);
@@ -111,15 +122,31 @@ errval_t pci_register_driver_movable_irq(pci_driver_init_fn init_func, uint32_t
         DEBUG_ERR(err, "Could not allocate dest irq cap");
         goto out;
     }
+    uint32_t irq_dest_vec = INVALID_VECTOR;
+    err = invoke_irqvector_get_vector(irq_dest_cap, &irq_dest_vec);
+    if (err_is_fail(err)) {
+        DEBUG_ERR(err, "Could not lookup irq vector");
+        return err;
+    }
+    PCI_CLIENT_DEBUG("Got dest cap, vector: %"PRIu32"\n", irq_dest_vec);
 
 
     // Setup routing
-    // TODO
+    // TODO: Instead of getting the vectors of each cap and set up routing,
+    // pass both to a routing service and let the service handle the setup.
+    struct acpi_rpc_client* cl = get_acpi_rpc_client();
+    errval_t ret_error;
+    err = cl->vtbl.enable_and_route_interrupt(cl, gsi, disp_get_core_id(), irq_dest_vec, &ret_error);
+    assert(err_is_ok(err));
+    if (err_is_fail(ret_error)) {
+        DEBUG_ERR(ret_error, "failed to route interrupt %d -> %d\n", gsi, irq_dest_vec);
+        return err_push(ret_error, PCI_ERR_ROUTING_IRQ);
+    }
 
     // Connect endpoint to handler
     if(handler != NULL){
-        err = inthandler_setup_movable_cap(irq_dest_cap, handler, handler_arg, reloc_handler,
-                    reloc_handler_arg);
+        err = inthandler_setup_movable_cap(irq_dest_cap, handler, handler_arg,
+                reloc_handler, reloc_handler_arg);
         if (err_is_fail(err)) {
             return err;
         }
@@ -338,6 +365,11 @@ errval_t pci_client_connect(void)
     iref_t iref;
     errval_t err, err2 = SYS_ERR_OK;
 
+    err = connect_to_acpi();
+    if(err_is_fail(err)){
+        return err;
+    }
+
     /* Connect to the pci server */
     err = nameservice_blocking_lookup("pci", &iref);
     if (err_is_fail(err)) {
index 4098038..0f467e4 100644 (file)
@@ -267,6 +267,7 @@ errval_t device_init(uint32_t class_code,
                      uint32_t *bus,
                      uint32_t *dev,
                      uint32_t *fun,
+                     bool *pcie,
                      int *nr_allocated_bars)
 {
     *nr_allocated_bars = 0;
@@ -275,7 +276,6 @@ errval_t device_init(uint32_t class_code,
     char s_bus[10], s_dev[10], s_fun[10], s_vendor_id[10], s_device_id[10];
     char s_class_code[10], s_sub_class[10], s_prog_if[10];
     char s_pcie[5];
-    bool pcie;
     int error_code;
     int bar_nr;
     pciaddr_t bar_base, bar_high;
@@ -359,9 +359,9 @@ errval_t device_init(uint32_t class_code,
         return err_push(err, PCI_ERR_DEVICE_INIT);
     }
     if (strncmp(s_pcie, "pcie", strlen("pcie")) == 0) {
-        pcie = true;
+        *pcie = true;
     } else {
-        pcie = false;
+        *pcie = false;
     }
 
     PCI_DEBUG("device_init(): Found device at %u:%u:%u\n", *bus, *dev, *fun);
@@ -414,7 +414,7 @@ errval_t device_init(uint32_t class_code,
     PCI_DEBUG("device_init(): Allocated caps for %d BARs\n", *nr_allocated_bars);
 
     PCI_DEBUG("enable busmaster for device (%u, %u, %u)...\n", *bus, *dev, *fun);
-    enable_busmaster(*bus, *dev, *fun, pcie);
+    enable_busmaster(*bus, *dev, *fun, *pcie);
 
     return SYS_ERR_OK;
 }
index f149869..f6f9b7f 100644 (file)
@@ -56,9 +56,15 @@ void pci_program_bridges(void);
 void pci_init(void);
 void pci_init_datastructures(void);
 
-errval_t device_init(uint32_t class_code, uint32_t sub_class, uint32_t prog_if,
-                     uint32_t vendor_id, uint32_t device_id,
-                     uint32_t *bus, uint32_t *dev,uint32_t *fun,
+errval_t device_init(uint32_t class_code,
+                     uint32_t sub_class,
+                     uint32_t prog_if,
+                     uint32_t vendor_id,
+                     uint32_t device_id,
+                     uint32_t *bus,
+                     uint32_t *dev,
+                     uint32_t *fun,
+                     bool *pcie,
                      int *nr_allocated_bars);
 errval_t device_reregister_interrupt(uint8_t coreid, int vector,
                  uint32_t class_code, uint32_t sub_class, uint32_t prog_if,
index a4f6a7d..097c28d 100644 (file)
  * XXX: this assumes only one driver per client */
 struct client_state {
 //    struct device_mem *bar_info;
+    uint8_t initialized;
     int nr_allocated_bars;
     uint32_t nr_caps_bar[PCI_NBARS];
     uint32_t bus;
     uint32_t dev;
     uint32_t fun;
+    bool pcie;
     void *cont_st;
 };
 
@@ -63,7 +65,7 @@ static void init_pci_device_handler(struct pci_binding *b,
 
 
     err = device_init(class_code, sub_class, prog_if, vendor_id, device_id,
-                      &bus, &dev, &fun, &(cc->nr_allocated_bars));
+                      &bus, &dev, &fun, &(cc->pcie), &(cc->nr_allocated_bars));
 
     cc->bus = bus;
     cc->dev = dev;
@@ -85,6 +87,18 @@ static void init_pci_device_handler(struct pci_binding *b,
     assert(err_is_ok(err));
 }
 
+static void irq_enable_handler(struct pci_binding *b)
+{
+    struct client_state *cc = (struct client_state *) b->st;
+    if(!cc->initialized){
+        b->tx_vtbl.irq_enable_response(b, NOP_CONT, PCI_ERR_DEVICE_NOT_INIT);
+        return;
+    }
+
+    pci_enable_interrupt_for_device(cc->bus, cc->dev, cc->fun, cc->pcie);
+    b->tx_vtbl.irq_enable_response(b, NOP_CONT, SYS_ERR_OK);
+}
+
 static void init_legacy_device_handler(struct pci_binding *b,
                                        uint16_t iomin, uint16_t iomax,
                                        uint8_t irq, coreid_t coreid,
@@ -173,6 +187,15 @@ static void get_bar_cap_response_resend(void *arg)
     free(a);
 }
 
+static void get_irq_cap_handler(struct pci_binding *b, uint16_t idx){
+    // TODO: This method hands out caps very generous.
+    errval_t err;
+    struct capref cap;
+    slot_alloc(&cap);
+    err = sys_debug_create_irq_src_cap(cap, idx);
+    b->tx_vtbl.get_irq_cap_response(b, NOP_CONT, err, cap);
+}
+
 static void get_bar_cap_handler(struct pci_binding *b, uint32_t idx,
                             uint32_t cap_nr)
 {
@@ -340,10 +363,12 @@ struct pci_rx_vtbl pci_rx_vtbl = {
     .init_pci_device_call = init_pci_device_handler,
     .init_legacy_device_call = init_legacy_device_handler,
     .get_bar_cap_call = get_bar_cap_handler,
+    .get_irq_cap_call = get_irq_cap_handler,
     .reregister_interrupt_call = reregister_interrupt_handler,
     //.get_vbe_bios_cap_call = get_vbe_bios_cap,
     .read_conf_header_call = read_conf_header_handler,
     .write_conf_header_call = write_conf_header_handler,
+    .irq_enable_call = irq_enable_handler,
 
     .msix_enable_call = msix_enable_handler,
     .msix_enable_addr_call = msix_enable_addr_handler,