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#include <barrelfish/barrelfish.h> 12#include "dma_mem.h" 13 14errval_t dma_mem_from_capref(struct capref frame, struct dma_mem *mem) 15{ 16 errval_t err = SYS_ERR_OK; 17 if (mem == NULL) { 18 return DMA_ERR_ARG_INVALID; 19 } 20 21 struct frame_identity id; 22 err = invoke_frame_identify(frame, &id); 23 if (err_is_fail(err)) { 24 DEBUG_ERR(err, "invoke frame id"); 25 return err; 26 } 27 28 mem->paddr = id.base; 29 mem->bytes = id.bytes; 30 mem->requested = id.bytes; 31 mem->frame = frame; 32 33 void *addr; 34 err = vspace_map_one_frame_attr(&addr, mem->bytes, mem->frame, VREGION_FLAGS_READ_WRITE, 35 NULL, NULL); 36 if (err_is_fail(err)) { 37 dma_mem_free(mem); 38 return err; 39 } 40 41 mem->vaddr = (lvaddr_t)addr; 42 43 return SYS_ERR_OK; 44} 45 46/** 47 * \brief allocates and maps a memory region to be used for DMA purposes 48 * 49 * \param bytes minimum size of the memory region in bytes 50 * \param flags VREGION flags how the region gets mapped 51 * \param mem returns the mapping information 52 * 53 * \returns SYS_ERR_OK on success 54 * errval on error 55 */ 56errval_t dma_mem_alloc(size_t bytes, struct dma_mem *mem) 57{ 58 errval_t err = SYS_ERR_OK; 59 mem->requested = bytes; 60 bytes = ROUND_UP(BASE_PAGE_SIZE, bytes); 61 62 if (mem == NULL) { 63 return DMA_ERR_ARG_INVALID; 64 } 65 66 err = frame_alloc(&mem->frame, bytes, &mem->bytes); 67 if (err_is_fail(err)) { 68 return err; 69 } 70 71 struct frame_identity id; 72 err = invoke_frame_identify(mem->frame, &id); 73 if (err_is_fail(err)) { 74 dma_mem_free(mem); 75 return err; 76 } 77 78 mem->paddr = id.base; 79 80 void *addr; 81 err = vspace_map_one_frame_attr(&addr, mem->bytes, mem->frame, VREGION_FLAGS_READ_WRITE, 82 NULL, NULL); 83 if (err_is_fail(err)) { 84 dma_mem_free(mem); 85 return err; 86 } 87 88 mem->vaddr = (lvaddr_t)addr; 89 90 return SYS_ERR_OK; 91} 92 93/** 94 * \brief tries to free the allocated memory region 95 * 96 * \returns SYS_ERR_OK on success 97 * errval on error 98 */ 99errval_t dma_mem_free(struct dma_mem *mem) 100{ 101 errval_t err; 102 103 if (mem->vaddr) { 104 err = vspace_unmap((void*)mem->vaddr); 105 if (err_is_fail(err)) { 106 USER_PANIC_ERR(err, "call failed."); 107 } 108 } 109 110 if (!capref_is_null(mem->frame)) { 111 err = cap_destroy(mem->frame); 112 if (err_is_fail(err)) { 113 if (err_is_fail(err)) { 114 USER_PANIC_ERR(err, "call failed."); 115 } 116 } 117 } 118 119 memset(mem, 0, sizeof(*mem)); 120 121 return SYS_ERR_OK; 122} 123