1/** 2 * \file 3 * \brief Code responsible for starting devices discovered from decoding nets 4 */ 5 6/* 7 * Copyright (c) 2016 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, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <barrelfish/barrelfish.h> 16 17#include <skb/skb.h> 18 19#include <if/octopus_defs.h> 20 21#include <octopus/getset.h> 22#include <octopus/trigger.h> 23 24#include <maps/omap44xx_map.h> 25#include <arch/arm/omap44xx/device_registers.h> 26 27#include <bitmacros.h> 28 29#include "kaluga.h" 30 31#define DRIVER_CORE 0 32 33static void start_driver_for_device(struct domain_instance *inst, char* device) { 34 35 errval_t err = skb_execute_query("find_dn_driver('%s',R),write(R)", device); 36 if (err == SKB_ERR_EXECUTION) { 37 KALUGA_DEBUG("No driver found for device %s\n", device); 38 return; 39 } else if (err_is_fail(err)) { 40 DEBUG_SKB_ERR(err, "Getting driver info"); 41 return; 42 } 43 // Save driver info for later 44 char *driver_info = strdup(skb_get_output()); 45 46 char *name = malloc(strlen(driver_info)); 47 int start_on_discovery = 0; 48 err = skb_read_output_at(driver_info, "driver(%[^,],%d", name, &start_on_discovery); 49 if (err_is_fail(err)) { 50 USER_PANIC_SKB_ERR(err, "SKB parse error while getting driver info."); 51 } 52 else if (!start_on_discovery && inst == NULL) { 53 KALUGA_DEBUG("Driver start deferred until other driver depends on it.\n"); 54 goto out; 55 } 56 KALUGA_DEBUG("Driver module name: %s\n", name); 57 58 if (inst == NULL) { 59 // XXX: for now we start all drivers on core 0 60 inst = instantiate_driver_domain(DRIVER_CORE); 61 } 62 63 struct driver_instance *drv = ddomain_create_driver_instance(name, name); 64 65 // Start driver dependencies 66 struct list_parser_status status; 67 skb_read_list_init_offset(&status, driver_info, 0); 68 69 char *dep = malloc(strlen(driver_info)); 70 71 while(skb_read_list(&status, "drv_dep(%[^)]", dep)) { 72 KALUGA_DEBUG("Driver %s dependency %s\n", name, dep); 73 start_driver_for_device(inst, dep); 74 } 75 free(dep); 76 77 // Give memory caps to driver by using decoding net 78 err = skb_execute_query("dn_driver{module:\"%s\",device_regions:D}," 79 "driver_register_regions(%d,D,R),write(R)", name, DRIVER_CORE); 80 if (err_is_fail(err)) { 81 USER_PANIC_SKB_ERR(err, "Could not get device regions"); 82 } 83 KALUGA_DEBUG("Register region list %s\n", skb_get_output()); 84 85 lpaddr_t addr, size; 86 87 skb_read_list_init(&status); 88 while(skb_read_list(&status, "reg(%" SCNuLPADDR",%" SCNuLPADDR ")", &addr, &size)) { 89 KALUGA_DEBUG("Get cap for registers: %"PRIxLPADDR", %"PRIxLPADDR"\n", addr, size); 90 91 struct capref device_frame; 92 err = get_device_cap(ROUND_DOWN(addr, BASE_PAGE_SIZE), ROUND_UP(size, BASE_PAGE_SIZE), &device_frame); 93 assert(err_is_ok(err)); 94 95 KALUGA_DEBUG("get_device_cap worked\n"); 96 err = ddomain_driver_add_cap(drv, device_frame); 97 } 98 99 // Give interrupt source caps to driver by using decoding net 100 err = skb_execute_query("dn_driver{module:\"%s\",device_interrupts:Ids}," 101 "driver_interrupt_enum(Ids,I),write(I)", name); 102 KALUGA_DEBUG("Interrupt enum list %s\n", skb_get_output()); 103 104 skb_read_list_init(&status); 105 uint32_t base, limit; 106 while(skb_read_list(&status, "int(%d,%d)", &base, &limit)) { 107 KALUGA_DEBUG("Get interrupt cap for range: base=%"PRIu32", " 108 "limit=%"PRIu32"\n", base, limit); 109 } 110 111 ddomain_instantiate_driver(inst, drv); 112 113 KALUGA_DEBUG("Driver %s started\n", name); 114 115 out: 116 free(name); 117 free(driver_info); 118} 119 120static void decnet_change_event(octopus_mode_t mode, const char* device_record, 121 void* st) 122{ 123 KALUGA_DEBUG("Decoding net record: %s\n", device_record); 124 125 if (mode & OCT_ON_SET) { 126 char *device = NULL; 127 128 errval_t err = oct_read(device_record, "_ { device: %s }", &device); 129 if (err_is_fail(err)) { 130 USER_PANIC_ERR(err, "Got malformed device record?"); 131 } 132 133 KALUGA_DEBUG("Found decoding net device %s\n", device); 134 135 start_driver_for_device(NULL, device); 136 } 137} 138 139errval_t watch_for_decnet_devices(void) 140{ 141 static char* decnet_device = "r'hw\\.dn\\.device\\.[0-9]+' { " 142 " device: _ }"; 143 octopus_trigger_id_t tid; 144 return oct_trigger_existing_and_watch(decnet_device, decnet_change_event, NULL, &tid); 145} 146