1/* 2 * Copyright (c) 2014 ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10#include <string.h> 11 12#include <barrelfish/barrelfish.h> 13 14#include <dma_internal.h> 15#include <dma_mem_utils.h> 16#include <driverkit/iommu.h> 17 18static lvaddr_t addr_start = (256UL << 30); 19 20/** 21 * \brief allocates and maps a memory region to be used for DMA purposes 22 * 23 * \param bytes minimum size of the memory region in bytes 24 * \param flags VREGION flags how the region gets mapped 25 * \param cl IOMMU client if IOMMU is present 26 * \param mem returns the mapping information 27 * 28 * \returns SYS_ERR_OK on success 29 * errval on error 30 */ 31errval_t dma_mem_alloc(size_t bytes, 32 vregion_flags_t flags, 33 struct iommu_client *cl, 34 struct dmem *mem) 35{ 36 // TODO might also include allocation with IOMMU present 37 errval_t err; 38 39 if (mem == NULL) { 40 return DMA_ERR_ARG_INVALID; 41 } 42 43 if (cl != NULL) { 44 err = driverkit_iommu_mmap_cl(cl, bytes, flags, mem); 45 return err; 46 } 47 48 uint64_t base, limit; 49 ram_get_affinity(&base, &limit); 50 ram_set_affinity(4UL << 30, 128UL << 32); 51 err = frame_alloc(&mem->mem, bytes, &mem->size); 52 if (err_is_fail(err)) { 53 return err; 54 } 55 ram_set_affinity(base, limit); 56 57 struct frame_identity id; 58 err = frame_identify(mem->mem, &id); 59 if (err_is_fail(err)) { 60 dma_mem_free(mem); 61 return err; 62 } 63 64 mem->devaddr = id.base; 65 66 67 void *addr; 68 err = vspace_map_one_frame_fixed_attr(addr_start, mem->size, mem->mem, flags, NULL, 69 NULL); 70 if (err_is_fail(err)) { 71 dma_mem_free(mem); 72 return err; 73 } 74 75 addr = (void *)addr_start; 76 addr_start += mem->size; 77 78 mem->vbase = (lvaddr_t)addr; 79 80 return SYS_ERR_OK; 81} 82 83/** 84 * \brief tries to free the allocated memory region 85 * 86 * \returns SYS_ERR_OK on success 87 * errval on error 88 */ 89errval_t dma_mem_free(struct dmem *mem) 90{ 91 errval_t err; 92 93 if (mem->vbase) { 94 err = vspace_unmap((void*)mem->vbase); 95 if (err_is_fail(err)) { 96 /* todo: error handling ignoring for now */ 97 } 98 } 99 100 if (!capref_is_null(mem->mem)) { 101 err = cap_destroy(mem->mem); 102 if (err_is_fail(err)) { 103 /* todo: error handling ignoring for now */ 104 105 } 106 } 107 108 memset(mem, 0, sizeof(*mem)); 109 110 return SYS_ERR_OK; 111} 112 113