1#include <barrelfish/barrelfish.h> 2#include <barrelfish/nameservice_client.h> 3#include <int_route/msix_ctrl.h> 4#include <int_route/int_model.h> 5#include <if/int_route_controller_defs.h> 6#include <dev/msix_e1000_dev.h> 7 8#include "debug.h" 9 10struct msix_ctrl_state { 11 int bound; 12 msix_e1000_t dev; // Mackerel state 13 struct int_startup_argument * arg; // Contains name etc. 14}; 15 16 17static void add_mapping(struct int_route_controller_binding *b, 18 const char *label, 19 const char *class, 20 int_route_controller_int_message_t from, 21 int_route_controller_int_message_t to) { 22 23 struct msix_ctrl_state * st = b->st; 24 CTRL_DEBUG("msix add_mapping: label:%s, class:%s (%"PRIu64", %"PRIu64") to " 25 "(%"PRIu64", %"PRIu64")\n", label, class, from.addr, from.msg, to.addr, to.msg); 26 27 28 CTRL_DEBUG("Setting MSIx port=%"PRIu64" to (addr=0x%"PRIx64",msg=0x%"PRIx64")\n", 29 from.port, to.addr, to.msg); 30 31 int vec_num = from.addr; //TODO make sure this is correct 32 msix_e1000_vec_control_wr(&st->dev, vec_num, 0); 33 msix_e1000_msg_data_wr(&st->dev, vec_num, to.msg); 34 msix_e1000_msg_addr_wr(&st->dev, vec_num, to.addr); 35}; 36 37static void msix_ctrl_bind_cb(void *stin, errval_t err, struct int_route_controller_binding *b) { 38 struct msix_ctrl_state * st = stin; 39 if(!err_is_ok(err)){ 40 debug_err(__FILE__,__FUNCTION__,__LINE__, err, "Bind failure\n"); 41 return; 42 } 43 44 b->rx_vtbl.add_mapping = add_mapping; 45 46 // Register this binding for name=msix_ctrl_name and class msix 47 b->tx_vtbl.register_controller(b, BLOCKING_CONT, st->arg->msix_ctrl_name, "msix"); 48 49 // Store state in binding 50 b->st = st; 51 52 st->bound = true; 53} 54 55errval_t msix_client_init_by_args(int argc, char **argv, void* msix_tab) { 56 struct int_startup_argument *arg = malloc(sizeof(struct int_startup_argument)); 57 if(!arg) return LIB_ERR_MALLOC_FAIL; 58 59 errval_t err = SYS_ERR_IRQ_NO_ARG; 60 for(int i=0; i<argc; i++){ 61 err = int_startup_argument_parse(argv[i], arg); 62 if(err_is_ok(err)) break; 63 } 64 if(!err_is_ok(err)) return err; 65 if(arg->model != INT_MODEL_MSIX) { 66 return SYS_ERR_IRQ_INVALID; 67 } 68 return msix_client_init(arg, msix_tab); 69}; 70 71errval_t msix_client_init(struct int_startup_argument *arg, void* msix_tab) { 72 // Allocate state. Need to think about this. 73 struct msix_ctrl_state * st = malloc(sizeof(struct msix_ctrl_state)); 74 st->bound = false; 75 st->arg = arg; 76 CTRL_DEBUG("Instantiating MSIx ctrl driver (name=%s)\n", 77 arg->msix_ctrl_name); 78 79 // Connect to int route service 80 iref_t int_route_service; 81 errval_t err; 82 err = nameservice_blocking_lookup("int_ctrl_service", &int_route_service); 83 if(!err_is_ok(err)){ 84 debug_err(__FILE__,__FUNCTION__,__LINE__, err, 85 "Could not lookup int_route_service\n"); 86 return err; 87 } 88 89 err = int_route_controller_bind(int_route_service, msix_ctrl_bind_cb, st, 90 get_default_waitset(), IDC_BIND_FLAGS_DEFAULT); 91 92 if(!err_is_ok(err)){ 93 debug_err(__FILE__,__FUNCTION__,__LINE__, err, 94 "Could not bind int_route_service\n"); 95 return err; 96 } 97 98 while(!st->bound) event_dispatch(get_default_waitset()); 99 100 101 msix_e1000_initialize(&st->dev, msix_tab); 102 103 return SYS_ERR_OK; 104}; 105