1#include <stdio.h> 2 3#include <pci/pci_types.h> 4#include <barrelfish/barrelfish.h> 5#include <barrelfish/barrelfish.h> 6#include <barrelfish/cpu_arch.h> 7#include <barrelfish/nameservice_client.h> 8#include <if/int_route_controller_defs.h> 9#include <skb/skb.h> 10 11#include "pci_int_ctrl.h" 12#include "pci_debug.h" 13#include "pci.h" 14 15/* 16 * This file contains interrupt controller clients for the classes 'pci' 17 * and 'pci_msix'. Both enable interrupts in the PCI conf space. The 18 * first does so for legacy interrupts, while the later is doing if for MSI-x 19 */ 20 21 22static void add_mapping(struct int_route_controller_binding *b, 23 const char *label, 24 const char *class, 25 int_route_controller_int_message_t from, 26 int_route_controller_int_message_t to) { 27 28 errval_t err = SYS_ERR_OK; 29 30 PCI_DEBUG("pci add_mapping: label:%s, class:%s (%"PRIu64", %"PRIu64") to " 31 "(%"PRIu64", %"PRIu64")\n", label, class, from.addr, from.msg, to.addr, to.msg); 32 33 assert(strcmp(class, "pci") == 0 || strcmp(class, "pci_msix") == 0); 34 35 36 struct pci_addr addr; 37 char s_pcie[5]; 38 bool pcie; 39 // Get pcilnk acpiName from SKB 40 err = skb_execute_query("pci_lbl_addr(%s, addr(Bus,Dev,Fun))," 41 "device(PCIE,addr(Bus,Dev,Fun), _, _, _, _, _, _)," 42 "write((Bus,Dev,Fun,PCIE)).", label); 43 if(err_is_fail(err)){ 44 DEBUG_SKB_ERR(err, "get pci addr"); 45 return; 46 } 47 48 49 err = skb_read_output("%d,%d,%d,%s", &addr.bus, &addr.device, 50 &addr.function, s_pcie); 51 if(err_is_fail(err)){ 52 DEBUG_SKB_ERR(err, "parse pci addr"); 53 return; 54 } 55 if(strncmp(s_pcie, "pcie", strlen("pcie")) == 0) { 56 pcie = true; 57 } else { 58 pcie = false; 59 } 60 61 PCI_DEBUG("add_mapping: pcie=%d, bus=%"PRIu32", dev=%"PRIu32", fun=%"PRIu32"\n", 62 pcie, addr.bus, addr.device, addr.function); 63 64 if(strncmp(label, "pci_msix", strlen("pci_msix")) == 0){ 65 //MSI-X 66 struct pci_address address = { 67 .bus = addr.bus, 68 .device = addr.device, 69 .function = addr.function 70 }; 71 err = pci_msix_enable_confspace(&address, 1); 72 if(err_is_fail(err)){ 73 USER_PANIC_ERR(err, "msix enable"); 74 } 75 } else { 76 //Legacy 77 pci_enable_interrupt_for_device(addr.bus, addr.device, addr.function, pcie); 78 } 79 80} 81 82static void bind_cb(void *st, errval_t err, struct int_route_controller_binding *b) { 83 if(!err_is_ok(err)){ 84 debug_err(__FILE__,__FUNCTION__,__LINE__, err, "Bind failure\n"); 85 return; 86 } 87 88 b->rx_vtbl.add_mapping = add_mapping; 89 90 // Register this binding for all controllers with class pci 91 const char * label = ""; 92 const char * ctrl_class = "pci"; 93 b->tx_vtbl.register_controller(b, NOP_CONT, label, ctrl_class); 94 95 // Register this binding for all controllers with class pci_msix 96 const char * ctrl_class_msix = "pci_msix"; 97 b->tx_vtbl.register_controller(b, NOP_CONT, label, ctrl_class_msix); 98 99} 100 101errval_t pci_int_ctrl_init(void) { 102 // Connect to int route service 103 iref_t int_route_service; 104 errval_t err; 105 err = nameservice_blocking_lookup("int_ctrl_service", &int_route_service); 106 if(!err_is_ok(err)){ 107 debug_err(__FILE__,__FUNCTION__,__LINE__, err, "Could not lookup int_route_service\n"); 108 return err; 109 } 110 111 err = int_route_controller_bind(int_route_service, 112 bind_cb, NULL, get_default_waitset(), 113 IDC_BIND_FLAGS_DEFAULT); 114 115 if(!err_is_ok(err)){ 116 debug_err(__FILE__,__FUNCTION__,__LINE__, err, "Could not bind int_route_service\n"); 117 return err; 118 } 119 120 return SYS_ERR_OK; 121} 122