5b18de7b641fcf682990cc622e9e6fc99ca43424
[barrelfish] / usr / kaluga / start_pci.c
1 /**
2  * \file
3  * \brief Code responsible for booting application cores
4  */
5
6 /*
7  * Copyright (c) 2007, 2008, 2009, 2010, 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
13  */
14
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <assert.h>
19
20 #include <barrelfish/barrelfish.h>
21
22 #include <octopus/octopus.h>
23 #include <if/octopus_thc.h>
24 #include <skb/skb.h>
25 #include <thc/thc.h>
26
27 #include "kaluga.h"
28
29 static void pci_change_event(octopus_mode_t mode, char* device_record, void* st);
30
31 static void spawnd_up_event(octopus_mode_t mode, char* spawnd_record, void* st)
32 {
33     assert(mode & OCT_ON_SET);
34     uint64_t iref;
35     errval_t err = oct_read(spawnd_record, "_ { iref: %d }", &iref);
36     if (err_is_fail(err)) {
37         USER_PANIC_ERR(err, "Failed to read iref from spawnd record?");
38     }
39
40     // Pass the iref as state, this tells pci_change_event that we
41     // don't need to look again for the spawnd iref
42     // XXX: Pointer
43     pci_change_event(OCT_ON_SET, st, (void*)(uintptr_t)iref);
44     free(spawnd_record);
45 }
46
47 static errval_t wait_for_spawnd(coreid_t core, void* state)
48 {
49     // Check if the core we're spawning on is already up...
50     struct octopus_thc_client_binding_t* cl = oct_get_thc_client();
51     errval_t error_code;
52     octopus_trigger_t t = oct_mktrigger(OCT_ERR_NO_RECORD,
53             octopus_BINDING_EVENT, OCT_ON_SET, spawnd_up_event, state);
54
55     // Construct service name
56     static char* format = "spawn.%"PRIuCOREID" { iref: _ }";
57     int length = snprintf(NULL, 0, format, core);
58     char* query = malloc(length+1);
59     snprintf(query, length+1, format, core);
60
61     errval_t err = cl->call_seq.get(cl, query, t, NULL, NULL, &error_code);
62     free(query);
63
64     if (err_is_fail(err)) {
65         return err;
66     }
67
68     return error_code;
69 }
70
71 static void pci_change_event(octopus_mode_t mode, char* device_record, void* st)
72 {
73     errval_t err;
74     char intcaps_debug_msg[100];
75     char *binary_name = NULL;
76     strcpy(intcaps_debug_msg, "none");
77     if (mode & OCT_ON_SET) {
78         KALUGA_DEBUG("pci_change_event: device_record: %s\n", device_record);
79         uint64_t vendor_id, device_id, bus, dev, fun;
80         err = oct_read(device_record, "_ { vendor: %d, device_id: %d, bus: %d, device: %d,"
81                 " function: %d }",
82                 &vendor_id, &device_id, &bus, &dev, &fun);
83         if (err_is_fail(err)) {
84             USER_PANIC_ERR(err, "Got malformed device record?");
85         }
86         
87         /* duplicate device record as we may need it for later */
88         device_record = strdup(device_record);
89         assert(device_record);
90         
91
92         // Ask the SKB which binary and where to start it...
93         static char* query = "find_pci_driver(pci_card(%"PRIu64", %"PRIu64", _, _, _), Driver),"
94                              "writeln(Driver).";
95         err = skb_execute_query(query, vendor_id, device_id);
96         if (err_no(err) == SKB_ERR_EXECUTION) {
97             KALUGA_DEBUG("No PCI driver found for: VendorId=0x%"PRIx64", "
98                          "DeviceId=0x%"PRIx64"\n",
99                     vendor_id, device_id);
100             goto out;
101         }
102         else if (err_is_fail(err)) {
103             DEBUG_SKB_ERR(err, "Failed to query SKB.\n");
104             goto out;
105         }
106
107         // XXX: Find better way to parse binary name from SKB
108         binary_name = malloc(strlen(skb_get_output()));
109         coreid_t core;
110         uint8_t multi;
111         uint8_t int_model_in;
112         struct int_startup_argument int_arg;
113         int_arg.int_range_start = 1000;
114         int_arg.int_range_end = 1004;
115         coreid_t offset;
116         err = skb_read_output("driver(%"SCNu8", %"SCNu8", %"SCNu8", %[^,], "
117                 "%"SCNu8")", &core, &multi, &offset, binary_name, &int_model_in);
118         if(err_is_fail(err)){
119             USER_PANIC_SKB_ERR(err, "Could not parse SKB output.\n");
120         }
121         int_arg.model = int_model_in;
122
123         struct driver_argument driver_arg;
124         driver_arg.int_arg = int_arg;
125         // TODO: every driver should specify the int_model in device_db
126         // until then, we treat them like legacy, so they can use the standard
127         // pci client functionality.
128         if(int_arg.model == INT_MODEL_LEGACY || int_arg.model == INT_MODEL_NONE){
129             KALUGA_DEBUG("Starting driver (%s) with legacy interrupts\n", binary_name);
130             // No controller has to instantiated, but we need to get caps for the int numbers
131             err = skb_execute_query("get_pci_legacy_int_range(addr(%"PRIu64",%"PRIu64",%"PRIu64"),Li),"
132                     "writeln(Li).", bus, dev, fun);
133             KALUGA_DEBUG("(Driver=%s,bus=%"PRIu64",dev=%"PRIu64",fun=%"PRIu64") "
134                     "int_range skb reply: %s\n",
135                     binary_name, bus, dev, fun, skb_get_output() );
136
137             // For debugging
138             strncpy(intcaps_debug_msg, skb_get_output(), sizeof(intcaps_debug_msg));
139             char * nl = strchr(intcaps_debug_msg, '\n');
140             if(nl) *nl = '\0';
141             intcaps_debug_msg[99] = '\0';
142
143             uint64_t start=0, end=0;
144             err = skb_read_output("%"SCNu64", %"SCNu64, &start, &end);
145             if(err_is_fail(err)){
146                 DEBUG_SKB_ERR(err, "Could not parse SKB output. Not starting driver.\n");
147                 goto out;
148             }
149
150             struct cnoderef argnode_ref;
151             err = cnode_create_l2(&driver_arg.arg_caps, &argnode_ref);
152             if(err_is_fail(err)){
153                 USER_PANIC_ERR(err, "Could not cnode_create_l2");
154             }
155
156             struct capref cap;
157             cap.cnode = argnode_ref;
158             cap.slot = 0;
159             err = sys_debug_create_irq_src_cap(cap, start, end);
160             if(err_is_fail(err)){
161                 USER_PANIC_ERR(err, "Could not create int_src cap");
162             }
163         } else if(int_arg.model == INT_MODEL_MSI){
164             KALUGA_DEBUG("Starting driver (%s) with MSI interrupts\n", binary_name);
165             // TODO instantiate controller
166         } else if(int_arg.model == INT_MODEL_MSIX){
167             KALUGA_DEBUG("Starting driver (%s) with MSI-x interrupts\n", binary_name);
168             // TODO instantiate controller
169         } else {
170             KALUGA_DEBUG("No interrupt model specified for %s. No interrupts for this driver.\n",
171                     binary_name);
172         }
173
174         struct module_info* mi = find_module(binary_name);
175         if (mi == NULL) {
176             KALUGA_DEBUG("Driver %s not loaded. Ignore.\n", binary_name);
177             goto out;
178         }
179
180         set_multi_instance(mi, multi);
181         set_core_id_offset(mi, offset);
182
183         // Wait until the core where we start the driver
184         // is ready
185         if (st == NULL && core != my_core_id) {
186             err = wait_for_spawnd(core, device_record);
187             if (err_no(err) == OCT_ERR_NO_RECORD) {
188                 KALUGA_DEBUG("Core where driver %s runs is not up yet.\n",
189                         mi->binary);
190                 // Don't want to free device record yet...
191                 return;
192             }
193             else if (err_is_fail(err)) {
194                 DEBUG_ERR(err, "Waiting for core %d failed?\n", core);
195                 goto out;
196             }
197         }
198
199         // If we've come here the core where we spawn the driver
200         // is already up
201         printf("Kaluga: Starting \"%s\" for (bus=%"PRIu64",dev=%"PRIu64",fun=%"PRIu64")"
202                ", intcaps: %s, on core %"PRIuCOREID"\n",
203                binary_name, bus, dev, fun, intcaps_debug_msg, core);
204
205         err = mi->start_function(core, mi, device_record, &driver_arg);
206         switch (err_no(err)) {
207         case SYS_ERR_OK:
208             KALUGA_DEBUG("Spawned PCI driver: %s\n", mi->binary);
209             set_started(mi);
210             break;
211
212         case KALUGA_ERR_DRIVER_ALREADY_STARTED:
213             KALUGA_DEBUG("%s already running.\n", mi->binary);
214             break;
215
216         case KALUGA_ERR_DRIVER_NOT_AUTO:
217             KALUGA_DEBUG("%s not declared as auto, ignore.\n", mi->binary);
218             break;
219
220         default:
221             DEBUG_ERR(err, "Unhandled error while starting %s\n", mi->binary);
222             break;
223         }
224     }
225
226 out:
227     free(device_record);
228     free(binary_name);
229 }
230
231 errval_t watch_for_pci_devices(void)
232 {
233     static char* pci_device  = "r'hw\\.pci\\.device\\.[0-9]+' { "
234                                " bus: _, device: _, function: _, vendor: _,"
235                                " device_id: _, class: _, subclass: _, "
236                                " prog_if: _ }";
237     octopus_trigger_id_t tid;
238     return oct_trigger_existing_and_watch(pci_device, pci_change_event, NULL, &tid);
239 }
240
241 static void bridge_change_event(octopus_mode_t mode, char* bridge_record, void* st)
242 {
243     if (mode & OCT_ON_SET) {
244         // No need to ask the SKB as we always start pci for
245         // in case we find a root bridge
246         struct module_info* mi = find_module("pci");
247         if (mi == NULL) {
248             KALUGA_DEBUG("PCI driver not found or not declared as auto.");
249             return;
250         }
251
252         // XXX: always spawn on my_core_id; otherwise we need to check that
253         // the other core is already up
254         errval_t err = mi->start_function(my_core_id, mi, bridge_record, NULL);
255         switch (err_no(err)) {
256         case SYS_ERR_OK:
257             KALUGA_DEBUG("Spawned PCI bus driver: %s\n", mi->binary);
258             set_started(mi);
259             break;
260
261         case KALUGA_ERR_DRIVER_ALREADY_STARTED:
262             KALUGA_DEBUG("%s already running.\n", mi->binary);
263             break;
264
265         case KALUGA_ERR_DRIVER_NOT_AUTO:
266             KALUGA_DEBUG("%s not declared as auto, ignore.\n", mi->binary);
267             break;
268
269         default:
270             DEBUG_ERR(err, "Unhandled error while starting %s\n", mi->binary);
271             break;
272         }
273     }
274 }
275
276 errval_t watch_for_pci_root_bridge(void)
277 {
278     static char* root_bridge = "r'hw\\.pci\\.rootbridge\\.[0-9]+' { "
279                                " bus: _, device: _, function: _, maxbus: _,"
280                                " acpi_node: _ }";
281     octopus_trigger_id_t tid;
282     return oct_trigger_existing_and_watch(root_bridge, bridge_change_event,
283             NULL, &tid);
284 }