ed4925d468fac9d953192ef00d026b21b8a568ed
[barrelfish] / usr / kaluga / driver_startup.c
1 /*
2  * Copyright (c) 2016, ETH Zurich.
3  * All rights reserved.
4  *
5  * This file is distributed under the terms in the attached LICENSE file.
6  * If you do not find this file, copies can be found by writing to:
7  * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
8  */
9
10 #include <stdio.h>
11 #include <string.h>
12
13 #include <barrelfish/barrelfish.h>
14 #include <barrelfish/spawn_client.h>
15
16 #include <pci/pci.h> // for pci_address
17
18 #ifdef __arm__
19 #include <if/monitor_blocking_rpcclient_defs.h>
20 #endif
21
22 #ifdef __aarch64__
23 #include <if/monitor_blocking_rpcclient_defs.h>
24 #endif
25
26 #include "kaluga.h"
27
28 #if defined(__x86__) || defined(__ARM_ARCH_8A)
29
30 // Add an argument to argc/argv pair. argv must be mallocd!
31 static void argv_push(int * argc, char *** argv, char * new_arg){
32     int new_size = *argc + 1;
33     //char ** argv_old = *argv;
34     //*argv = malloc((new_size+1) * sizeof(char*));
35     //memcpy(*argv, argv_old, sizeof(char*) * (*argc + 1));
36     *argv = realloc(*argv, (new_size+1) * sizeof(char*)); // +1 for last NULL entry.
37     if(*argv == NULL){
38         USER_PANIC("Could not allocate argv memory");
39     }
40     *argc = new_size;
41     (*argv)[new_size-1] = new_arg;
42     (*argv)[new_size] = NULL;
43 }
44
45 errval_t default_start_function(coreid_t where,
46                                 struct module_info* mi,
47                                 char* record, struct int_startup_argument * int_arg)
48 {
49     assert(mi != NULL);
50     errval_t err = SYS_ERR_OK;
51     coreid_t core;
52     /*
53      *  XXX: there may be more device using this driver, so starting it a second time
54      *       may be needed.
55      */
56     if (!can_start(mi)) {
57         return KALUGA_ERR_DRIVER_ALREADY_STARTED;
58     }
59
60     core = where + get_core_id_offset(mi);
61
62     if (!is_auto_driver(mi)) {
63         return KALUGA_ERR_DRIVER_NOT_AUTO;
64     }
65
66     // Construct additional command line arguments containing pci-id.
67     // We need one extra entry for the new argument.
68     char **argv = NULL;
69     int argc = mi->argc;
70     argv = malloc((argc+1) * sizeof(char *)); // +1 for trailing NULL
71     assert(argv != NULL);
72     memcpy(argv, mi->argv, (argc+1) * sizeof(char *));
73     assert(argv[argc] == NULL);
74
75     uint64_t vendor_id, device_id, bus, dev, fun;
76     err = oct_read(record, "_ { bus: %d, device: %d, function: %d, vendor: %d, device_id: %d }",
77                     &bus, &dev, &fun, &vendor_id, &device_id);
78
79     char * int_arg_str = NULL;
80     if(int_arg != NULL){
81         // This malloc int_arg_str
82         int_startup_argument_to_string(int_arg, &int_arg_str);
83         KALUGA_DEBUG("Adding int_arg_str: %s\n", int_arg_str);
84         argv_push(&argc, &argv, int_arg_str);
85     }
86
87     char * pci_arg_str = NULL;
88     if (err_is_ok(err)) {
89         // We assume that we're starting a device if the query above succeeds
90         // and therefore append the pci vendor and device id to the argument
91         // list.
92         pci_arg_str = malloc(26);
93         // Make sure pci vendor and device id fit into our argument
94         assert(vendor_id < 0x9999 && device_id < 0x9999);
95         snprintf(pci_arg_str, 26, "%04"PRIx64":%04"PRIx64":%04"PRIx64":%04"
96                         PRIx64":%04"PRIx64, vendor_id, device_id, bus, dev, fun);
97
98         argv_push(&argc, &argv, pci_arg_str);
99     }
100
101
102     err = spawn_program(core, mi->path, argv,
103                     environ, 0, get_did_ptr(mi));
104
105     if (err_is_fail(err)) {
106         DEBUG_ERR(err, "Spawning %s failed.", mi->path);
107     }
108
109     free(argv);
110     free(pci_arg_str);
111     free(int_arg_str);
112
113     return err;
114 }
115 #endif
116
117 errval_t start_networking(coreid_t core,
118                           struct module_info* driver,
119                           char* record, struct int_startup_argument * intarg)
120 {
121     assert(driver != NULL);
122     errval_t err = SYS_ERR_OK;
123
124     uint64_t vendor_id, device_id, bus, dev, fun;
125
126     /* check if we are using the supplied pci address of eth0 */
127     if (eth0.bus != 0xff || eth0.device != 0xff || eth0.function != 0xff) {
128         err = oct_read(record, "_ { bus: %d, device: %d, function: %d, vendor: %d, device_id: %d }",
129                             &bus, &dev, &fun, &vendor_id, &device_id);
130         assert(err_is_ok(err));
131
132         if ((eth0.bus != (uint8_t)bus)
133              | (eth0.device != (uint8_t)dev)
134              | (eth0.function != (uint8_t)fun)) {
135             KALUGA_DEBUG("start_networking: skipping card %" PRIu64 ":%" PRIu64 ":%"
136                          PRIu64"\n", bus, dev, fun);
137             return KALUGA_ERR_DRIVER_NOT_AUTO;
138         }
139     }
140
141     if (is_started(driver)) {
142         return KALUGA_ERR_DRIVER_ALREADY_STARTED;
143     }
144
145     if (!is_auto_driver(driver)) {
146         return KALUGA_ERR_DRIVER_NOT_AUTO;
147     }
148
149     struct module_info* netd = find_module("netd");
150     if (netd == NULL || !is_auto_driver(netd)) {
151         KALUGA_DEBUG("netd not found or not declared as auto.");
152         return KALUGA_ERR_DRIVER_NOT_AUTO;
153     }
154
155     struct module_info* ngd_mng = find_module("NGD_mng");
156     if (ngd_mng == NULL || !is_auto_driver(ngd_mng)) {
157         KALUGA_DEBUG("NGD_mng not found or not declared as auto.");
158         return KALUGA_ERR_DRIVER_NOT_AUTO;
159     }
160
161     err = default_start_function(core, driver, record, NULL);
162     if (err_is_fail(err)) {
163         DEBUG_ERR(err, "Spawning %s failed.", driver->path);
164         return err;
165     }
166
167     // XXX: Manually add cardname (overwrite first (auto) argument)
168     // +Weird convention, e1000n binary but cardname=e1000
169     char* cardname = strcmp(driver->binary, "e1000n") == 0 ? "e1000" : driver->binary;
170
171     size_t name_len = strlen("cardname=") + strlen(cardname) + 1;
172     char* card_argument = malloc(name_len);
173     sprintf(card_argument, "cardname=%s", cardname);
174     printf("############# starting network with arguments %s\n", card_argument);
175
176     // Spawn netd and ngd_mng
177     netd->argv[0] = card_argument;
178     err = spawn_program(core, netd->path, netd->argv, environ, 0, get_did_ptr(netd));
179
180     ngd_mng->argv[0] = card_argument;
181     err = spawn_program(core, ngd_mng->path, ngd_mng->argv, environ, 0,
182                         get_did_ptr(ngd_mng));
183
184     free(card_argument);
185     return err;
186 }
187
188 /* errval_t start_usb_manager(void) */
189 /* { */
190
191 /*     struct module_info* driver = find_module("usb_manager"); */
192 /*     if (driver == NULL || !is_auto_driver(driver)) { */
193 /*         KALUGA_DEBUG("NGD_mng not found or not declared as auto."); */
194 /*         return KALUGA_ERR_DRIVER_NOT_AUTO; */
195 /*     } */
196
197 /*     debug_printf("doing pandaboard related setup...\n"); */
198 /*     errval_t err; */
199
200 /*     struct monitor_blocking_rpc_client *cl = get_monitor_blocking_rpc_client(); */
201 /*     assert(cl != NULL); */
202
203 /*     // Request I/O Cap */
204 /*     struct capref requested_caps; */
205 /*     errval_t error_code; */
206
207 /*     err = cl->vtbl.get_io_cap(cl, &requested_caps, &error_code); */
208 /*     assert(err_is_ok(err) && err_is_ok(error_code)); */
209
210 /*     // Copy into correct slot */
211
212 /*     struct capref device_range_cap = NULL_CAP; */
213
214 /*     err = slot_alloc(&device_range_cap); */
215 /*     if (err_is_fail(err)) { */
216 /*         printf("slot alloc failed. Step 1\n"); */
217 /*         return (err); */
218 /*     } */
219 /*     struct capref tiler_cap = NULL_CAP; */
220
221 /*     err = slot_alloc(&tiler_cap); */
222 /*     if (err_is_fail(err)) { */
223 /*         DEBUG_ERR(err, "slot_alloc failed. Step 1\n"); */
224 /*         return (err); */
225 /*     } */
226
227 /*     err = cap_retype(device_range_cap, requested_caps, ObjType_DevFrame, 29); */
228
229 /*     struct capref l3_ocm_ram = NULL_CAP; */
230
231 /*     err = slot_alloc(&l3_ocm_ram); */
232 /*     if (err_is_fail(err)) { */
233 /*         DEBUG_ERR(err, "slot_alloc failed. Step 2\n"); */
234 /*         return (err); */
235 /*     } */
236
237 /*     err = cap_retype(l3_ocm_ram, device_range_cap, ObjType_DevFrame, 26); */
238 /*     if (err_is_fail(err)) { */
239 /*         DEBUG_ERR(err, "failed to retype the dev cap. Step 3\n"); */
240 /*         return (err); */
241 /*     } */
242
243 /*     struct capref l3_config_registers_cap; */
244 /*     err = slot_alloc(&l3_config_registers_cap); */
245 /*     if (err_is_fail(err)) { */
246 /*         DEBUG_ERR(err, "slot alloc failed. Step 4\n"); */
247 /*         return (err); */
248 /*     } */
249
250 /*     struct capref l4_domains_cap; */
251 /*     err = slot_alloc(&l4_domains_cap); */
252 /*     if (err_is_fail(err)) { */
253 /*         DEBUG_ERR(err, "slot_alloc failed. Step 5\n"); */
254 /*         return (err); */
255 /*     } */
256
257 /*     struct capref emif_registers_cap; */
258 /*     err = slot_alloc(&emif_registers_cap); */
259 /*     if (err_is_fail(err)) { */
260 /*         DEBUG_ERR(err, "slot_alloc failed. Step 6\n"); */
261 /*         return (err); */
262 /*     } */
263
264 /*     struct capref gpmc_iss_cap; */
265 /*     err = slot_alloc(&gpmc_iss_cap); */
266 /*     if (err_is_fail(err)) { */
267 /*         DEBUG_ERR(err, "slot_alloc failed. Step 7\n"); */
268 /*         return (err); */
269 /*     } */
270
271 /*     struct capref l3_emu_m3_sgx_cap; */
272 /*     err = slot_alloc(&l3_emu_m3_sgx_cap); */
273 /*     if (err_is_fail(err)) { */
274 /*         DEBUG_ERR(err, "slot_alloc failed. Step 8\n"); */
275 /*         return (err); */
276 /*     } */
277
278 /*     struct capref display_iva_cap; */
279 /*     err = slot_alloc(&display_iva_cap); */
280 /*     if (err_is_fail(err)) { */
281 /*         DEBUG_ERR(err, "slot_alloc failed. Step 9\n"); */
282 /*         return (err); */
283 /*     } */
284 /*     struct capref tmp_cap = display_iva_cap; */
285 /*     tmp_cap.slot++; */
286 /*     cap_delete(tmp_cap); */
287
288 /*     struct capref l4_PER_domain_cap; */
289 /*     err = slot_alloc(&l4_PER_domain_cap); */
290 /*     if (err_is_fail(err)) { */
291 /*         DEBUG_ERR(err, "slot_alloc failed. Step 12\n"); */
292 /*         return (err); */
293 /*     } */
294
295 /*     struct capref l4_ABE_domain_cap; */
296 /*     err = slot_alloc(&l4_ABE_domain_cap); */
297 /*     if (err_is_fail(err)) { */
298 /*         DEBUG_ERR(err, "slot_alloc failed. Step 11\n"); */
299 /*         return (err); */
300 /*     } */
301
302 /*     struct capref l4_CFG_domain_cap; */
303 /*     err = slot_alloc(&l4_CFG_domain_cap); */
304 /*     if (err_is_fail(err)) { */
305 /*         DEBUG_ERR(err, "slot_alloc failed. Step 12\n"); */
306 /*         return (err); */
307 /*     } */
308
309 /*     err = cap_retype(l4_PER_domain_cap, l4_domains_cap, ObjType_DevFrame, 24); */
310 /*     if (err_is_fail(err)) { */
311 /*         DEBUG_ERR(err, "failed to retype the cap. Step 13\n"); */
312 /*         return (err); */
313 /*     } */
314 /*     tmp_cap = l4_CFG_domain_cap; */
315 /*     tmp_cap.slot++; */
316 /*     cap_delete(tmp_cap); */
317
318 /*     struct frame_identity frameid;  // = {        0,        0    }; */
319
320 /*     err = invoke_frame_identify(l4_CFG_domain_cap, &frameid); */
321 /*     if (err_is_fail(err)) { */
322 /*         DEBUG_ERR(err, "could not identify the frame. Step 14\n"); */
323 /*     } */
324
325 /*     // get the 32 bit */
326 /*     uint32_t last = (uint32_t) (0xFFFFFFFF & (frameid.base)); */
327 /*     uint32_t size2 = frameid.bits; */
328
329 /*     /\* the L4 CFG domain cap must have address 0x4A000000 *\/ */
330 /*     assert(last == 0x4a000000); */
331
332 /*     /\* the size of the L4 CFG domain is 16k *\/ */
333 /*     assert(((1 << size2) / 1024) == (16 * 1024)); */
334
335 /* #define USB_SUBSYSTEM_L4_OFFSET 0x00062000 */
336 /* //#define USB_OHCI_OFFSET         (0x000A9000-USB_SUBSYSTEM_L4_OFFSET) */
337 /* #define USB_OHCI_OFFSET         0x00002800 */
338 /* #define USB_EHCI_OFFSET         0x00002C00 */
339
340 /* #define USB_ARM_EHCI_IRQ 109 */
341
342 /*     uint32_t tmp = (uint32_t) USB_EHCI_OFFSET + USB_SUBSYSTEM_L4_OFFSET; */
343
344 /*     char buf[255]; */
345 /*     uint8_t offset = 0; */
346 /*     driver->cmdargs = buf; */
347 /*     driver->argc = 3; */
348 /*     driver->argv[0] = driver->cmdargs+0; */
349
350 /*     snprintf(buf+offset, 255-offset, "ehci\0"); */
351 /*     offset += strlen(driver->argv[0])+1; */
352 /*     driver->argv[1] = driver->cmdargs+offset; */
353 /*     snprintf(buf+offset, 255-offset, "%u\0", tmp); */
354 /*     offset += strlen(driver->argv[1])+1; */
355 /*             driver->argv[2] = driver->cmdargs+offset; */
356 /*     snprintf(buf+offset, 255-offset, "%u\0", USB_ARM_EHCI_IRQ); */
357
358 /*     err = SYS_ERR_OK; */
359 /*     coreid_t core = 0; */
360
361 /*     if (is_started(driver)) { */
362 /*         debug_printf("driver is already started..."); */
363 /*         return KALUGA_ERR_DRIVER_ALREADY_STARTED; */
364 /*     } */
365
366 /*     err = spawn_program_with_caps(core, driver->path, driver->argv, environ, */
367 /*             NULL_CAP, l4_CFG_domain_cap, 0, &driver->did); */
368 /*     if (err_is_fail(err)) { */
369 /*         DEBUG_ERR(err, "Spawning %s failed.", driver->path); */
370 /*         return err; */
371 /*     } */
372
373 /*     return err; */
374 /* } */