3 * \brief Contains handler functions for server-side octopus interface RPC call.
7 * Copyright (c) 2009, 2010, 2012, ETH Zurich.
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, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
19 #include <barrelfish/barrelfish.h>
20 #include <barrelfish/nameservice_client.h>
21 #include <skb/skb.h> // read list
22 #include <int_route/int_route_server.h>
23 #include <int_route/int_route_debug.h>
25 #include <if/int_route_service_defs.h>
26 #include <if/int_route_controller_defs.h>
28 struct controller_driver {
29 char * label; // Label used in the SKB
30 char * class; // Label used in the SKB
31 struct int_route_controller_binding * binding; //
32 struct controller_driver * next; // Linked list next
35 /* This server exports two interfaces:
36 * * RPC interface - This is RPC the interface that
37 * * Controller interface - Interrupt controllers use a
40 struct controller_driver * controller_head;
41 static int exported = 0;
43 //static struct controller_driver * find_controller(char * lbl, struct controller_driver *d){
46 // } else if(strcmp(d->lbl, lbl) == 0){
49 // return find_controller(lbl, d->next);
53 static struct controller_driver * add_controller(struct controller_driver * d){
54 INT_DEBUG("%s: enter\n", __FUNCTION__);
55 struct controller_driver * cur;
56 if(controller_head == NULL){
57 controller_head = malloc(sizeof(struct controller_driver));
58 cur = controller_head;
59 } else if(d != NULL && d->next != NULL){
60 return add_controller(d->next);
63 d->next = malloc(sizeof(struct controller_driver));
76 * Finds a controller for the given label/class combination.
77 * First, if a label is passed, it tries to match the label exactly, if no controller is found, it
78 * goes on to match on the class.
80 static struct controller_driver * find_controller(char * label, char * class){
81 if(label != NULL && strlen(label) > 0) {
82 for(struct controller_driver * cur = controller_head; cur != NULL; cur = cur->next){
83 if(strcmp(label, cur->label) == 0){
88 if(class != NULL && strlen(class) > 0) {
89 for(struct controller_driver * cur = controller_head; cur != NULL; cur = cur->next){
90 if(strcmp(class, cur->class) == 0){
98 static int_route_controller_int_message_t build_int_message(uint64_t port, char * in){
99 int_route_controller_int_message_t ret = {0,0};
101 if(strcmp(in,"nullMsg") == 0){
107 if(strncmp(in, "mem_write", strlen("mem_write")) == 0){
108 sscanf(in, "mem_write(%"SCNu64",%"SCNu64")", &ret.addr, &ret.msg);
113 if(sscanf(in,"%"SCNu64,&ret.msg) == 1){
118 INT_DEBUG("Could not parse int_message: %s\n", in);
122 static void tx_cont(void * arg){
123 INT_DEBUG("Continuation called :-(\n");
126 static errval_t read_route_output_and_tell_controllers(void){
127 char * out = skb_get_output();
128 INT_DEBUG("skb output: %s\n", out);
130 // Parse output and instruct controller
132 char class[255], lbl[255];
133 char inmsg[255], outmsg[255];
135 for(char * pos = out; pos - 1 != NULL && *pos != 0; pos = strchr(pos,'\n')+1 ) {
136 int res = sscanf(pos, "%[^,],%[^,],%d,%[^,],%d,%[^,]",
137 lbl, class, &inport, inmsg, &outport, outmsg);
139 debug_printf("WARNING: Invalid SKB response. (%d)\n", __LINE__);
142 INT_DEBUG("Scanned %d args: %s %s %d %s %d %s\n", res, lbl, class,
143 inport, inmsg, outport, outmsg );
145 struct controller_driver * dest = find_controller(lbl, class);
147 INT_DEBUG("No controller driver found.");
149 struct int_route_controller_binding * b = dest->binding;
150 b->tx_vtbl.add_mapping(b, MKCONT(tx_cont, NULL), lbl, strlen(lbl), class, strlen(class),
151 build_int_message(inport, inmsg),
152 build_int_message(outport, outmsg));
158 #define INVALID_VECTOR ((uint64_t)-1)
160 static void driver_route_call(struct int_route_service_binding *b,
161 struct capref intsource, struct capref intdest){
162 INT_DEBUG("%s: enter\n", __FUNCTION__);
165 uint64_t int_src_num = INVALID_VECTOR;
166 err = invoke_irqsrc_get_vector(intsource, &int_src_num);
167 assert(err_is_ok(err));
169 uint64_t dest_vec = INVALID_VECTOR;
170 err = invoke_irqdest_get_vector(intdest, &dest_vec);
171 assert(err_is_ok(err));
174 uint64_t dest_cpu = INVALID_VECTOR;
175 err = invoke_irqdest_get_cpu(intdest, &dest_cpu);
176 assert(err_is_ok(err));
178 const char * template = "find_and_add_irq_route(%"PRIu64",%"PRIu64",%"PRIu64").";
179 int q_size = strlen(template) + 3 * 16;
180 char * query = malloc(q_size);
181 snprintf(query, q_size, template, int_src_num, dest_cpu, dest_vec);
182 err = skb_execute(query);
183 if(err_is_fail(err)){
184 DEBUG_ERR(err, "Error executing: %s.\n", query);
185 b->tx_vtbl.route_response(b, NOP_CONT, err);
189 err = read_route_output_and_tell_controllers();
190 if(err_is_fail(err)){
191 DEBUG_ERR(err, "Error read_route_and_tell_controllers.\n");
193 b->tx_vtbl.route_response(b, NOP_CONT, err);
196 static void ctrl_register_controller(struct int_route_controller_binding *_binding,
197 char *label, size_t l1, char *class, size_t l2) {
198 struct controller_driver * c = add_controller(controller_head);
199 c->label = malloc(l1+1);
200 assert(c->label != NULL);
201 strncpy(c->label, label, l1);
204 c->class = malloc(l2+1);
205 assert(c->class != NULL);
206 strncpy(c->class, class, l2);
208 INT_DEBUG("ctrl_register_controller, label=%s, class=%s\n",c->label, c->class);
210 c->binding = _binding;
214 static struct int_route_service_rx_vtbl driver_rx_vtbl = {
215 .route_call = driver_route_call
219 static struct int_route_controller_rx_vtbl ctrl_rx_vtbl = {
220 .register_controller = ctrl_register_controller
223 static errval_t driver_connect_cb(void *st, struct int_route_service_binding *b) {
224 INT_DEBUG("%s: enter\n", __FUNCTION__);
226 b->rx_vtbl = driver_rx_vtbl;
231 static errval_t ctrl_connect_cb(void *st, struct int_route_controller_binding *b) {
232 INT_DEBUG("%s: enter\n", __FUNCTION__);
234 b->rx_vtbl = ctrl_rx_vtbl;
239 static void driver_export_cb(void *st, errval_t err, iref_t iref){
240 INT_DEBUG("%s: enter\n", __FUNCTION__);
241 assert(err_is_ok(err));
243 err = nameservice_register("int_route_service", iref);
244 if (err_is_fail(err)) {
245 USER_PANIC_ERR(err, "nameservice_register 1 failed");
250 static void ctrl_export_cb(void *st, errval_t err, iref_t iref){
251 INT_DEBUG("%s: enter\n", __FUNCTION__);
252 assert(err_is_ok(err));
254 err = nameservice_register("int_ctrl_service", iref);
255 if (err_is_fail(err)) {
256 USER_PANIC_ERR(err, "nameservice_register 2 failed");
262 // The main function of this service
263 errval_t int_route_service_init(void)
266 INT_DEBUG("int_route_service_init\n");
267 // We need skb connection
268 skb_client_connect();
270 // Export route service for PCI device drivers
271 err = int_route_service_export(NULL, driver_export_cb, driver_connect_cb, get_default_waitset(),
272 IDC_EXPORT_FLAGS_DEFAULT);
274 if(err_is_fail(err)){
275 USER_PANIC_ERR(err, "int_route_service_export failed");
278 err = int_route_controller_export(NULL, ctrl_export_cb, ctrl_connect_cb, get_default_waitset(),
279 IDC_EXPORT_FLAGS_DEFAULT);
280 if(err_is_fail(err)){
281 USER_PANIC_ERR(err, "int_route_controller_export failed");
285 // XXX: Due to cyclic dependency, we must make sure the service has been exported before
288 while(exported != 2){
289 event_dispatch(get_default_waitset());