71ac15ffe4a43ed4e79eb6c0d029477c68fd1614
[barrelfish] / lib / int_route / server / init.c
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, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
13  */
14
15 #include <stdio.h>
16 #include <string.h>
17 #include <inttypes.h>
18
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>
24
25 #include <if/int_route_service_defs.h>
26 #include <if/int_route_controller_defs.h>
27
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
33 };
34
35 /* This server exports two interfaces:
36  * * RPC interface - This is RPC the interface that
37  * * Controller interface - Interrupt controllers use a
38  */
39
40 struct controller_driver * controller_head;
41 static int exported = 0;
42
43 //static struct controller_driver * find_controller(char * lbl, struct controller_driver *d){
44 //    if(d == NULL){
45 //        return NULL;
46 //    } else if(strcmp(d->lbl, lbl) == 0){
47 //        return d;
48 //    } else {
49 //        return find_controller(lbl, d->next);
50 //    }
51 //}
52
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);
61     } else {
62         assert(d != NULL);
63         d->next = malloc(sizeof(struct controller_driver));
64         cur = d->next;
65     }
66
67     // Initialize cur
68     cur->next = NULL;
69     cur->binding = NULL;
70     cur->label = NULL;
71     cur->class = NULL;
72     return cur;
73 }
74
75 /*
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.
79  */
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){
84                 return cur;
85             }
86         }
87     }
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){
91                 return cur;
92             }
93         }
94     }
95     return NULL;
96 }
97
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};
100
101     if(strcmp(in,"nullMsg") == 0){
102         ret.addr = port;
103         ret.msg = 0;
104         return ret;
105     }
106
107     if(strncmp(in, "mem_write", strlen("mem_write")) == 0){
108         sscanf(in, "mem_write(%"SCNu64",%"SCNu64")", &ret.addr, &ret.msg);
109         assert(port == 0);
110         return ret;
111     }
112
113     if(sscanf(in,"%"SCNu64,&ret.msg) == 1){
114         ret.addr = port;
115         return ret;
116     }
117
118     INT_DEBUG("Could not parse int_message: %s\n", in);
119     return ret;
120 }
121
122 static void tx_cont(void * arg){
123     INT_DEBUG("Continuation called :-(\n");
124 }
125
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);
129
130     // Parse output and instruct controller
131     int inport, outport;
132     char class[255], lbl[255];
133     char inmsg[255], outmsg[255];
134
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);
138         if(res != 6) {
139             debug_printf("WARNING: Invalid SKB response. (%d)\n", __LINE__);
140             continue;
141         }
142         INT_DEBUG("Scanned %d args: %s %s %d %s %d %s\n", res, lbl, class,
143                 inport, inmsg, outport, outmsg );
144
145         struct controller_driver * dest = find_controller(lbl, class);
146         if(dest == NULL){
147             INT_DEBUG("No controller driver found.");
148         } else {
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));
153         }
154     }
155     return SYS_ERR_OK;
156 }
157
158 #define INVALID_VECTOR ((uint64_t)-1)
159
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__);
163     errval_t err;
164
165     uint64_t int_src_num = INVALID_VECTOR;
166     err = invoke_irqsrc_get_vector(intsource, &int_src_num);
167     assert(err_is_ok(err));
168
169     uint64_t dest_vec = INVALID_VECTOR;
170     err = invoke_irqdest_get_vector(intdest, &dest_vec);
171     assert(err_is_ok(err));
172
173     //TODO fix this
174     uint64_t dest_cpu = INVALID_VECTOR;
175     err = invoke_irqdest_get_cpu(intdest, &dest_cpu);
176     assert(err_is_ok(err));
177
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->rx_vtbl.route_response(b, err);
186         return;
187     }
188
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");
192     }
193     b->rx_vtbl.route_response(b, err);
194 }
195
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);
202     c->label[l1] = '\0';
203
204     c->class = malloc(l2+1);
205     assert(c->class != NULL);
206     strncpy(c->class, class, l2);
207     c->label[l2] = '\0';
208     INT_DEBUG("ctrl_register_controller, label=%s, class=%s\n",c->label, c->class);
209
210     c->binding = _binding;
211 }
212
213
214 static struct int_route_service_rx_vtbl driver_rx_vtbl = {
215         .route_call = driver_route_call
216
217 };
218
219 static struct int_route_controller_rx_vtbl ctrl_rx_vtbl = {
220         .register_controller = ctrl_register_controller
221 };
222
223 static errval_t driver_connect_cb(void *st, struct int_route_service_binding *b) {
224     INT_DEBUG("%s: enter\n", __FUNCTION__);
225     b->st = NULL;
226     b->rx_vtbl = driver_rx_vtbl;
227     return SYS_ERR_OK;
228
229 }
230
231 static errval_t ctrl_connect_cb(void *st, struct int_route_controller_binding *b) {
232     INT_DEBUG("%s: enter\n", __FUNCTION__);
233     b->st = NULL;
234     b->rx_vtbl = ctrl_rx_vtbl;
235     return SYS_ERR_OK;
236
237 }
238
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));
242
243     err = nameservice_register("int_route_service", iref);
244     if (err_is_fail(err)) {
245         USER_PANIC_ERR(err, "nameservice_register 1 failed");
246     };
247     exported++;
248 }
249
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));
253
254     err = nameservice_register("int_ctrl_service", iref);
255     if (err_is_fail(err)) {
256         USER_PANIC_ERR(err, "nameservice_register 2 failed");
257     };
258     exported++;
259 }
260
261
262 // The main function of this service
263 errval_t int_route_service_init(void)
264 {
265     errval_t err;
266     INT_DEBUG("int_route_service_init\n");
267     // We need skb connection
268     skb_client_connect();
269
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);
273
274     if(err_is_fail(err)){
275         USER_PANIC_ERR(err, "int_route_service_export failed");
276     }
277
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");
282     }
283
284
285     // HACK: Due to cyclic dependency, we must make sure the service has been exported before
286     // returning.
287
288     while(exported != 2){
289         event_dispatch(get_default_waitset());
290     }
291     return SYS_ERR_OK;
292 }