1/* 2 * Copyright (c) 2014, ETH Zurich. All rights reserved. 3 * 4 * This file is distributed under the terms in the attached LICENSE file. 5 * If you do not find this file, copies can be found by writing to: 6 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group. 7 */ 8/* 9 * 10 * 11 */ 12#include <stdio.h> 13#include <string.h> 14 15#include <barrelfish/barrelfish.h> 16 17#include <dma/dma_manager_client.h> 18 19#include "dma_mgr.h" 20#include "debug.h" 21 22struct dma_service 23{ 24 struct dma_mgr_driver_info info; 25 struct dma_service *prev; 26 struct dma_service *next; 27}; 28 29static struct dma_service *dma_services = NULL; 30 31static void service_insert(struct dma_service *svc) 32{ 33 if (dma_services == NULL) { 34 svc->next = NULL; 35 svc->prev = NULL; 36 dma_services = svc; 37 return; 38 } 39 40 struct dma_service *current = dma_services; 41 while (current) { 42 if (current->info.mem_low > svc->info.mem_low) { 43 if (current->prev) { 44 svc->prev = current->prev; 45 current->prev->next = svc; 46 } else { 47 svc->prev = NULL; 48 dma_services = svc; 49 } 50 svc->next = current; 51 current->prev = svc; 52 break; 53 } 54 if (current->next == NULL) { 55 current->next = svc; 56 svc->prev = current; 57 break; 58 } 59 current = current->next; 60 } 61} 62 63static inline uint8_t get_diff(uint8_t a, 64 uint8_t b) 65{ 66 if (a > b) { 67 return a - b; 68 } else { 69 return b - a; 70 } 71} 72 73static struct dma_service *service_lookup(lpaddr_t mem_low, 74 size_t size, 75 uint8_t numa_node) 76{ 77 78 struct dma_service *current = dma_services; 79 struct dma_service *best = NULL; 80 while (current) { 81 if (current->info.mem_low <= mem_low) { 82 if (current->info.mem_high >= (mem_low + size)) { 83 /* we have a match */ 84 if (best == NULL) { 85 best = current; 86 } else { 87 uint8_t best_numa_diff = get_diff(numa_node, 88 best->info.numa_node); 89 uint8_t curr_numa_diff = get_diff(numa_node, 90 current->info.numa_node); 91 if (curr_numa_diff < best_numa_diff) { 92 best = current; 93 } 94 } 95 } 96 } 97 current = current->next; 98 } 99 return best; 100} 101 102static struct dma_service *service_lookup_iref(iref_t iref) 103{ 104 struct dma_service *current = dma_services; 105 while(current) { 106 if (current->info.iref == iref) { 107 return current; 108 } 109 current = current->next; 110 } 111 return NULL; 112} 113 114/* 115 * ============================================================================ 116 * 117 * ============================================================================ 118 */ 119 120errval_t driver_store_init(void) 121{ 122 return SYS_ERR_OK; 123} 124 125errval_t driver_store_insert(lpaddr_t mem_low, 126 lpaddr_t mem_high, 127 uint8_t numa_node, 128 uint8_t type, 129 iref_t iref) 130{ 131 struct dma_service *driver = calloc(1, sizeof(*driver)); 132 if (driver == NULL) { 133 return LIB_ERR_MALLOC_FAIL; 134 } 135 136 DS_DEBUG("insert: {%016lx, %016lx, %u, %u} @ %x\n", mem_low, mem_high, numa_node, 137 type, iref); 138 139 driver->info.mem_low = mem_low; 140 driver->info.mem_high = mem_high; 141 driver->info.numa_node = numa_node; 142 driver->info.type = type; 143 driver->info.iref = iref; 144 145 service_insert(driver); 146 147 return SYS_ERR_OK; 148} 149 150errval_t driver_store_lookup_by_iref(iref_t iref, 151 struct dma_mgr_driver_info **info) 152{ 153 DS_DEBUG("lookup: iref:%"PRIxIREF"\n", iref); 154 155 struct dma_service *svc = service_lookup_iref(iref); 156 if (svc == NULL) { 157 DS_DEBUG("no such service: iref:%"PRIxIREF"\n", iref); 158 return DMA_ERR_SVC_VOID; 159 } 160 161 *info = &svc->info; 162 163 return SYS_ERR_OK; 164} 165 166errval_t driver_store_lookup(lpaddr_t mem_low, 167 size_t size, 168 uint8_t numa_node, 169 struct dma_mgr_driver_info **info) 170{ 171 172 DS_DEBUG("lookup: {%016lx, %016lx, %u}\n", mem_low, size, numa_node); 173 174 struct dma_service *svc = service_lookup(mem_low, size, numa_node); 175 if (svc == NULL) { 176 return DMA_ERR_SVC_VOID; 177 } 178 179 DS_DEBUG("lookup: {%016lx, %016lx, %u} @ %x\n", mem_low, size, numa_node, 180 svc->info.iref); 181 182 *info = &svc->info; 183 184 return SYS_ERR_OK; 185} 186