3 * \brief Code responsible for booting application cores
7 * Copyright (c) 2007, 2008, 2009, 2010, 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
20 #include <barrelfish/barrelfish.h>
22 #include <octopus/octopus.h>
23 #include <if/octopus_thc.h>
29 static void pci_change_event(octopus_mode_t mode, char* device_record, void* st);
31 static void spawnd_up_event(octopus_mode_t mode, char* spawnd_record, void* st)
33 assert(mode & OCT_ON_SET);
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?");
40 // Pass the iref as state, this tells pci_change_event that we
41 // don't need to look again for the spawnd iref
43 pci_change_event(OCT_ON_SET, st, (void*)(uintptr_t)iref);
47 static errval_t wait_for_spawnd(coreid_t core, void* state)
49 // Check if the core we're spawning on is already up...
50 struct octopus_thc_client_binding_t* cl = oct_get_thc_client();
52 octopus_trigger_t t = oct_mktrigger(OCT_ERR_NO_RECORD,
53 octopus_BINDING_EVENT, OCT_ON_SET, spawnd_up_event, state);
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);
61 errval_t err = cl->call_seq.get(cl, query, t, NULL, NULL, &error_code);
64 if (err_is_fail(err)) {
71 static void pci_change_event(octopus_mode_t mode, char* device_record, void* st)
74 if (mode & OCT_ON_SET) {
75 uint64_t vendor_id, device_id, bus, dev, fun;
76 err = oct_read(device_record, "_ { vendor: %d, device_id: %d, bus: %d, device: %d,"
78 &vendor_id, &device_id, &bus, &dev, &fun);
79 if (err_is_fail(err)) {
80 USER_PANIC_ERR(err, "Got malformed device record?");
83 /* duplicate device record as we may need it for later */
84 device_record = strdup(device_record);
85 assert(device_record);
88 // Ask the SKB which binary and where to start it...
89 static char* query = "find_pci_driver(pci_card(%"PRIu64", %"PRIu64", _, _, _), Driver),"
91 err = skb_execute_query(query, vendor_id, device_id);
92 if (err_no(err) == SKB_ERR_EXECUTION) {
93 KALUGA_DEBUG("No PCI driver found for: VendorId=0x%"PRIx64", "
94 "DeviceId=0x%"PRIx64"\n",
95 vendor_id, device_id);
98 else if (err_is_fail(err)) {
99 DEBUG_ERR(err, "Failed to query SKB.\n");
103 // XXX: Find better way to parse binary name from SKB
104 char* binary_name = malloc(strlen(skb_get_output()));
107 uint8_t int_model_in;
108 struct int_startup_argument int_arg;
109 int_arg.int_range_start = 1000;
110 int_arg.int_range_end = 1004;
112 err = skb_read_output("driver(%"SCNu8", %"SCNu8", %"SCNu8", %[^,], %"SCNu8")", &core, &multi, &offset,
113 binary_name, &int_model_in);
114 if(err_is_fail(err)){
115 USER_PANIC_ERR(err, "Could not parse SKB output: %s\n", skb_get_output());
117 int_arg.model = int_model_in;
119 struct driver_argument driver_arg;
120 driver_arg.int_arg = int_arg;
121 if(int_arg.model == INT_MODEL_LEGACY){
122 KALUGA_DEBUG("Starting driver with legacy interrupts\n");
123 // No controller has to instantiated, but we need to get caps for the int numbers
124 err = skb_execute_query("get_pci_legacy_int_range(addr(%"PRIu64",%"PRIu64",%"PRIu64"),Li),"
125 "writeln(Li).", bus, dev, fun);
126 KALUGA_DEBUG("int_range skb reply: %s\n", skb_get_output() );
127 if(err_is_fail(err)){
128 USER_PANIC_ERR(err, "Could not parse SKB output: %s\n", skb_get_output());
130 struct list_parser_status pa_sta;
131 skb_read_list_init(&pa_sta);
133 struct cnoderef argnode_ref;
134 err = cnode_create(&driver_arg.arg_caps, &argnode_ref,
135 DEFAULT_CNODE_SLOTS, NULL);
137 if(err_is_fail(err)){
138 USER_PANIC_ERR(err, "Could not create int_src cap");
141 for(int i=0; skb_read_list(&pa_sta, "int(%d)", &int_num); i++){
143 KALUGA_DEBUG("Interrupt for driver: %d\n", int_num);
145 cap.cnode = argnode_ref;
147 err = sys_debug_create_irq_src_cap(cap, int_num);
149 if(err_is_fail(err)){
150 USER_PANIC_ERR(err, "Could not create int_src cap");
153 } else if(int_arg.model == INT_MODEL_MSI){
154 KALUGA_DEBUG("Starting driver with MSI interrupts");
155 // TODO instantiate controller
156 } else if(int_arg.model == INT_MODEL_MSIX){
157 KALUGA_DEBUG("Starting driver with MSI-x interrupts");
158 // TODO instantiate controller
160 KALUGA_DEBUG("No interrupt model specified for %s. No interrupts for this driver.\n",
164 struct module_info* mi = find_module(binary_name);
167 KALUGA_DEBUG("Driver %s not loaded. Ignore.\n", binary_name);
171 set_multi_instance(mi, multi);
172 set_core_id_offset(mi, offset);
174 // Wait until the core where we start the driver
176 if (st == NULL && core != my_core_id) {
177 err = wait_for_spawnd(core, device_record);
178 if (err_no(err) == OCT_ERR_NO_RECORD) {
179 KALUGA_DEBUG("Core where driver %s runs is not up yet.\n",
181 // Don't want to free device record yet...
184 else if (err_is_fail(err)) {
185 DEBUG_ERR(err, "Waiting for core %d failed?\n", core);
190 // If we've come here the core where we spawn the driver
192 err = mi->start_function(core, mi, device_record, &driver_arg);
193 switch (err_no(err)) {
195 KALUGA_DEBUG("Spawned PCI driver: %s\n", mi->binary);
199 case KALUGA_ERR_DRIVER_ALREADY_STARTED:
200 KALUGA_DEBUG("%s already running.\n", mi->binary);
203 case KALUGA_ERR_DRIVER_NOT_AUTO:
204 KALUGA_DEBUG("%s not declared as auto, ignore.\n", mi->binary);
208 DEBUG_ERR(err, "Unhandled error while starting %s\n", mi->binary);
217 errval_t watch_for_pci_devices(void)
219 static char* pci_device = "r'hw\\.pci\\.device\\.[0-9]+' { "
220 " bus: _, device: _, function: _, vendor: _,"
221 " device_id: _, class: _, subclass: _, "
223 octopus_trigger_id_t tid;
224 return oct_trigger_existing_and_watch(pci_device, pci_change_event, NULL, &tid);
227 static void bridge_change_event(octopus_mode_t mode, char* bridge_record, void* st)
229 if (mode & OCT_ON_SET) {
230 // No need to ask the SKB as we always start pci for
231 // in case we find a root bridge
232 struct module_info* mi = find_module("pci");
234 KALUGA_DEBUG("PCI driver not found or not declared as auto.");
238 // XXX: always spawn on my_core_id; otherwise we need to check that
239 // the other core is already up
240 errval_t err = mi->start_function(my_core_id, mi, bridge_record, NULL);
241 switch (err_no(err)) {
243 KALUGA_DEBUG("Spawned PCI bus driver: %s\n", mi->binary);
247 case KALUGA_ERR_DRIVER_ALREADY_STARTED:
248 KALUGA_DEBUG("%s already running.\n", mi->binary);
251 case KALUGA_ERR_DRIVER_NOT_AUTO:
252 KALUGA_DEBUG("%s not declared as auto, ignore.\n", mi->binary);
256 DEBUG_ERR(err, "Unhandled error while starting %s\n", mi->binary);
262 errval_t watch_for_pci_root_bridge(void)
264 static char* root_bridge = "r'hw\\.pci\\.rootbridge\\.[0-9]+' { "
265 " bus: _, device: _, function: _, maxbus: _,"
267 octopus_trigger_id_t tid;
268 return oct_trigger_existing_and_watch(root_bridge, bridge_change_event,