3 * \brief ACPI daemon Flounder handler functions
7 * Copyright (c) 2007, 2008, 2009, 2011, 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.
16 #include <barrelfish/barrelfish.h>
17 #include <barrelfish/nameservice_client.h>
18 #include <if/acpi_defs.h>
21 #include "acpi_shared.h"
22 #include "acpi_debug.h"
25 # include "intel_vtd.h"
29 // XXX: proper cap handling (del etc.)
30 static void mm_alloc_range_proxy_handler(struct acpi_binding* b, uint8_t sizebits,
31 genpaddr_t minbase, genpaddr_t maxlimit)
33 ACPI_DEBUG("mm_alloc_range_proxy_handler: sizebits: %d, minbase: 0x%lx maxlimit: 0x%lx\n",
34 sizebits, minbase, maxlimit);
36 struct capref devframe = NULL_CAP;
37 /* errval_t err = mm_alloc_range(&pci_mm_physaddr, sizebits, minbase, maxlimit, &devframe, NULL); */
38 errval_t err = mm_realloc_range(&pci_mm_physaddr, sizebits, minbase, &devframe);
39 if (err_is_fail(err)) {
40 DEBUG_ERR(err, "mm realloc range failed...\n");
43 err = b->tx_vtbl.mm_alloc_range_proxy_response(b, NOP_CONT, devframe, err);
44 assert(err_is_ok(err));
47 static void mm_realloc_range_proxy_handler(struct acpi_binding* b, uint8_t sizebits,
50 ACPI_DEBUG("mm_realloc_range_proxy_handler: sizebits: %d, "
51 "minbase: 0x%"PRIxGENPADDR"\n",
54 struct capref devframe = NULL_CAP;
55 errval_t err = mm_realloc_range(&pci_mm_physaddr, sizebits, minbase, &devframe);
56 if (err_is_fail(err)) {
57 DEBUG_ERR(err, "mm alloc range failed...\n");
60 err = b->tx_vtbl.mm_realloc_range_proxy_response(b, NOP_CONT, devframe, err);
61 assert(err_is_ok(err));
64 // XXX: proper cap handling
65 static void mm_free_proxy_handler(struct acpi_binding* b, struct capref devframe,
66 uint64_t base, uint8_t sizebits)
68 ACPI_DEBUG("mm_free_proxy_handler: base: 0x%"PRIx64", sizebits: %d\n", base, sizebits);
70 errval_t err = mm_free(&pci_mm_physaddr, devframe, base, sizebits);
71 if (err_is_fail(err)) {
72 DEBUG_ERR(err, "mm free failed...\n");
75 err = b->tx_vtbl.mm_free_proxy_response(b, NOP_CONT, err);
76 assert(err_is_ok(err));
79 static void enable_interrupt_handler(struct acpi_binding* b, uint32_t gsi,
80 coreid_t dest, uint32_t vector)
82 errval_t err = SYS_ERR_OK;
83 err = enable_and_route_interrupt(gsi, dest, vector);
85 err = b->tx_vtbl.enable_and_route_interrupt_response(b, NOP_CONT, err);
86 assert(err_is_ok(err));
90 static inline bool mcfg_correct_length(uint32_t header_len)
93 sizeof(ACPI_TABLE_MCFG) + sizeof(ACPI_MCFG_ALLOCATION);
96 static void get_pcie_confspace(struct acpi_binding* b)
98 ACPI_DEBUG("get_pcie_confspace\n");
102 ACPI_TABLE_HEADER *mcfg_header;
104 as = AcpiGetTable("MCFG", 1, &mcfg_header);
105 if (ACPI_SUCCESS(as) && mcfg_correct_length(mcfg_header->Length)) {
107 ACPI_MCFG_ALLOCATION *mcfg = (void*) mcfg_header
108 + sizeof(ACPI_TABLE_MCFG);
110 "PCIe enhanced configuration region at 0x%"PRIx64" "
111 "(segment %u, buses %u-%u)\n", mcfg->Address,
112 mcfg->PciSegment, mcfg->StartBusNumber, mcfg->EndBusNumber);
114 err = b->tx_vtbl.get_pcie_confspace_response(b, NOP_CONT, SYS_ERR_OK,
115 mcfg->Address, mcfg->PciSegment, mcfg->StartBusNumber,
119 ACPI_DEBUG("No MCFG table found -> no PCIe enhanced configuration\n");
120 err = b->tx_vtbl.get_pcie_confspace_response(b, NOP_CONT,
121 ACPI_ERR_NO_MCFG_TABLE, 0, 0, 0, 0);
124 assert(err_is_ok(err));
127 static void get_path_name(ACPI_HANDLE handle, char* name, size_t len)
129 ACPI_BUFFER buf = { .Length = len, .Pointer = name };
132 s = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf);
133 assert(ACPI_SUCCESS(s));
136 static void read_irq_table(struct acpi_binding* b, const char* pathname,
137 acpi_pci_address_t addr, uint8_t bus)
139 ACPI_DEBUG("read_irq_table: (parent)%s, (%"PRIu8",%"PRIu8",%"PRIu8"), %"PRIu8"\n",
140 pathname == NULL ? "NULL" : pathname, addr.bus, addr.device, addr.function, bus);
146 as = AcpiGetHandle(NULL, (CONST_CAST)pathname, &handle);
147 if (ACPI_SUCCESS(as)) {
149 err = acpi_get_irqtable_device(handle, addr, &child, bus);
151 if(err_is_fail(err)){
152 ACPI_DEBUG("get_irq_table failed.\n");
153 err = b->tx_vtbl.read_irq_table_response(b, NOP_CONT, err, NULL);
154 assert(err_is_ok(err));
157 get_path_name(child, name, 128);
158 ACPI_DEBUG("Sending back path name: %s\n", name);
160 err = b->tx_vtbl.read_irq_table_response(b, NOP_CONT, SYS_ERR_OK, name);
161 assert(err_is_ok(err));
165 ACPI_DEBUG("Unknown ACPI Handle for path: %s\n", pathname);
166 err = b->tx_vtbl.read_irq_table_response(b, NOP_CONT,
167 ACPI_ERR_INVALID_PATH_NAME, NULL);
168 assert(err_is_ok(err));
174 static void set_device_irq_handler(struct acpi_binding *b, const char* device, uint32_t irq)
176 errval_t err = set_device_irq(device,irq);
177 err = b->tx_vtbl.set_device_irq_response(b, NOP_CONT, err);
178 assert(err_is_ok(err));
181 static void reset_handler(struct acpi_binding *b)
183 if (AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) {
184 printf("Resetting machine via ACPI...\n");
185 ACPI_STATUS as = AcpiReset();
186 if (ACPI_FAILURE(as)) {
187 printf("ACPI reset failed\n");
191 printf("Resetting machine via syscall...\n");
192 errval_t err = sys_reboot();
193 if (err_is_fail(err)) {
194 DEBUG_ERR(err, "reboot syscall failed");
198 static void sleep_handler(struct acpi_binding *b, uint32_t state)
200 printf("Entering S%"PRIu32" sleep state via ACPI...\n", state);
201 ACPI_STATUS as = AcpiEnterSleepStatePrep(state);
202 if (!ACPI_SUCCESS(as)) {
203 printf("AcpiEnterSleepStatePrep failed\n");
207 as = AcpiEnterSleepState(state);
208 if (!ACPI_SUCCESS(as)) {
209 printf("AcpiEnterSleepState failed\n");
215 ACPI_STATUS get_handle_handler_callback(
219 void **ReturnValue) {
222 ACPI_DEVICE_INFO *device_info;
223 as = AcpiGetObjectInfo(Object, &device_info);
224 if (ACPI_FAILURE(as)) {
225 debug_printf("AcpiGetObjectInfo failed: %x\n", as);
229 if (device_info->HardwareId.Length &&
230 !strncmp(device_info->HardwareId.String, Context, device_info->HardwareId.Length)) {
231 debug_printf("device HardwareId=%s UniqueId=%s\n", device_info->HardwareId.String, device_info->UniqueId.String);
232 *ReturnValue = Object;
234 ACPI_FREE(device_info);
238 static void get_handle_handler(struct acpi_binding *b, const char *dev_id)
240 errval_t err = SYS_ERR_OK;;
242 debug_printf("Looking up handle for device '%s'\n", dev_id);
245 ACPI_HANDLE handle = NULL;
247 s = AcpiGetDevices(NULL, get_handle_handler_callback, (CONST_CAST)dev_id, &handle);
248 if (ACPI_FAILURE(s)) {
249 debug_printf("Looking up handle failed: %d\n", s);
250 err = ACPI_ERR_INVALID_HANDLE;
251 } else if (handle == NULL) {
252 err = ACPI_ERR_OBJECT_NOT_FOUND;
255 //out uint64 handle, out errval err
256 err = b->tx_vtbl.get_handle_response(b, NOP_CONT, (uint64_t)handle, err);
257 assert(err_is_ok(err));
260 static void eval_integer_handler(struct acpi_binding *b,
261 uint64_t handle, const char *path)
263 errval_t err = SYS_ERR_OK;
266 ACPI_INTEGER val = 0;
267 s = acpi_eval_integer((ACPI_HANDLE)handle, path, &val);
268 if (ACPI_FAILURE(s)) {
269 if (s == AE_BAD_PATHNAME) {
270 err = ACPI_ERR_INVALID_PATH_NAME;
272 err = ACPI_ERR_INVALID_HANDLE;
277 debug_printf("eval_integer_handler\n");
278 err = b->tx_vtbl.eval_integer_response(b, NOP_CONT, val, err);
282 struct acpi_rx_vtbl acpi_rx_vtbl = {
283 .get_pcie_confspace_call = get_pcie_confspace,
284 .read_irq_table_call = read_irq_table,
285 .set_device_irq_call = set_device_irq_handler,
286 .enable_and_route_interrupt_call = enable_interrupt_handler,
288 .get_handle_call = get_handle_handler,
289 .eval_integer_call = eval_integer_handler,
291 .mm_alloc_range_proxy_call = mm_alloc_range_proxy_handler,
292 .mm_realloc_range_proxy_call = mm_realloc_range_proxy_handler,
293 .mm_free_proxy_call = mm_free_proxy_handler,
295 .reset_call = reset_handler,
296 .sleep_call = sleep_handler,
299 static void export_callback(void *st, errval_t err, iref_t iref)
301 assert(err_is_ok(err));
303 err = nameservice_register("acpi", iref);
304 if (err_is_fail(err)) {
305 USER_PANIC_ERR(err, "nameservice_register failed");
307 ACPI_DEBUG("acpi service exported\n");
310 static errval_t connect_callback(void *cst, struct acpi_binding *b)
312 ACPI_DEBUG("acpi service get connection\n");
313 b->rx_vtbl = acpi_rx_vtbl;
319 void start_service(void)
321 ACPI_DEBUG("start_service\n");
323 acpi_service_arch_init(&acpi_rx_vtbl);
325 errval_t r = acpi_export(NULL, export_callback, connect_callback,
326 get_default_waitset(), IDC_EXPORT_FLAGS_DEFAULT);
327 assert(err_is_ok(r));
329 ACPI_DEBUG("start_service: terminated\n");