kaluga: waiting for all spawnds to be up before starting drivers/apps
[barrelfish] / usr / kaluga / x86.c
1 /**
2  * \file
3  * \brief Device manager for Barrelfish.
4  *
5  * Interacts with the SKB / PCI to start cores, drivers etc.
6  *
7  * x86 specific startup code
8  *
9  */
10
11 /*
12  * Copyright (c) 2007-2010, 2016 ETH Zurich.
13  * Copyright (c) 2015, Hewlett Packard Enterprise Development LP.
14  * All rights reserved.
15  *
16  * This file is distributed under the terms in the attached LICENSE file.
17  * If you do not find this file, copies can be found by writing to:
18  * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
19  */
20
21 #include <barrelfish/barrelfish.h>
22 #include <skb/skb.h>
23 #include "kaluga.h"
24
25 #define SERIAL_IRQ 4
26 #define SERIAL_BINARY "serial_pc16550d"
27
28 #define LPC_TIMER_IRQ 0
29 #define LPC_TIMER_BINARY "lpc_timer"
30
31 static errval_t start_serial(void){
32     errval_t err;
33     struct module_info * mi = find_module(SERIAL_BINARY);
34     if (mi != NULL) {
35         // Get internal int number. COM1 uses ISA nr. 4
36         struct driver_argument arg;
37         err = skb_execute_query("isa_irq_to_int(%d,N), writeln(N).", SERIAL_IRQ);
38         if(err_is_fail(err)){
39             DEBUG_SKB_ERR(err, "skb_execute_query");
40             return err;
41         }
42         int int_nr;
43         err = skb_read_output("%d", &int_nr);
44         if(err_is_fail(err)){
45             DEBUG_ERR(err, "skb_read_output");
46             return err;
47         }
48         KALUGA_DEBUG("Found internal int number (%d) for serial.\n", int_nr);
49         arg.int_arg.int_range_start = int_nr;
50         arg.int_arg.int_range_end = int_nr;
51         arg.int_arg.model = INT_MODEL_LEGACY;
52
53         struct cnoderef argnode_ref;
54         err = cnode_create_l2(&arg.arg_caps, &argnode_ref);
55         if(err_is_fail(err)){
56             DEBUG_ERR(err, "cnode_create_l2");
57             return err;
58         }
59
60         // Build irq src cap
61         struct capref cap;
62         cap.cnode = argnode_ref;
63         cap.slot = 0;
64         err = sys_debug_create_irq_src_cap(cap, int_nr, int_nr);
65
66         if(err_is_fail(err)){
67             DEBUG_ERR(err, "Could not create int_src cap");
68             return err;
69         }
70         err = mi->start_function(0, mi, "hw.legacy.uart.1 {}", &arg);
71         if(err_is_fail(err)){
72             USER_PANIC_ERR(err, "serial->start_function");
73         }
74     } else {
75         printf("Kaluga: Not starting \"%s\", binary not found\n", SERIAL_BINARY);
76         return KALUGA_ERR_MODULE_NOT_FOUND;
77     }
78     return SYS_ERR_OK;
79 }
80
81 static errval_t start_lpc_timer(void){
82     errval_t err;
83     struct module_info * mi = find_module(LPC_TIMER_BINARY);
84     if (mi != NULL) {
85         // Get internal int number.
86         struct driver_argument arg;
87         err = skb_execute_query("isa_irq_to_int(%d,N), writeln(N).", LPC_TIMER_IRQ);
88         if(err_is_fail(err)){
89             DEBUG_SKB_ERR(err, "skb_execute");
90             return err;
91         }
92         int int_nr;
93         err = skb_read_output("%d", &int_nr);
94         if(err_is_fail(err)){
95             DEBUG_ERR(err, "skb_read_output");
96             return err;
97         }
98         KALUGA_DEBUG("Found internal int number (%d) for lpc_timer.\n", int_nr);
99         arg.int_arg.int_range_start = int_nr;
100         arg.int_arg.int_range_end = int_nr;
101         arg.int_arg.model = INT_MODEL_LEGACY;
102
103         struct cnoderef argnode_ref;
104         err = cnode_create_l2(&arg.arg_caps, &argnode_ref);
105         if(err_is_fail(err)){
106             DEBUG_ERR(err, "cnode_create_l2");
107             return err;
108         }
109
110         // Build irq src cap
111         struct capref cap;
112         cap.cnode = argnode_ref;
113         cap.slot = 0;
114         err = sys_debug_create_irq_src_cap(cap, int_nr, int_nr);
115
116         if(err_is_fail(err)){
117             DEBUG_ERR(err, "Could not create int_src cap");
118             return err;
119         }
120         err = mi->start_function(0, mi, "hw.legacy.timer.1 {}", &arg);
121         if(err_is_fail(err)){
122             USER_PANIC_ERR(err, "serial->start_function");
123         }
124     } else {
125         printf("Kaluga: Not starting \"%s\", binary not found\n", LPC_TIMER_BINARY);
126         return KALUGA_ERR_MODULE_NOT_FOUND;
127     }
128     return SYS_ERR_OK;
129 }
130
131 errval_t arch_startup(char * add_device_db_file)
132 {
133     errval_t err = SYS_ERR_OK;
134     // We need to run on core 0
135     // (we are responsible for booting all the other cores)
136     assert(my_core_id == BSP_CORE_ID);
137     KALUGA_DEBUG("Kaluga running on x86.\n");
138
139     err = skb_client_connect();
140     if (err_is_fail(err)) {
141         USER_PANIC_ERR(err, "Connect to SKB.");
142     }
143
144     // Make sure the driver db is loaded
145     err = skb_execute("[device_db].");
146     if (err_is_fail(err)) {
147         USER_PANIC_SKB_ERR(err, "Device DB not loaded.");
148     }
149     if(add_device_db_file != NULL){
150         err = skb_execute_query("[%s].", add_device_db_file);
151         if(err_is_fail(err)){
152             USER_PANIC_SKB_ERR(err,"Additional device db file %s not loaded.", add_device_db_file);
153         }
154     }
155
156     // The current boot protocol needs us to have
157     // knowledge about how many CPUs are available at boot
158     // time in order to start-up properly.
159     char* record = NULL;
160     err = oct_barrier_enter("barrier.acpi", &record, 2);
161
162     KALUGA_DEBUG("Kaluga: watch_for_cores\n");
163
164     err = watch_for_cores();
165     if (err_is_fail(err)) {
166         USER_PANIC_ERR(err, "Watching cores.");
167     }
168
169     KALUGA_DEBUG("Kaluga: pci_root_bridge\n");
170
171     err = watch_for_pci_root_bridge();
172     if (err_is_fail(err)) {
173         USER_PANIC_ERR(err, "Watching PCI root bridges.");
174     }
175
176     KALUGA_DEBUG("Kaluga: int_controller_devices\n");
177
178     err = watch_for_int_controller();
179     if (err_is_fail(err)) {
180         USER_PANIC_ERR(err, "Watching interrupt controllers.");
181     }
182
183     KALUGA_DEBUG("Kaluga: wait_for_all_spawnds\n");
184
185     err = wait_for_all_spawnds();
186     if (err_is_fail(err)) {
187         USER_PANIC_ERR(err, "Unable to wait for spawnds failed.");
188     }
189
190     KALUGA_DEBUG("Kaluga: pci_devices\n");
191
192     err = watch_for_pci_devices();
193     if (err_is_fail(err)) {
194         USER_PANIC_ERR(err, "Watching PCI devices.");
195     }
196
197     KALUGA_DEBUG("Kaluga: Starting serial...\n");
198     err = start_serial();
199     if (err_is_fail(err) && err != KALUGA_ERR_MODULE_NOT_FOUND) {
200         USER_PANIC_ERR(err, "start_serial");
201     }
202
203     KALUGA_DEBUG("Kaluga: Starting lpc timer...\n");
204     err = start_lpc_timer();
205     if (err_is_fail(err) && err != KALUGA_ERR_MODULE_NOT_FOUND) {
206         USER_PANIC_ERR(err, "start_lpc_timer");
207     }
208
209     return SYS_ERR_OK;
210 }