1/**
2 * \file
3 * \brief PCI
4 */
5
6/*
7 * Copyright (c) 2007, 2008, 2009, 2011, 2014, 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 <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18
19#include <barrelfish/barrelfish.h>
20#include <barrelfish/nameservice_client.h>
21
22#include <if/monitor_blocking_defs.h>
23
24#include <mm/mm.h>
25#include <octopus/init.h>
26#include <skb/skb.h>
27#include <acpi_client/acpi_client.h>
28#include <int_route/int_route_server.h>
29#include <int_route/int_route_debug.h>
30
31#include "pci.h"
32#include "pci_debug.h"
33#include "pci_int_ctrl.h"
34
35#if !defined(__ARM_ARCH_8A__)
36static errval_t init_io_ports(void)
37{
38    errval_t err;
39
40    struct monitor_blocking_binding *cl = get_monitor_blocking_binding();
41    assert(cl != NULL);
42
43    // Request I/O Cap
44    struct capref requested_caps;
45    errval_t error_code;
46    err = slot_alloc(&requested_caps);
47    assert(err_is_ok(err));
48    err = cl->rpc_tx_vtbl.get_io_cap(cl, &requested_caps, &error_code);
49    assert(err_is_ok(err) && err_is_ok(error_code));
50
51    // Copy into correct slot
52    struct capref caps_io = {
53        .cnode = cnode_task,
54        .slot  = TASKCN_SLOT_IO
55    };
56    err = cap_copy(caps_io, requested_caps);
57
58    return SYS_ERR_OK;
59}
60#endif
61
62int main(int argc, char *argv[])
63{
64    errval_t err;
65
66    // Parse commandline arguments
67    for(int i = 1; i < argc; i++) {
68        if(!strncmp(argv[i], "skb_bridge_program=", strlen("skb_bridge_program="))) {
69            skb_bridge_program = argv[i] + strlen("skb_bridge_program=");
70        } else if(!strncmp(argv[i], "numvfs=", strlen("numvfs="))) {
71            max_numvfs = atoi(argv[i] + strlen("numvfs="));
72            enable_vfs = true;
73        } else {
74            printf("%s: Unknown commandline option \"%s\" -- skipping.\n", argv[0], argv[i]);
75        }
76    }
77
78    PCI_DEBUG("oct_init.\n");
79    err = oct_init();
80    if (err_is_fail(err)) {
81    	USER_PANIC_ERR(err, "dist initialization failed.");
82    }
83
84    PCI_DEBUG("skb_client_connect.\n");
85    err = skb_client_connect();
86    if (err_is_fail(err)) {
87    	USER_PANIC_ERR(err, "Connecting to SKB failed.");
88    }
89
90    PCI_DEBUG("int_route_service_init.\n");
91    err = int_route_service_init();
92    if (err_is_fail(err)) {
93        DEBUG_ERR(err, "int_route_service_init failed");
94        abort();
95    }
96
97    PCI_DEBUG("connect_to_acpi.\n");
98    err = connect_to_acpi();
99    if (err_is_fail(err)) {
100        USER_PANIC_ERR(err, "ACPI Connection failed.");
101    }
102
103#if !defined(__ARM_ARCH_8A__)
104    err = init_io_ports();
105    if (err_is_fail(err)) {
106    	USER_PANIC_ERR(err, "Init memory allocator failed.");
107    }
108#endif
109
110    err = pcie_setup_confspace();
111    if (err_is_fail(err)) {
112        if (err_no(err) == ACPI_ERR_NO_MCFG_TABLE) {
113            PCI_DEBUG("No PCIe found, continue.\n");
114        }
115        else {
116            USER_PANIC_ERR(err, "Setup PCIe confspace failed.");
117        }
118    }
119
120    err = pci_setup_root_complex();
121    if (err_is_fail(err)) {
122    	USER_PANIC_ERR(err, "Setup PCI root complex failed.");
123    }
124
125    err = pci_int_ctrl_init();
126    if (err_is_fail(err)) {
127    	USER_PANIC_ERR(err, "Initializing pci_int_ctrl failed");
128    }
129
130
131    // Start configuring PCI
132    PCI_DEBUG("Programming PCI BARs and bridge windows\n");
133    pci_program_bridges();
134    PCI_DEBUG("PCI programming completed\n");
135    pci_init_datastructures();
136    pci_init();
137
138
139#if 0 // defined(PCI_SERVICE_DEBUG) || defined(GLOBAL_DEBUG)
140//output all the facts stored in the SKB to produce a sample data file to use
141//for debugging on linux
142    skb_execute("listing.");
143    while (skb_read_error_code() == SKB_PROCESSING) messages_wait_and_handle_next();
144    PCI_DEBUG("\nSKB returned: \n%s\n", skb_get_output());
145    const char *errout = skb_get_error_output();
146    if (errout != NULL && *errout != '\0') {
147        PCI_DEBUG("\nSKB error returned: \n%s\n", errout);
148    }
149#endif
150
151    skb_add_fact("pci_discovery_done.");
152
153    /* Using the name server as a lock server,
154       register a service with it so that other domains can do a blocking wait
155       on pci to finish enumeration */
156    err = nameservice_register("pci_discovery_done", 0);
157    if (err_is_fail(err)) {
158        DEBUG_ERR(err, "nameservice_register failed");
159        abort();
160    }
161
162    err = vtd_add_devices();
163    if (err_is_fail(err)) {
164        DEBUG_ERR(err, "vtd_add_devices failed");
165        abort();
166    }
167
168    messages_handler_loop();
169}
170