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 <pci/pci.h>
24#include <acpi_client/acpi_client.h>
25#include "kaluga.h"
26
27#define SERIAL_IRQ 4
28#define SERIAL_BINARY "serial_pc16550d"
29
30#define LPC_TIMER_IRQ 0
31#define LPC_TIMER_BINARY "lpc_timer"
32
33static errval_t start_serial(void){
34    errval_t err;
35    struct module_info * mi = find_module(SERIAL_BINARY);
36    if (mi != NULL) {
37        // Get internal int number. COM1 uses ISA nr. 4
38        struct driver_argument arg;
39        err = init_driver_argument(&arg);
40        if(err_is_fail(err)){
41            DEBUG_ERR(err, "init_driver_argument failed\n");
42            return err;
43        }
44        err = skb_execute_query("isa_irq_to_int(%d,N), writeln(N).", SERIAL_IRQ);
45        if(err_is_fail(err)){
46            DEBUG_SKB_ERR(err, "skb_execute_query");
47            return err;
48        }
49        int int_nr;
50        err = skb_read_output("%d", &int_nr);
51        if(err_is_fail(err)){
52            DEBUG_ERR(err, "skb_read_output");
53            return err;
54        }
55        KALUGA_DEBUG("Found internal int number (%d) for serial.\n", int_nr);
56        arg.int_arg.int_range_start = int_nr;
57        arg.int_arg.int_range_end = int_nr;
58        arg.int_arg.model = INT_MODEL_LEGACY;
59
60        err = store_int_cap(int_nr, int_nr, &arg);
61        if(err_is_fail(err)){
62            DEBUG_ERR(err, "int_src_cap");
63            return err;
64        }
65        err = mi->start_function(0, mi, "hw.legacy.uart.1 {}", &arg);
66        if(err_is_fail(err)){
67            USER_PANIC_ERR(err, "serial->start_function");
68        }
69    } else {
70        printf("Kaluga: Not starting \"%s\", binary not found\n", SERIAL_BINARY);
71        return KALUGA_ERR_MODULE_NOT_FOUND;
72    }
73    return SYS_ERR_OK;
74}
75
76static errval_t start_lpc_timer(void){
77    errval_t err;
78    struct module_info * mi = find_module(LPC_TIMER_BINARY);
79    if (mi != NULL) {
80        // Get internal int number.
81        struct driver_argument arg;
82        init_driver_argument(&arg);
83
84        err = skb_execute_query("isa_irq_to_int(%d,N), writeln(N).", LPC_TIMER_IRQ);
85        if(err_is_fail(err)){
86            DEBUG_SKB_ERR(err, "skb_execute");
87            return err;
88        }
89        int int_nr;
90        err = skb_read_output("%d", &int_nr);
91        if(err_is_fail(err)){
92            DEBUG_ERR(err, "skb_read_output");
93            return err;
94        }
95        KALUGA_DEBUG("Found internal int number (%d) for lpc_timer.\n", int_nr);
96        arg.int_arg.int_range_start = int_nr;
97        arg.int_arg.int_range_end = int_nr;
98        arg.int_arg.model = INT_MODEL_LEGACY;
99
100        err = store_int_cap(int_nr, int_nr, &arg);
101        if(err_is_fail(err)){
102            DEBUG_ERR(err, "store_int_cap");
103            return err;
104        }
105
106        err = mi->start_function(0, mi, "hw.legacy.timer.1 {}", &arg);
107        if(err_is_fail(err)){
108            USER_PANIC_ERR(err, "serial->start_function");
109        }
110    } else {
111        printf("Kaluga: Not starting \"%s\", binary not found\n", LPC_TIMER_BINARY);
112        return KALUGA_ERR_MODULE_NOT_FOUND;
113    }
114    return SYS_ERR_OK;
115}
116
117errval_t arch_startup(char * add_device_db_file)
118{
119    errval_t err = SYS_ERR_OK;
120    // We need to run on core 0
121    // (we are responsible for booting all the other cores)
122    assert(my_core_id == BSP_CORE_ID);
123    KALUGA_DEBUG("Kaluga running on x86.\n");
124
125
126    err = skb_client_connect();
127    if (err_is_fail(err)) {
128        USER_PANIC_ERR(err, "Connect to SKB.");
129    }
130
131    // Make sure the driver db is loaded
132    err = skb_execute("[device_db].");
133    if (err_is_fail(err)) {
134        USER_PANIC_SKB_ERR(err, "Device DB not loaded.");
135    }
136    if(add_device_db_file != NULL){
137        err = skb_execute_query("[%s].", add_device_db_file);
138        if(err_is_fail(err)){
139            USER_PANIC_SKB_ERR(err,"Additional device db file %s not loaded.", add_device_db_file);
140        }
141    }
142
143    // The current boot protocol needs us to have
144    // knowledge about how many CPUs are available at boot
145    // time in order to start-up properly.
146    char* record = NULL;
147    err = oct_barrier_enter("barrier.acpi", &record, 2);
148
149    KALUGA_DEBUG("Kaluga: watch_for_cores\n");
150
151    err = watch_for_cores();
152    if (err_is_fail(err)) {
153        USER_PANIC_ERR(err, "Watching cores.");
154    }
155
156    KALUGA_DEBUG("Kaluga: pci_root_bridge\n");
157
158    err = watch_for_pci_root_bridge();
159    if (err_is_fail(err)) {
160        USER_PANIC_ERR(err, "Watching PCI root bridges.");
161    }
162
163    KALUGA_DEBUG("Kaluga: int_controller_devices\n");
164
165    err = watch_for_int_controller();
166    if (err_is_fail(err)) {
167        USER_PANIC_ERR(err, "Watching interrupt controllers.");
168    }
169
170    KALUGA_DEBUG("Kaluga: wait_for_all_spawnds\n");
171
172    err = wait_for_all_spawnds();
173    if (err_is_fail(err)) {
174        USER_PANIC_ERR(err, "Unable to wait for spawnds failed.");
175    }
176
177    KALUGA_DEBUG("Kaluga: ACPI connect...\n");
178    err = connect_to_acpi();
179    if (err_is_fail(err) && err != KALUGA_ERR_MODULE_NOT_FOUND) {
180        USER_PANIC_ERR(err, "start_lpc_timer");
181    }
182
183    KALUGA_DEBUG("Kaluga: pci_devices\n");
184
185    err = watch_for_pci_devices();
186    if (err_is_fail(err)) {
187        USER_PANIC_ERR(err, "Watching PCI devices.");
188    }
189
190    KALUGA_DEBUG("Kaluga: Starting serial...\n");
191    err = start_serial();
192    if (err_is_fail(err) && err != KALUGA_ERR_MODULE_NOT_FOUND) {
193        USER_PANIC_ERR(err, "start_serial");
194    }
195
196    KALUGA_DEBUG("Kaluga: Starting lpc timer...\n");
197    err = start_lpc_timer();
198    if (err_is_fail(err) && err != KALUGA_ERR_MODULE_NOT_FOUND) {
199        USER_PANIC_ERR(err, "start_lpc_timer");
200    }
201
202    return SYS_ERR_OK;
203}
204