1/**
2 * \file
3 * \brief ACPI RPC Client
4 */
5
6/*
7 * Copyright (c) 2007, 2008, 2009, 2011, 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 <barrelfish/barrelfish.h>
16#include <barrelfish/caddr.h>
17#include <barrelfish/nameservice_client.h>
18
19#include <if/acpi_defs.h>
20#include <if/acpi_defs.h>
21
22#include <acpi_client/acpi_client.h>
23
24static struct acpi_connection {
25    bool is_done;
26    errval_t err;
27} state;
28
29static struct acpi_binding* binding;
30
31errval_t acpi_client_get_device_handle(const char *dev_id,
32                                       acpi_device_handle_t *ret_handle)
33{
34    assert(binding != NULL);
35    errval_t err, msgerr;
36    err = binding->rpc_tx_vtbl.get_handle(binding, dev_id, ret_handle, &msgerr);
37    return err_is_fail(err) ? err : msgerr;
38}
39
40errval_t acpi_client_eval_integer(acpi_device_handle_t handle,
41                                  const char *path, uint64_t *data)
42{
43    assert(binding != NULL);
44    errval_t err, msgerr;
45    err = binding->rpc_tx_vtbl.eval_integer(binding, handle, path, data, &msgerr);
46    return err_is_fail(err) ? err : msgerr;
47}
48
49
50errval_t acpi_reset(void)
51{
52    assert(binding != NULL);
53    errval_t err, msgerr;
54    err = binding->rpc_tx_vtbl.reset(binding, &msgerr);
55    return err_is_fail(err) ? err : msgerr;
56}
57
58errval_t acpi_sleep(int st)
59{
60    assert(binding != NULL);
61    errval_t err, msgerr;
62    err = binding->rpc_tx_vtbl.sleep(binding, st, &msgerr);
63    return err_is_fail(err) ? err : msgerr;
64}
65
66// Kludge for VBE driver
67errval_t acpi_get_vbe_bios_cap(struct capref *retcap, size_t *retsize)
68{
69    assert(binding != NULL);
70    errval_t err, msgerr;
71    assert(retcap != NULL);
72    assert(retsize != NULL);
73    uint32_t s;
74    err = slot_alloc(retcap);
75    if (err_is_fail(err)) {
76        return err;
77    }
78    err = binding->rpc_tx_vtbl.get_vbe_bios_cap(binding, &msgerr, retcap, &s);
79    *retsize = s;
80    return err_is_fail(err) ? err : msgerr;
81}
82
83errval_t vtd_create_domain(struct capref pml4)
84{
85    assert(binding != NULL);
86    errval_t err, msgerr;
87    err = binding->rpc_tx_vtbl.create_domain(binding, pml4, &msgerr);
88    return err_is_fail(err) ? err : msgerr;
89}
90
91errval_t vtd_delete_domain(struct capref pml4)
92{
93    assert(binding != NULL);
94    errval_t err, msgerr;
95    err = binding->rpc_tx_vtbl.delete_domain(binding, pml4, &msgerr);
96    return err_is_fail(err) ? err : msgerr;
97}
98
99errval_t vtd_domain_add_device(int seg, int bus, int dev, int func, struct capref pml4)
100{
101    assert(binding != NULL);
102    errval_t err, msgerr;
103    err = binding->rpc_tx_vtbl.vtd_add_device(binding, seg, bus, dev, func, pml4, &msgerr);
104    return err_is_fail(err) ? err : msgerr;
105}
106
107errval_t vtd_domain_remove_device(int seg, int bus, int dev, int func, struct capref pml4)
108{
109    assert(binding != NULL);
110    errval_t err, msgerr;
111    err = binding->rpc_tx_vtbl.vtd_remove_device(binding, seg, bus, dev, func, pml4, &msgerr);
112    return err_is_fail(err) ? err : msgerr;
113}
114
115errval_t vtd_add_devices(void)
116{
117    assert(binding != NULL);
118    errval_t err, msgerr;
119    err = binding->rpc_tx_vtbl.vtd_id_dom_add_devices(binding, &msgerr);
120    return err_is_fail(err) ? err : msgerr;
121}
122
123struct acpi_binding* get_acpi_binding(void)
124{
125    assert(binding != NULL);
126    return binding;
127}
128
129static void rpc_bind_cb(void *st, errval_t err, struct acpi_binding* b)
130{
131    if (err_is_ok(err)) {
132        binding = b;
133        acpi_rpc_client_init(binding);
134    } // else: Do nothing
135
136    assert(!state.is_done);
137    state.is_done = true;
138    state.err = err;
139}
140
141errval_t connect_to_acpi(void)
142{
143    errval_t err;
144    iref_t iref;
145
146    err = nameservice_blocking_lookup("acpi", &iref);
147    if (err_is_fail(err)) {
148        return err;
149    }
150
151    state.is_done = false;
152    err = acpi_bind(iref, rpc_bind_cb, NULL, get_default_waitset(),
153            IDC_BIND_FLAGS_DEFAULT);
154    if (err_is_fail(err)) {
155        return err_push(err, FLOUNDER_ERR_BIND);
156    }
157
158    //  Wait for callback to complete
159    while (!state.is_done) {
160        messages_wait_and_handle_next();
161    }
162
163    return state.err;
164
165}
166