1/** 2 * \file 3 * \brief Contains handler functions for server-side octopus interface RPC call. 4 */ 5 6/* 7 * Copyright (c) 2009, 2010, 2012, ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <stdio.h> 16#include <string.h> 17#include <inttypes.h> 18#include <errno.h> 19 20#include <barrelfish/barrelfish.h> 21#include <barrelfish/nameservice_client.h> 22#include <skb/skb.h> // read list 23#include <int_route/int_route_server.h> 24#include <int_route/int_route_debug.h> 25 26#include <if/int_route_service_defs.h> 27#include <if/int_route_controller_defs.h> 28 29struct controller_driver { 30 char * label; // Label used in the SKB 31 char * class; // Class used in the SKB 32 struct int_route_controller_binding * binding; // 33 struct controller_driver * next; // Linked list next 34}; 35 36/* This server exports two interfaces: 37 * * RPC interface - This is RPC the interface that 38 * * Controller interface - Interrupt controllers use a 39 */ 40 41struct controller_driver * controller_head; 42static int exported = 0; 43 44static struct controller_driver * add_controller(struct controller_driver * d){ 45 struct controller_driver * cur; 46 if(controller_head == NULL){ 47 controller_head = malloc(sizeof(struct controller_driver)); 48 cur = controller_head; 49 } else if(d != NULL && d->next != NULL){ 50 return add_controller(d->next); 51 } else { 52 assert(d != NULL); 53 d->next = malloc(sizeof(struct controller_driver)); 54 cur = d->next; 55 } 56 57 // Initialize cur 58 cur->next = NULL; 59 cur->binding = NULL; 60 cur->label = NULL; 61 cur->class = NULL; 62 return cur; 63} 64 65/* 66 * Finds a controller for the given label/class combination. 67 * First, if a label is passed, it tries to match the label exactly, if no 68 * controller is found, it goes on to match on the class. 69 */ 70static struct controller_driver *find_controller(const char *label, 71 const char *class) { 72 if (label != NULL && strlen(label) > 0) { 73 for (struct controller_driver *cur = controller_head; cur != NULL; 74 cur = cur->next) { 75 if (strcmp(label, cur->label) == 0) { 76 return cur; 77 } 78 } 79 } 80 if (class != NULL && strlen(class) > 0) { 81 for (struct controller_driver *cur = controller_head; cur != NULL; 82 cur = cur->next) { 83 if (strcmp(class, cur->class) == 0) { 84 return cur; 85 } 86 } 87 } 88 return NULL; 89} 90 91struct controller_add_mapping_data { 92 char * lbl; 93 char * class; 94 int_route_controller_int_message_t in_msg; 95 int_route_controller_int_message_t out_msg; 96 struct int_route_controller_binding *binding; 97}; 98 99#define INVALID_PORT -1 100#define INVALID_VECTOR ((uint64_t)-1) 101 102/** 103 * Since on ARMv7 the topolgy is easy, we don't use the SKB. 104 */ 105static void driver_route_call_armv7(struct int_route_service_binding *b, 106 struct capref intsource, int irq_idx, 107 struct capref intdest){ 108 INT_DEBUG("%s: enter\n", __FUNCTION__); 109 110 errval_t err; 111 uint64_t int_src_num = INVALID_VECTOR; 112 err = invoke_irqsrc_get_vec_start(intsource, &int_src_num); 113 uint64_t int_src_num_high = INVALID_VECTOR; 114 err = invoke_irqsrc_get_vec_end(intsource, &int_src_num_high); 115 if(int_src_num + irq_idx > int_src_num_high || irq_idx < 0){ 116 err = SYS_ERR_IRQ_INVALID; 117 DEBUG_ERR(err, "irq_idx out of range"); 118 b->tx_vtbl.route_response(b, NOP_CONT, err); 119 return; 120 } 121 122 assert(err_is_ok(err)); 123 int_src_num += irq_idx; 124 125 uint64_t dest_vec = INVALID_VECTOR; 126 err = invoke_irqdest_get_vector(intdest, &dest_vec); 127 assert(err_is_ok(err)); 128 129 uint64_t dest_cpu = INVALID_VECTOR; 130 err = invoke_irqdest_get_cpu(intdest, &dest_cpu); 131 assert(err_is_ok(err)); 132 133 printf("Int route service: Routing request, (int=%"PRIu64") to " 134 "(cpu=%"PRIu64",vec=%"PRIu64")\n", 135 int_src_num, dest_cpu, dest_vec); 136 137 138 const char * class = "gic_dist"; 139 struct controller_driver * gic_dist = find_controller(NULL, class); 140 141 if(gic_dist == NULL){ 142 err = SYS_ERR_IRQ_INVALID; 143 DEBUG_ERR(err, "gic_dist controller not found!\n"); 144 } else { 145 int_route_controller_int_message_t in_msg; 146 in_msg.port = int_src_num; 147 int_route_controller_int_message_t out_msg; 148 out_msg.port = dest_cpu; 149 err = int_route_controller_add_mapping__tx(gic_dist->binding, 150 BLOCKING_CONT, NULL, class, in_msg, 151 out_msg); 152 } 153 154 b->tx_vtbl.route_response(b, NOP_CONT, err); 155} 156 157static void ctrl_register_controller(struct int_route_controller_binding *_binding, 158 const char *label, const char *class) { 159 struct controller_driver * c = add_controller(controller_head); 160 c->label = malloc(strlen(label)+1); 161 assert(c->label != NULL); 162 strcpy(c->label, label); 163 164 c->class = malloc(strlen(class)+1); 165 assert(c->class != NULL); 166 strcpy(c->class, class); 167 INT_DEBUG("ctrl_register_controller, label=%s, class=%s\n",c->label, c->class); 168 169 c->binding = _binding; 170} 171 172 173static struct int_route_service_rx_vtbl driver_rx_vtbl = { 174 .route_call = driver_route_call_armv7 175 176}; 177 178static struct int_route_controller_rx_vtbl ctrl_rx_vtbl = { 179 .register_controller = ctrl_register_controller 180}; 181 182static errval_t driver_connect_cb(void *st, struct int_route_service_binding *b) { 183 INT_DEBUG("%s: enter\n", __FUNCTION__); 184 b->st = NULL; 185 b->rx_vtbl = driver_rx_vtbl; 186 return SYS_ERR_OK; 187 188} 189 190static errval_t ctrl_connect_cb(void *st, struct int_route_controller_binding *b) { 191 INT_DEBUG("%s: enter\n", __FUNCTION__); 192 b->st = NULL; 193 b->rx_vtbl = ctrl_rx_vtbl; 194 return SYS_ERR_OK; 195 196} 197 198static void driver_export_cb(void *st, errval_t err, iref_t iref){ 199 INT_DEBUG("%s: enter\n", __FUNCTION__); 200 assert(err_is_ok(err)); 201 202 err = nameservice_register("int_route_service", iref); 203 if (err_is_fail(err)) { 204 USER_PANIC_ERR(err, "nameservice_register 1 failed"); 205 }; 206 exported++; 207} 208 209static void ctrl_export_cb(void *st, errval_t err, iref_t iref){ 210 INT_DEBUG("%s: enter\n", __FUNCTION__); 211 assert(err_is_ok(err)); 212 213 err = nameservice_register("int_ctrl_service", iref); 214 if (err_is_fail(err)) { 215 USER_PANIC_ERR(err, "nameservice_register 2 failed"); 216 }; 217 exported++; 218} 219 220 221// The main function of this service 222int main(void) { 223 errval_t err; 224 debug_printf("Start\n"); 225 226 // Export route service for PCI device drivers 227 err = int_route_service_export(NULL, driver_export_cb, driver_connect_cb, 228 get_default_waitset(), 229 IDC_EXPORT_FLAGS_DEFAULT); 230 231 if (err_is_fail(err)) { 232 USER_PANIC_ERR(err, "int_route_service_export failed"); 233 } 234 235 err = int_route_controller_export(NULL, ctrl_export_cb, ctrl_connect_cb, 236 get_default_waitset(), 237 IDC_EXPORT_FLAGS_DEFAULT); 238 if (err_is_fail(err)) { 239 USER_PANIC_ERR(err, "int_route_controller_export failed"); 240 } 241 242 while (true) { 243 event_dispatch(get_default_waitset()); 244 } 245 246 return 0; 247} 248